@inweb/viewer-three 27.2.1 → 27.2.2

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.
@@ -23,7 +23,7 @@
23
23
 
24
24
  import { draggersRegistry, commandsRegistry, Options, componentsRegistry, Info, Loader, loadersRegistry, CANVAS_EVENTS } from '@inweb/viewer-core';
25
25
  export * from '@inweb/viewer-core';
26
- import { Line, Vector3, BufferGeometry, Float32BufferAttribute, LineBasicMaterial, Mesh, MeshBasicMaterial, DoubleSide, EventDispatcher, MOUSE, TOUCH, Spherical, Quaternion, Vector2, Plane, Object3D, Line3, Raycaster, MathUtils, EdgesGeometry, Matrix4, Vector4, Controls, Clock, Box3, Color, PerspectiveCamera, OrthographicCamera, AmbientLight, DirectionalLight, HemisphereLight, REVISION, MeshPhongMaterial, WebGLRenderTarget, UnsignedByteType, RGBAFormat, CylinderGeometry, Sprite, CanvasTexture, SRGBColorSpace, SpriteMaterial, TextureLoader, BufferAttribute, PointsMaterial, Points, TriangleStripDrawMode, TriangleFanDrawMode, LineSegments, LineLoop, Group, NormalBlending, LoadingManager, LoaderUtils, FileLoader, UniformsUtils, ShaderMaterial, AdditiveBlending, HalfFloatType, Scene, WebGLRenderer, LinearSRGBColorSpace } from 'three';
26
+ import { Line, BufferGeometry, Float32BufferAttribute, LineBasicMaterial, Mesh, MeshBasicMaterial, DoubleSide, EventDispatcher, Vector3, MOUSE, TOUCH, Spherical, Quaternion, Vector2, Plane, Object3D, Line3, Raycaster, MathUtils, EdgesGeometry, Matrix4, Vector4, Controls, Box3, Clock, Color, PerspectiveCamera, OrthographicCamera, AmbientLight, DirectionalLight, HemisphereLight, REVISION, MeshPhongMaterial, WebGLRenderTarget, UnsignedByteType, RGBAFormat, CylinderGeometry, Sprite, CanvasTexture, SRGBColorSpace, SpriteMaterial, TextureLoader, BufferAttribute, PointsMaterial, Points, TriangleStripDrawMode, TriangleFanDrawMode, LineSegments, LineLoop, Group, NormalBlending, LoadingManager, LoaderUtils, FileLoader, UniformsUtils, ShaderMaterial, AdditiveBlending, HalfFloatType, Scene, WebGLRenderer, LinearSRGBColorSpace } from 'three';
27
27
  import { TransformControls } from 'three/examples/jsm/controls/TransformControls.js';
28
28
  import { LineSegmentsGeometry } from 'three/examples/jsm/lines/LineSegmentsGeometry.js';
29
29
  import { Wireframe } from 'three/examples/jsm/lines/Wireframe.js';
@@ -41,17 +41,15 @@ import { EventEmitter2 } from '@inweb/eventemitter2';
41
41
  import { Markup } from '@inweb/markup';
42
42
  export * from '@inweb/markup';
43
43
 
44
- class PlaneHelper extends Line {
45
- constructor(plane, size = 1, color = 0xffff00, offset = new Vector3()) {
44
+ class PlaneHelper2 extends Line {
45
+ constructor(size = 1, color = 0xc0c0c0) {
46
46
  const positions = [1, 1, 0, -1, 1, 0, -1, -1, 0, 1, -1, 0, 1, 1, 0];
47
47
  const geometry = new BufferGeometry();
48
48
  geometry.setAttribute("position", new Float32BufferAttribute(positions, 3));
49
49
  geometry.computeBoundingSphere();
50
50
  super(geometry, new LineBasicMaterial({ color, toneMapped: false }));
51
- this.type = "PlaneHelper";
52
- this.plane = plane;
51
+ this.type = "PlaneHelper2";
53
52
  this.size = size;
54
- this.offset = offset;
55
53
  const positions2 = [1, 1, 0, -1, 1, 0, -1, -1, 0, 1, 1, 0, -1, -1, 0, 1, -1, 0];
56
54
  const geometry2 = new BufferGeometry();
57
55
  geometry2.setAttribute("position", new Float32BufferAttribute(positions2, 3));
@@ -69,14 +67,10 @@ class PlaneHelper extends Line {
69
67
  dispose() {
70
68
  this.geometry.dispose();
71
69
  this.material.dispose();
72
- this.children[0].geometry.dispose();
73
- this.children[0].material.dispose();
70
+ this.helper.geometry.dispose();
71
+ this.helper.material.dispose();
74
72
  }
75
73
  updateMatrixWorld(force) {
76
- this.position.set(0, 0, 0);
77
- this.lookAt(this.plane.normal);
78
- this.position.copy(this.offset);
79
- this.translateZ(-(this.offset.dot(this.plane.normal) + this.plane.constant));
80
74
  this.scale.set(0.5 * this.size, 0.5 * this.size, 1);
81
75
  super.updateMatrixWorld(force);
82
76
  }
@@ -832,26 +826,41 @@ class OrbitDragger {
832
826
  }
833
827
 
834
828
  class CuttingPlaneDragger extends OrbitDragger {
835
- constructor(viewer, normal, color) {
829
+ constructor(viewer, normal) {
836
830
  super(viewer);
837
831
  this.transformChange = () => {
832
+ this.plane.normal.copy(new Vector3(0, 0, -1)).applyQuaternion(this.planeCenter.quaternion);
838
833
  this.plane.constant = -this.planeCenter.position.dot(this.plane.normal);
839
834
  this.viewer.update();
840
835
  };
841
- this.transformDrag = (event) => {
836
+ this.translateDrag = (event) => {
842
837
  this.orbit.enabled = !event.value;
838
+ this.rotate.enabled = !event.value;
839
+ };
840
+ this.rotateDrag = (event) => {
841
+ this.orbit.enabled = !event.value;
842
+ this.translate.enabled = !event.value;
843
843
  };
844
844
  this.updatePlaneSize = () => {
845
845
  this.planeHelper.size = this.viewer.extents.getSize(new Vector3()).length() || 1;
846
846
  this.viewer.update();
847
847
  };
848
848
  this.updateTransformCamera = () => {
849
- this.transform.camera = this.viewer.camera;
849
+ this.translate.camera = this.viewer.camera;
850
+ this.rotate.camera = this.viewer.camera;
851
+ };
852
+ this.onKeyDown = (event) => {
853
+ if (event.key === "Shift")
854
+ this.rotate.setRotationSnap(Math.PI / 4);
855
+ };
856
+ this.onKeyUp = (event) => {
857
+ if (event.key === "Shift")
858
+ this.rotate.setRotationSnap(null);
850
859
  };
851
860
  this.onDoubleClick = (event) => {
852
861
  event.stopPropagation();
853
- this.plane.negate();
854
- this.viewer.update();
862
+ this.planeCenter.rotateOnAxis(new Vector3(0, 1, 0), Math.PI);
863
+ this.transformChange();
855
864
  };
856
865
  const extentsSize = viewer.extents.getSize(new Vector3()).length() || 1;
857
866
  const extentsCenter = viewer.extents.getCenter(new Vector3());
@@ -860,24 +869,38 @@ class CuttingPlaneDragger extends OrbitDragger {
860
869
  if (!viewer.renderer.clippingPlanes)
861
870
  viewer.renderer.clippingPlanes = [];
862
871
  viewer.renderer.clippingPlanes.push(this.plane);
863
- this.planeHelper = new PlaneHelper(this.plane, extentsSize, color, extentsCenter);
864
- this.viewer.helpers.add(this.planeHelper);
865
872
  this.planeCenter = new Object3D();
866
873
  this.planeCenter.position.copy(extentsCenter);
874
+ this.planeCenter.quaternion.setFromUnitVectors(new Vector3(0, 0, -1), normal);
867
875
  this.viewer.helpers.add(this.planeCenter);
868
- this.transform = new TransformControls(viewer.camera, viewer.canvas);
869
- this.transform.showX = !!normal.x;
870
- this.transform.showY = !!normal.y;
871
- this.transform.showZ = !!normal.z;
872
- this.transform.attach(this.planeCenter);
873
- this.transform.addEventListener("change", this.transformChange);
874
- this.transform.addEventListener("dragging-changed", this.transformDrag);
875
- this.viewer.helpers.add(this.transform.getHelper());
876
+ this.planeHelper = new PlaneHelper2(extentsSize);
877
+ this.planeCenter.add(this.planeHelper);
878
+ this.translate = new TransformControls(viewer.camera, viewer.canvas);
879
+ this.translate.setSpace("local");
880
+ this.translate.showX = false;
881
+ this.translate.showY = false;
882
+ this.translate.showZ = true;
883
+ this.translate.attach(this.planeCenter);
884
+ this.translate.addEventListener("change", this.transformChange);
885
+ this.translate.addEventListener("dragging-changed", this.translateDrag);
886
+ this.viewer.helpers.add(this.translate.getHelper());
887
+ this.rotate = new TransformControls(viewer.camera, viewer.canvas);
888
+ this.rotate.setMode("rotate");
889
+ this.rotate.setSpace("local");
890
+ this.rotate.showX = true;
891
+ this.rotate.showY = true;
892
+ this.rotate.showZ = false;
893
+ this.rotate.attach(this.planeCenter);
894
+ this.rotate.addEventListener("change", this.transformChange);
895
+ this.rotate.addEventListener("dragging-changed", this.rotateDrag);
896
+ this.viewer.helpers.add(this.rotate.getHelper());
876
897
  this.viewer.addEventListener("explode", this.updatePlaneSize);
877
898
  this.viewer.addEventListener("show", this.updatePlaneSize);
878
899
  this.viewer.addEventListener("showall", this.updatePlaneSize);
879
900
  this.viewer.addEventListener("changecameramode", this.updateTransformCamera);
880
901
  this.viewer.canvas.addEventListener("dblclick", this.onDoubleClick, true);
902
+ window.addEventListener("keydown", this.onKeyDown);
903
+ window.addEventListener("keyup", this.onKeyUp);
881
904
  this.viewer.update();
882
905
  }
883
906
  dispose() {
@@ -886,11 +909,18 @@ class CuttingPlaneDragger extends OrbitDragger {
886
909
  this.viewer.removeEventListener("showall", this.updatePlaneSize);
887
910
  this.viewer.removeEventListener("changecameramode", this.updateTransformCamera);
888
911
  this.viewer.canvas.removeEventListener("dblclick", this.onDoubleClick, true);
889
- this.transform.removeEventListener("change", this.transformChange);
890
- this.transform.removeEventListener("dragging-changed", this.transformDrag);
891
- this.transform.getHelper().removeFromParent();
892
- this.transform.detach();
893
- this.transform.dispose();
912
+ window.removeEventListener("keydown", this.onKeyDown);
913
+ window.removeEventListener("keyup", this.onKeyUp);
914
+ this.translate.removeEventListener("change", this.transformChange);
915
+ this.translate.removeEventListener("dragging-changed", this.translateDrag);
916
+ this.translate.getHelper().removeFromParent();
917
+ this.translate.detach();
918
+ this.translate.dispose();
919
+ this.rotate.removeEventListener("change", this.transformChange);
920
+ this.rotate.removeEventListener("dragging-changed", this.rotateDrag);
921
+ this.rotate.getHelper().removeFromParent();
922
+ this.rotate.detach();
923
+ this.rotate.dispose();
894
924
  this.planeHelper.removeFromParent();
895
925
  this.planeHelper.dispose();
896
926
  this.planeCenter.removeFromParent();
@@ -900,19 +930,19 @@ class CuttingPlaneDragger extends OrbitDragger {
900
930
 
901
931
  class CuttingPlaneXAxisDragger extends CuttingPlaneDragger {
902
932
  constructor(viewer) {
903
- super(viewer, new Vector3(1, 0, 0), 0xff0000);
933
+ super(viewer, new Vector3(-1, 0, 0));
904
934
  }
905
935
  }
906
936
 
907
937
  class CuttingPlaneYAxisDragger extends CuttingPlaneDragger {
908
938
  constructor(viewer) {
909
- super(viewer, new Vector3(0, 1, 0), 0x00ff00);
939
+ super(viewer, new Vector3(0, -1, 0));
910
940
  }
911
941
  }
912
942
 
913
943
  class CuttingPlaneZAxisDragger extends CuttingPlaneDragger {
914
944
  constructor(viewer) {
915
- super(viewer, new Vector3(0, 0, 1), 0x0000ff);
945
+ super(viewer, new Vector3(0, 0, -1));
916
946
  }
917
947
  }
918
948
 
@@ -1514,6 +1544,12 @@ class WalkControls extends Controls {
1514
1544
  this.movementSpeed = 0.1;
1515
1545
  this.multiplier = 3;
1516
1546
  this.groundFollowingSkippedFrames = 0;
1547
+ this.GROUND_BOX_HALF_SIZE = 20;
1548
+ this.GROUND_BOX_REFRESH_THRESHOLD = 0.3;
1549
+ this._groundObjectBoxes = new Map();
1550
+ this._activeGroundObjects = [];
1551
+ this._groundBox = new Box3();
1552
+ this._groundBoxCenter = new Vector3();
1517
1553
  this.moveWheel = 0;
1518
1554
  this.mouseDragOn = false;
1519
1555
  this._up = new Vector3();
@@ -1585,6 +1621,9 @@ class WalkControls extends Controls {
1585
1621
  };
1586
1622
  this.camera = camera;
1587
1623
  this.groundObjects = groundObjects;
1624
+ for (const obj of groundObjects) {
1625
+ this._groundObjectBoxes.set(obj, new Box3().setFromObject(obj));
1626
+ }
1588
1627
  this.raycaster = new Raycaster();
1589
1628
  this.raycaster.near = 0;
1590
1629
  this.raycaster.far = this.EYE_HEIGHT + this.FAILING_DISTANCE;
@@ -1619,10 +1658,29 @@ class WalkControls extends Controls {
1619
1658
  window.removeEventListener("keyup", this.onKeyUp);
1620
1659
  super.dispose();
1621
1660
  }
1661
+ _rebuildGroundBox(center) {
1662
+ const h = this.GROUND_BOX_HALF_SIZE;
1663
+ this._groundBoxCenter.copy(center);
1664
+ 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));
1665
+ this._activeGroundObjects = this.groundObjects.filter((obj) => {
1666
+ const objectBox = this._groundObjectBoxes.get(obj);
1667
+ return objectBox !== undefined && this._groundBox.intersectsBox(objectBox);
1668
+ });
1669
+ }
1670
+ _needsGroundBoxRebuild(pos) {
1671
+ if (this._activeGroundObjects.length === 0 && this.groundObjects.length > 0)
1672
+ return true;
1673
+ const threshold = this.GROUND_BOX_HALF_SIZE * this.GROUND_BOX_REFRESH_THRESHOLD;
1674
+ return (Math.abs(pos.x - this._groundBoxCenter.x) > threshold || Math.abs(pos.z - this._groundBoxCenter.z) > threshold);
1675
+ }
1622
1676
  updateGroundFollowing() {
1677
+ const pos = this.object.position;
1678
+ if (this._needsGroundBoxRebuild(pos)) {
1679
+ this._rebuildGroundBox(pos);
1680
+ }
1623
1681
  this._up.copy(this.camera.up).negate();
1624
- this.raycaster.set(this.object.position, this._up);
1625
- const intersects = this.raycaster.intersectObjects(this.groundObjects, false);
1682
+ this.raycaster.set(pos, this._up);
1683
+ const intersects = this.raycaster.intersectObjects(this._activeGroundObjects, false);
1626
1684
  if (intersects.length > 0) {
1627
1685
  const groundY = intersects[0].point.y;
1628
1686
  const targetY = groundY + this.EYE_HEIGHT;
@@ -7186,12 +7244,14 @@ class Viewer extends EventEmitter2 {
7186
7244
  if (!this.renderer)
7187
7245
  return;
7188
7246
  this._markup.clearOverlay();
7247
+ this.emitEvent({ type: "clearoverlay" });
7189
7248
  this.update();
7190
7249
  }
7191
7250
  clearSlices() {
7192
7251
  if (!this.renderer)
7193
7252
  return;
7194
7253
  this.renderer.clippingPlanes = [];
7254
+ this.emitEvent({ type: "clearslices" });
7195
7255
  this.update();
7196
7256
  }
7197
7257
  getSelected() {