@inweb/viewer-three 26.9.1 → 26.9.3
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.
- package/dist/plugins/components/AxesHelperComponent.js +8 -6
- package/dist/plugins/components/AxesHelperComponent.js.map +1 -1
- package/dist/plugins/components/AxesHelperComponent.min.js +1 -1
- package/dist/plugins/components/AxesHelperComponent.module.js +8 -6
- package/dist/plugins/components/AxesHelperComponent.module.js.map +1 -1
- package/dist/plugins/components/ExtentsHelperComponent.js.map +1 -1
- package/dist/plugins/components/ExtentsHelperComponent.min.js +1 -1
- package/dist/plugins/components/ExtentsHelperComponent.module.js +1 -1
- package/dist/plugins/components/ExtentsHelperComponent.module.js.map +1 -1
- package/dist/plugins/components/LightHelperComponent.js.map +1 -1
- package/dist/plugins/components/LightHelperComponent.min.js +1 -1
- package/dist/plugins/components/LightHelperComponent.module.js +7 -7
- package/dist/plugins/components/LightHelperComponent.module.js.map +1 -1
- package/dist/plugins/components/RoomEnvironmentComponent.js.map +1 -1
- package/dist/plugins/components/RoomEnvironmentComponent.min.js +1 -1
- package/dist/plugins/components/RoomEnvironmentComponent.module.js +1 -1
- package/dist/plugins/components/RoomEnvironmentComponent.module.js.map +1 -1
- package/dist/plugins/components/StatsPanelComponent.js.map +1 -1
- package/dist/plugins/components/StatsPanelComponent.min.js +1 -1
- package/dist/plugins/components/StatsPanelComponent.module.js +1 -1
- package/dist/plugins/components/StatsPanelComponent.module.js.map +1 -1
- package/dist/plugins/loaders/GLTFCloudLoader.js.map +1 -1
- package/dist/plugins/loaders/GLTFCloudLoader.min.js +1 -1
- package/dist/plugins/loaders/GLTFCloudLoader.module.js +1 -1
- package/dist/plugins/loaders/GLTFCloudLoader.module.js.map +1 -1
- package/dist/plugins/loaders/IFCXLoader.js +4 -4
- package/dist/plugins/loaders/IFCXLoader.js.map +1 -1
- package/dist/plugins/loaders/IFCXLoader.min.js +1 -1
- package/dist/plugins/loaders/IFCXLoader.module.js +92 -92
- package/dist/plugins/loaders/IFCXLoader.module.js.map +1 -1
- package/dist/plugins/loaders/PotreeLoader.js +160 -0
- package/dist/plugins/loaders/PotreeLoader.js.map +1 -0
- package/dist/plugins/loaders/PotreeLoader.min.js +1 -0
- package/dist/plugins/loaders/PotreeLoader.module.js +68 -0
- package/dist/plugins/loaders/PotreeLoader.module.js.map +1 -0
- package/dist/viewer-three.js +1180 -795
- package/dist/viewer-three.js.map +1 -1
- package/dist/viewer-three.min.js +3 -3
- package/dist/viewer-three.module.js +608 -301
- package/dist/viewer-three.module.js.map +1 -1
- package/lib/Viewer/Viewer.d.ts +3 -2
- package/lib/Viewer/controls/FlyControls.d.ts +34 -0
- package/lib/Viewer/controls/WalkControls.d.ts +19 -3
- package/lib/Viewer/draggers/FlyDragger.d.ts +14 -0
- package/package.json +6 -5
- package/plugins/components/AxesHelperComponent.ts +10 -6
- package/plugins/loaders/{IFCXCloudLoader.ts → IFCX/IFCXCloudLoader.ts} +1 -1
- package/plugins/loaders/{IFCXFileLoader.ts → IFCX/IFCXFileLoader.ts} +1 -1
- package/plugins/loaders/Potree/PotreeFileLoader.ts +106 -0
- package/plugins/loaders/Potree/PotreeModelImpl.ts +36 -0
- package/plugins/loaders/Potree/index.ts +28 -0
- package/src/Viewer/Viewer.ts +34 -10
- package/src/Viewer/components/ExtentsComponent.ts +1 -1
- package/src/Viewer/components/ResizeCanvasComponent.ts +1 -18
- package/src/Viewer/controls/FlyControls.ts +205 -0
- package/src/Viewer/controls/WalkControls.ts +129 -20
- package/src/Viewer/draggers/FlyDragger.ts +73 -0
- package/src/Viewer/draggers/OrbitDragger.ts +9 -0
- package/src/Viewer/draggers/WalkDragger.ts +11 -2
- package/src/Viewer/draggers/index.ts +2 -0
- package/src/Viewer/helpers/WCSHelper.ts +3 -3
- /package/plugins/loaders/{IFCXLoader.ts → IFCX/index.ts} +0 -0
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
2
|
+
// Copyright (C) 2002-2025, Open Design Alliance (the "Alliance").
|
|
3
|
+
// All rights reserved.
|
|
4
|
+
//
|
|
5
|
+
// This software and its documentation and related materials are owned by
|
|
6
|
+
// the Alliance. The software may only be incorporated into application
|
|
7
|
+
// programs owned by members of the Alliance, subject to a signed
|
|
8
|
+
// Membership Agreement and Supplemental Software License Agreement with the
|
|
9
|
+
// Alliance. The structure and organization of this software are the valuable
|
|
10
|
+
// trade secrets of the Alliance and its suppliers. The software is also
|
|
11
|
+
// protected by copyright law and international treaty provisions. Application
|
|
12
|
+
// programs incorporating this software must include the following statement
|
|
13
|
+
// with their copyright notices:
|
|
14
|
+
//
|
|
15
|
+
// This application incorporates Open Design Alliance software pursuant to a
|
|
16
|
+
// license agreement with Open Design Alliance.
|
|
17
|
+
// Open Design Alliance Copyright (C) 2002-2025 by Open Design Alliance.
|
|
18
|
+
// All rights reserved.
|
|
19
|
+
//
|
|
20
|
+
// By use of this software, its documentation or related materials, you
|
|
21
|
+
// acknowledge and accept the above terms.
|
|
22
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
23
|
+
|
|
24
|
+
import { Clock, Camera, Controls, Quaternion, Vector2, Vector3 } from "three";
|
|
25
|
+
|
|
26
|
+
interface FlyControlsEventMap {
|
|
27
|
+
change: { type: "change" };
|
|
28
|
+
flyspeedchange: { type: "flyspeedchange"; data: number };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export class FlyControls extends Controls<FlyControlsEventMap> {
|
|
32
|
+
public movementSpeed = 0.2;
|
|
33
|
+
public lookSpeed = 5;
|
|
34
|
+
public multiplier = 5;
|
|
35
|
+
|
|
36
|
+
private moveKeys: Set<string>;
|
|
37
|
+
private moveWheel = 0;
|
|
38
|
+
private moveClock: Clock;
|
|
39
|
+
|
|
40
|
+
private quaternion: Quaternion;
|
|
41
|
+
private downPosition: Vector2;
|
|
42
|
+
private mouseDragOn = false;
|
|
43
|
+
public rotateDelta: Vector2;
|
|
44
|
+
|
|
45
|
+
constructor(camera: Camera, canvas: HTMLElement) {
|
|
46
|
+
super(camera, canvas);
|
|
47
|
+
|
|
48
|
+
this.moveKeys = new Set();
|
|
49
|
+
this.moveClock = new Clock();
|
|
50
|
+
|
|
51
|
+
this.quaternion = camera.quaternion.clone();
|
|
52
|
+
this.downPosition = new Vector2(0, 0);
|
|
53
|
+
this.rotateDelta = new Vector2(0, 0);
|
|
54
|
+
|
|
55
|
+
this.domElement.addEventListener("pointerdown", this.onPointerDown);
|
|
56
|
+
this.domElement.addEventListener("pointermove", this.onPointerMove);
|
|
57
|
+
this.domElement.addEventListener("pointerup", this.onPointerUp);
|
|
58
|
+
this.domElement.addEventListener("pointercancel", this.onPointerCancel);
|
|
59
|
+
this.domElement.addEventListener("wheel", this.onWheel);
|
|
60
|
+
|
|
61
|
+
window.addEventListener("keydown", this.onKeyDown);
|
|
62
|
+
window.addEventListener("keyup", this.onKeyUp);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
override dispose() {
|
|
66
|
+
this.domElement.removeEventListener("pointerdown", this.onPointerDown);
|
|
67
|
+
this.domElement.removeEventListener("pointermove", this.onPointerMove);
|
|
68
|
+
this.domElement.removeEventListener("pointerup", this.onPointerUp);
|
|
69
|
+
this.domElement.removeEventListener("pointercancel", this.onPointerCancel);
|
|
70
|
+
this.domElement.removeEventListener("wheel", this.onWheel);
|
|
71
|
+
|
|
72
|
+
window.removeEventListener("keydown", this.onKeyDown);
|
|
73
|
+
window.removeEventListener("keyup", this.onKeyUp);
|
|
74
|
+
|
|
75
|
+
super.dispose();
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
onPointerDown = (event: PointerEvent) => {
|
|
79
|
+
if (event.button !== 0) return;
|
|
80
|
+
|
|
81
|
+
this.domElement.setPointerCapture(event.pointerId);
|
|
82
|
+
this.downPosition.set(event.clientX, event.clientY);
|
|
83
|
+
this.quaternion.copy(this.object.quaternion);
|
|
84
|
+
this.mouseDragOn = true;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
onPointerMove = (event: PointerEvent) => {
|
|
88
|
+
if (!this.mouseDragOn) return;
|
|
89
|
+
|
|
90
|
+
const movePosition = new Vector2(event.clientX, event.clientY);
|
|
91
|
+
if (this.downPosition.distanceTo(movePosition) === 0) return;
|
|
92
|
+
|
|
93
|
+
this.rotateDelta.copy(this.downPosition).sub(movePosition);
|
|
94
|
+
this.rotateCamera(this.rotateDelta);
|
|
95
|
+
this.dispatchEvent({ type: "change" });
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
onPointerUp = (event: PointerEvent) => {
|
|
99
|
+
this.domElement.releasePointerCapture(event.pointerId);
|
|
100
|
+
this.mouseDragOn = false;
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
onPointerCancel = (event: PointerEvent) => {
|
|
104
|
+
this.domElement.dispatchEvent(new PointerEvent("pointerup", event));
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
onWheel = (event: WheelEvent) => {
|
|
108
|
+
this.moveWheel = event.deltaY;
|
|
109
|
+
this.update();
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
onKeyDown = (event: KeyboardEvent) => {
|
|
113
|
+
switch (event.code) {
|
|
114
|
+
case "NumpadSubtract":
|
|
115
|
+
case "Minus":
|
|
116
|
+
if (this.multiplier > 1) {
|
|
117
|
+
this.multiplier = this.multiplier - 1;
|
|
118
|
+
this.dispatchEvent({ type: "flyspeedchange", data: this.multiplier });
|
|
119
|
+
}
|
|
120
|
+
break;
|
|
121
|
+
|
|
122
|
+
case "NumpadAdd":
|
|
123
|
+
case "Equal":
|
|
124
|
+
if (this.multiplier < 10) {
|
|
125
|
+
this.multiplier = this.multiplier + 1;
|
|
126
|
+
this.dispatchEvent({ type: "flyspeedchange", data: this.multiplier });
|
|
127
|
+
}
|
|
128
|
+
break;
|
|
129
|
+
|
|
130
|
+
case "ArrowLeft":
|
|
131
|
+
case "ArrowRight":
|
|
132
|
+
case "ArrowUp":
|
|
133
|
+
case "ArrowDown":
|
|
134
|
+
case "KeyW":
|
|
135
|
+
case "KeyS":
|
|
136
|
+
case "KeyA":
|
|
137
|
+
case "KeyD":
|
|
138
|
+
case "KeyQ":
|
|
139
|
+
case "KeyE":
|
|
140
|
+
this.moveKeys.add(event.code);
|
|
141
|
+
this.update();
|
|
142
|
+
break;
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
onKeyUp = (event: KeyboardEvent) => {
|
|
147
|
+
if (this.moveKeys.delete(event.code)) this.update();
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
override update() {
|
|
151
|
+
if (this.moveKeys.size > 0) {
|
|
152
|
+
const timeDelta = this.moveClock.getDelta();
|
|
153
|
+
const moveDelta = timeDelta * this.movementSpeed * this.multiplier;
|
|
154
|
+
|
|
155
|
+
if (this.moveKeys.has("KeyW")) this.object.translateZ(-moveDelta);
|
|
156
|
+
if (this.moveKeys.has("KeyS")) this.object.translateZ(moveDelta);
|
|
157
|
+
|
|
158
|
+
if (this.moveKeys.has("KeyA")) this.object.translateX(-moveDelta);
|
|
159
|
+
if (this.moveKeys.has("KeyD")) this.object.translateX(moveDelta);
|
|
160
|
+
|
|
161
|
+
if (this.moveKeys.has("KeyQ")) this.object.translateY(moveDelta);
|
|
162
|
+
if (this.moveKeys.has("KeyE")) this.object.translateY(-moveDelta);
|
|
163
|
+
|
|
164
|
+
const lookDelta = this.lookSpeed + (this.multiplier - 1);
|
|
165
|
+
|
|
166
|
+
if (this.moveKeys.has("ArrowUp")) this.rotateCamera(this.rotateDelta.add(new Vector2(0, -lookDelta / 2)));
|
|
167
|
+
if (this.moveKeys.has("ArrowDown")) this.rotateCamera(this.rotateDelta.add(new Vector2(0, lookDelta / 2)));
|
|
168
|
+
|
|
169
|
+
if (this.moveKeys.has("ArrowLeft")) this.rotateCamera(this.rotateDelta.add(new Vector2(lookDelta, 0)));
|
|
170
|
+
if (this.moveKeys.has("ArrowRight")) this.rotateCamera(this.rotateDelta.add(new Vector2(-lookDelta, 0)));
|
|
171
|
+
|
|
172
|
+
this.moveWheel = 0;
|
|
173
|
+
this.dispatchEvent({ type: "change" });
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (this.moveWheel !== 0) {
|
|
177
|
+
const moveDelta = this.moveWheel * 0.0001 * this.movementSpeed * this.multiplier;
|
|
178
|
+
|
|
179
|
+
this.object.translateZ(-moveDelta);
|
|
180
|
+
this.moveWheel += -1 * Math.sign(this.moveWheel);
|
|
181
|
+
this.dispatchEvent({ type: "change" });
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (this.moveKeys.size === 0 && this.moveWheel === 0) {
|
|
185
|
+
this.moveClock.stop();
|
|
186
|
+
this.moveClock.autoStart = true;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
rotateCamera(delta: Vector2) {
|
|
191
|
+
const rotateX = (Math.PI * delta.x) / this.domElement.clientWidth;
|
|
192
|
+
const rotateY = (Math.PI * delta.y) / this.domElement.clientHeight;
|
|
193
|
+
|
|
194
|
+
const xRotation = new Quaternion();
|
|
195
|
+
xRotation.setFromAxisAngle(this.object.up, rotateX);
|
|
196
|
+
|
|
197
|
+
const yRotation = new Quaternion();
|
|
198
|
+
yRotation.setFromAxisAngle(new Vector3(1, 0, 0), rotateY);
|
|
199
|
+
|
|
200
|
+
const quaternion = this.quaternion.clone();
|
|
201
|
+
quaternion.premultiply(xRotation).multiply(yRotation).normalize();
|
|
202
|
+
|
|
203
|
+
this.object.setRotationFromQuaternion(quaternion);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
@@ -21,7 +21,10 @@
|
|
|
21
21
|
// acknowledge and accept the above terms.
|
|
22
22
|
///////////////////////////////////////////////////////////////////////////////
|
|
23
23
|
|
|
24
|
-
import { Clock, Camera, Controls, Quaternion, Vector2, Vector3 } from "three";
|
|
24
|
+
import { Clock, Camera, Controls, Quaternion, Vector2, Vector3, Raycaster, Object3D, MathUtils } from "three";
|
|
25
|
+
import { Viewer } from "../Viewer";
|
|
26
|
+
import { IModelImpl } from "../models/IModelImpl";
|
|
27
|
+
import { HighlighterComponent } from "../components/HighlighterComponent";
|
|
25
28
|
|
|
26
29
|
interface WalkControlsEventMap {
|
|
27
30
|
change: { type: "change" };
|
|
@@ -29,9 +32,18 @@ interface WalkControlsEventMap {
|
|
|
29
32
|
}
|
|
30
33
|
|
|
31
34
|
export class WalkControls extends Controls<WalkControlsEventMap> {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
+
readonly EYE_HEIGHT = 1.7;
|
|
36
|
+
readonly FAILING_DISTANCE = 2;
|
|
37
|
+
readonly GROUND_FOLLOWING_SPEED = 0.05;
|
|
38
|
+
readonly LOOK_SPEED = 0.1;
|
|
39
|
+
readonly WALK_SPEED_DELIMITER = 4;
|
|
40
|
+
readonly WHEEL_SPEED_DELIMITER = 15000;
|
|
41
|
+
|
|
42
|
+
public movementSpeed = 0.1;
|
|
43
|
+
public multiplier = 3;
|
|
44
|
+
|
|
45
|
+
private raycaster: Raycaster;
|
|
46
|
+
private groundObjects: Object3D[];
|
|
35
47
|
|
|
36
48
|
private moveKeys: Set<string>;
|
|
37
49
|
private moveWheel = 0;
|
|
@@ -42,8 +54,19 @@ export class WalkControls extends Controls<WalkControlsEventMap> {
|
|
|
42
54
|
private mouseDragOn = false;
|
|
43
55
|
public rotateDelta: Vector2;
|
|
44
56
|
|
|
45
|
-
|
|
57
|
+
private camera: Camera;
|
|
58
|
+
private viewer: Viewer;
|
|
59
|
+
protected highlighter: HighlighterComponent;
|
|
60
|
+
|
|
61
|
+
constructor(camera: Camera, canvas: HTMLElement, groundObjects: Object3D[], viewer: Viewer) {
|
|
46
62
|
super(camera, canvas);
|
|
63
|
+
this.camera = camera;
|
|
64
|
+
this.viewer = viewer;
|
|
65
|
+
|
|
66
|
+
this.groundObjects = groundObjects;
|
|
67
|
+
this.raycaster = new Raycaster();
|
|
68
|
+
this.raycaster.near = 0;
|
|
69
|
+
this.raycaster.far = this.EYE_HEIGHT + this.FAILING_DISTANCE;
|
|
47
70
|
|
|
48
71
|
this.moveKeys = new Set();
|
|
49
72
|
this.moveClock = new Clock();
|
|
@@ -147,37 +170,123 @@ export class WalkControls extends Controls<WalkControlsEventMap> {
|
|
|
147
170
|
if (this.moveKeys.delete(event.code)) this.update();
|
|
148
171
|
};
|
|
149
172
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
173
|
+
private updateGroundFollowing() {
|
|
174
|
+
this.raycaster.set(this.object.position, new Vector3(0, -1, 0));
|
|
175
|
+
|
|
176
|
+
this.raycaster.params = this.raycaster.params = {
|
|
177
|
+
Mesh: {},
|
|
178
|
+
Line: { threshold: 0 },
|
|
179
|
+
Line2: { threshold: 0 },
|
|
180
|
+
LOD: { threshold: 0 },
|
|
181
|
+
Points: { threshold: 0 },
|
|
182
|
+
Sprite: { threshold: 0 },
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
let intersects = this.raycaster.intersectObjects(this.groundObjects, false);
|
|
186
|
+
if (intersects.length > 0) {
|
|
187
|
+
const groundY = intersects[0].point.y;
|
|
188
|
+
const targetY = groundY + this.EYE_HEIGHT;
|
|
189
|
+
|
|
190
|
+
// Smoothly interpolate the camera's y position to the target height
|
|
191
|
+
this.object.position.y = MathUtils.lerp(this.object.position.y, targetY, this.GROUND_FOLLOWING_SPEED);
|
|
192
|
+
|
|
193
|
+
// Only for debug
|
|
194
|
+
// const model = this.viewer.models[0];
|
|
195
|
+
// const handles = model.getHandlesByObjects(intersects[0].object);
|
|
196
|
+
// const objects = model.getObjectsByHandles(handles);
|
|
197
|
+
// this.viewer.clearSelected();
|
|
198
|
+
// this.select(objects, model);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
select(objects: Object3D | Object3D[], model?: IModelImpl) {
|
|
203
|
+
if (!model) {
|
|
204
|
+
this.viewer.models.forEach((model) => this.select(objects, model));
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
if (!Array.isArray(objects)) objects = [objects];
|
|
209
|
+
if (!objects.length) return;
|
|
154
210
|
|
|
155
|
-
|
|
156
|
-
|
|
211
|
+
model.showOriginalObjects(objects);
|
|
212
|
+
this.highlighter.highlight(objects);
|
|
157
213
|
|
|
158
|
-
|
|
159
|
-
|
|
214
|
+
objects.forEach((object: any) => this.viewer.selected.push(object));
|
|
215
|
+
objects.forEach((object: any) => (object.isSelected = true));
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
initHighlighter = () => {
|
|
219
|
+
this.highlighter = this.viewer.getComponent("HighlighterComponent") as HighlighterComponent;
|
|
220
|
+
};
|
|
160
221
|
|
|
161
|
-
|
|
162
|
-
|
|
222
|
+
override update() {
|
|
223
|
+
let moved = false;
|
|
224
|
+
let upgradeGroundFollowing = false;
|
|
225
|
+
const forward = new Vector3();
|
|
226
|
+
const sideways = new Vector3();
|
|
163
227
|
|
|
164
|
-
|
|
228
|
+
if (this.moveKeys.size > 0) {
|
|
229
|
+
upgradeGroundFollowing = true;
|
|
230
|
+
const timeDelta = this.moveClock.getDelta();
|
|
231
|
+
const moveDelta = (timeDelta * this.multiplier * this.movementSpeed) / this.WALK_SPEED_DELIMITER;
|
|
232
|
+
|
|
233
|
+
this.object.getWorldDirection(forward);
|
|
234
|
+
forward.y = 0;
|
|
235
|
+
forward.normalize();
|
|
236
|
+
|
|
237
|
+
sideways.setFromMatrixColumn(this.object.matrix, 0);
|
|
238
|
+
sideways.y = 0;
|
|
239
|
+
sideways.normalize();
|
|
240
|
+
|
|
241
|
+
if (this.moveKeys.has("KeyW")) {
|
|
242
|
+
this.object.position.addScaledVector(forward, moveDelta);
|
|
243
|
+
}
|
|
244
|
+
if (this.moveKeys.has("KeyS")) {
|
|
245
|
+
this.object.position.addScaledVector(forward, -moveDelta);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
if (this.moveKeys.has("KeyA")) {
|
|
249
|
+
this.object.position.addScaledVector(sideways, -moveDelta);
|
|
250
|
+
}
|
|
251
|
+
if (this.moveKeys.has("KeyD")) {
|
|
252
|
+
this.object.position.addScaledVector(sideways, moveDelta);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
if (this.moveKeys.has("KeyQ")) {
|
|
256
|
+
this.object.translateY(moveDelta);
|
|
257
|
+
upgradeGroundFollowing = false;
|
|
258
|
+
}
|
|
259
|
+
if (this.moveKeys.has("KeyE")) {
|
|
260
|
+
this.object.translateY(-moveDelta);
|
|
261
|
+
upgradeGroundFollowing = false;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
const lookDelta = this.LOOK_SPEED + (this.multiplier - 1);
|
|
165
265
|
|
|
166
266
|
if (this.moveKeys.has("ArrowUp")) this.rotateCamera(this.rotateDelta.add(new Vector2(0, -lookDelta / 2)));
|
|
167
267
|
if (this.moveKeys.has("ArrowDown")) this.rotateCamera(this.rotateDelta.add(new Vector2(0, lookDelta / 2)));
|
|
168
|
-
|
|
169
268
|
if (this.moveKeys.has("ArrowLeft")) this.rotateCamera(this.rotateDelta.add(new Vector2(lookDelta, 0)));
|
|
170
269
|
if (this.moveKeys.has("ArrowRight")) this.rotateCamera(this.rotateDelta.add(new Vector2(-lookDelta, 0)));
|
|
171
270
|
|
|
172
271
|
this.moveWheel = 0;
|
|
173
|
-
|
|
272
|
+
moved = true;
|
|
174
273
|
}
|
|
175
274
|
|
|
176
275
|
if (this.moveWheel !== 0) {
|
|
177
|
-
const moveDelta = this.moveWheel *
|
|
276
|
+
const moveDelta = (this.moveWheel * this.multiplier * this.movementSpeed) / this.WHEEL_SPEED_DELIMITER;
|
|
277
|
+
|
|
278
|
+
this.object.getWorldDirection(forward);
|
|
279
|
+
forward.y = 0;
|
|
280
|
+
forward.normalize();
|
|
281
|
+
this.object.position.addScaledVector(forward, -moveDelta);
|
|
178
282
|
|
|
179
|
-
this.object.translateZ(-moveDelta);
|
|
180
283
|
this.moveWheel += -1 * Math.sign(this.moveWheel);
|
|
284
|
+
moved = true;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
if (upgradeGroundFollowing) this.updateGroundFollowing();
|
|
288
|
+
|
|
289
|
+
if (moved) {
|
|
181
290
|
this.dispatchEvent({ type: "change" });
|
|
182
291
|
}
|
|
183
292
|
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
2
|
+
// Copyright (C) 2002-2025, Open Design Alliance (the "Alliance").
|
|
3
|
+
// All rights reserved.
|
|
4
|
+
//
|
|
5
|
+
// This software and its documentation and related materials are owned by
|
|
6
|
+
// the Alliance. The software may only be incorporated into application
|
|
7
|
+
// programs owned by members of the Alliance, subject to a signed
|
|
8
|
+
// Membership Agreement and Supplemental Software License Agreement with the
|
|
9
|
+
// Alliance. The structure and organization of this software are the valuable
|
|
10
|
+
// trade secrets of the Alliance and its suppliers. The software is also
|
|
11
|
+
// protected by copyright law and international treaty provisions. Application
|
|
12
|
+
// programs incorporating this software must include the following statement
|
|
13
|
+
// with their copyright notices:
|
|
14
|
+
//
|
|
15
|
+
// This application incorporates Open Design Alliance software pursuant to a
|
|
16
|
+
// license agreement with Open Design Alliance.
|
|
17
|
+
// Open Design Alliance Copyright (C) 2002-2025 by Open Design Alliance.
|
|
18
|
+
// All rights reserved.
|
|
19
|
+
//
|
|
20
|
+
// By use of this software, its documentation or related materials, you
|
|
21
|
+
// acknowledge and accept the above terms.
|
|
22
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
23
|
+
|
|
24
|
+
import { Vector3 } from "three";
|
|
25
|
+
import { type IDragger } from "@inweb/viewer-core";
|
|
26
|
+
|
|
27
|
+
import type { Viewer } from "../Viewer";
|
|
28
|
+
import { FlyControls } from "../controls/FlyControls";
|
|
29
|
+
|
|
30
|
+
export class FlyDragger implements IDragger {
|
|
31
|
+
protected viewer: Viewer;
|
|
32
|
+
public controls: FlyControls;
|
|
33
|
+
|
|
34
|
+
constructor(viewer: Viewer) {
|
|
35
|
+
this.controls = new FlyControls(viewer.camera, viewer.canvas);
|
|
36
|
+
this.controls.addEventListener("change", this.controlsChange);
|
|
37
|
+
this.controls.addEventListener("flyspeedchange", this.flyspeedChange);
|
|
38
|
+
this.viewer = viewer;
|
|
39
|
+
this.viewer.on("render", this.viewerRender);
|
|
40
|
+
this.viewer.on("zoom", this.viewerZoom);
|
|
41
|
+
this.updateControls();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
dispose() {
|
|
45
|
+
this.viewer.off("render", this.viewerRender);
|
|
46
|
+
this.viewer.off("zoom", this.viewerZoom);
|
|
47
|
+
this.controls.removeEventListener("flyspeedchange", this.flyspeedChange);
|
|
48
|
+
this.controls.removeEventListener("change", this.controlsChange);
|
|
49
|
+
this.controls.dispose();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
updateControls = () => {
|
|
53
|
+
const size = this.viewer.extents.getSize(new Vector3());
|
|
54
|
+
this.controls.movementSpeed = Math.min(size.x, size.y, size.z) / 2;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
controlsChange = () => {
|
|
58
|
+
this.viewer.update();
|
|
59
|
+
this.viewer.emitEvent({ type: "changecamera" });
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
flyspeedChange = (event: any) => {
|
|
63
|
+
this.viewer.emitEvent(event);
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
viewerRender = () => {
|
|
67
|
+
this.controls.update();
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
viewerZoom = () => {
|
|
71
|
+
this.controls.rotateDelta.set(0, 0);
|
|
72
|
+
};
|
|
73
|
+
}
|
|
@@ -81,6 +81,13 @@ export class OrbitDragger implements IDragger {
|
|
|
81
81
|
this.viewer.update();
|
|
82
82
|
|
|
83
83
|
switch (this.orbit.state) {
|
|
84
|
+
case STATE.ROTATE:
|
|
85
|
+
case STATE.TOUCH_ROTATE:
|
|
86
|
+
this.viewer.emitEvent({
|
|
87
|
+
type: "orbit",
|
|
88
|
+
});
|
|
89
|
+
break;
|
|
90
|
+
|
|
84
91
|
case STATE.PAN:
|
|
85
92
|
case STATE.TOUCH_PAN:
|
|
86
93
|
this.viewer.emitEvent({
|
|
@@ -102,6 +109,8 @@ export class OrbitDragger implements IDragger {
|
|
|
102
109
|
break;
|
|
103
110
|
}
|
|
104
111
|
|
|
112
|
+
this.viewer.emitEvent({ type: "changecamera" });
|
|
113
|
+
|
|
105
114
|
this.changed = true;
|
|
106
115
|
};
|
|
107
116
|
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
// acknowledge and accept the above terms.
|
|
22
22
|
///////////////////////////////////////////////////////////////////////////////
|
|
23
23
|
|
|
24
|
-
import { Vector3 } from "three";
|
|
24
|
+
import { Mesh, Vector3 } from "three";
|
|
25
25
|
import { type IDragger } from "@inweb/viewer-core";
|
|
26
26
|
|
|
27
27
|
import type { Viewer } from "../Viewer";
|
|
@@ -32,7 +32,15 @@ export class WalkDragger implements IDragger {
|
|
|
32
32
|
public controls: WalkControls;
|
|
33
33
|
|
|
34
34
|
constructor(viewer: Viewer) {
|
|
35
|
-
|
|
35
|
+
const meshOnlyGround: Mesh[] = [];
|
|
36
|
+
viewer.models[0].getObjects().forEach((obj) => {
|
|
37
|
+
obj.traverse((child) => {
|
|
38
|
+
if (child instanceof Mesh) {
|
|
39
|
+
meshOnlyGround.push(child);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
this.controls = new WalkControls(viewer.camera, viewer.canvas, meshOnlyGround, viewer);
|
|
36
44
|
this.controls.addEventListener("change", this.controlsChange);
|
|
37
45
|
this.controls.addEventListener("walkspeedchange", this.walkspeedChange);
|
|
38
46
|
this.viewer = viewer;
|
|
@@ -56,6 +64,7 @@ export class WalkDragger implements IDragger {
|
|
|
56
64
|
|
|
57
65
|
controlsChange = () => {
|
|
58
66
|
this.viewer.update();
|
|
67
|
+
this.viewer.emitEvent({ type: "changecamera" });
|
|
59
68
|
};
|
|
60
69
|
|
|
61
70
|
walkspeedChange = (event: any) => {
|
|
@@ -30,6 +30,7 @@ import { MeasureLineDragger } from "./MeasureLineDragger";
|
|
|
30
30
|
import { OrbitDragger } from "./OrbitDragger";
|
|
31
31
|
import { PanDragger } from "./PanDragger";
|
|
32
32
|
import { WalkDragger } from "./WalkDragger";
|
|
33
|
+
import { FlyDragger } from "./FlyDragger";
|
|
33
34
|
import { ZoomDragger } from "./ZoomDragger";
|
|
34
35
|
|
|
35
36
|
/**
|
|
@@ -87,3 +88,4 @@ draggers.registerDragger("CuttingPlaneXAxis", (viewer) => new CuttingPlaneXAxisD
|
|
|
87
88
|
draggers.registerDragger("CuttingPlaneYAxis", (viewer) => new CuttingPlaneYAxisDragger(viewer));
|
|
88
89
|
draggers.registerDragger("CuttingPlaneZAxis", (viewer) => new CuttingPlaneZAxisDragger(viewer));
|
|
89
90
|
draggers.registerDragger("Walk", (viewer) => new WalkDragger(viewer));
|
|
91
|
+
draggers.registerDragger("Fly", (viewer) => new FlyDragger(viewer));
|
|
@@ -28,9 +28,9 @@ export class WCSHelper extends Object3D {
|
|
|
28
28
|
this.orthoCamera = new OrthographicCamera(-2, 2, 2, -2, 0, 4);
|
|
29
29
|
this.orthoCamera.position.set(0, 0, 2);
|
|
30
30
|
|
|
31
|
-
const matRed = new MeshBasicMaterial({ toneMapped: false, color: "#
|
|
32
|
-
const matGreen = new MeshBasicMaterial({ toneMapped: false, color: "#
|
|
33
|
-
const matBlue = new MeshBasicMaterial({ toneMapped: false, color: "#
|
|
31
|
+
const matRed = new MeshBasicMaterial({ toneMapped: false, color: "#dd0000" });
|
|
32
|
+
const matGreen = new MeshBasicMaterial({ toneMapped: false, color: "#00dd00" });
|
|
33
|
+
const matBlue = new MeshBasicMaterial({ toneMapped: false, color: "#0000dd" });
|
|
34
34
|
|
|
35
35
|
const spriteRed = this.getSpriteMaterial(matRed.color, "X");
|
|
36
36
|
const spriteGreen = this.getSpriteMaterial(matGreen.color, "Y");
|
|
File without changes
|