camera controls improvements
This commit is contained in:
parent
4fe6c2ac6c
commit
c26292e441
|
@ -6,6 +6,7 @@ const _PI_2 = Math.PI / 2;
|
|||
|
||||
class CameraControls extends EventDispatcher {
|
||||
private cameraMoving = false;
|
||||
private cameraPanning = false;
|
||||
|
||||
// Set to constrain the pitch of the camera
|
||||
// Range is 0 to Math.PI radians
|
||||
|
@ -13,7 +14,11 @@ class CameraControls extends EventDispatcher {
|
|||
public maxPolarAngle = Math.PI; // radians
|
||||
|
||||
public pointerSpeed = 1.5;
|
||||
public panSpeed = 1;
|
||||
public movementSpeed = 0.025;
|
||||
public shiftMultiplier = 1.2;
|
||||
public zoomScale = 100;
|
||||
public screenSpacePanning = true;
|
||||
|
||||
private rotation = new Euler(0, 0, 0, 'YXZ');
|
||||
private look = new Vector3();
|
||||
|
@ -23,12 +28,15 @@ class CameraControls extends EventDispatcher {
|
|||
private boundOnMouseUp = this.onMouseUp.bind(this);
|
||||
private boundOnKeyDown = this.onKeyDown.bind(this);
|
||||
private boundOnKeyUp = this.onKeyUp.bind(this);
|
||||
private boundOnScroll = this.onScroll.bind(this);
|
||||
|
||||
private movement = {
|
||||
forward: 0,
|
||||
backward: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
up: 0,
|
||||
down: 0,
|
||||
};
|
||||
|
||||
constructor(private camera: Object3D, private domElement: HTMLElement) {
|
||||
|
@ -50,6 +58,7 @@ class CameraControls extends EventDispatcher {
|
|||
'mouseup',
|
||||
this.boundOnMouseUp
|
||||
);
|
||||
this.domElement.ownerDocument.addEventListener('wheel', this.boundOnScroll);
|
||||
window.addEventListener('keydown', this.boundOnKeyDown);
|
||||
window.addEventListener('keyup', this.boundOnKeyUp);
|
||||
}
|
||||
|
@ -67,6 +76,10 @@ class CameraControls extends EventDispatcher {
|
|||
'mouseup',
|
||||
this.boundOnMouseUp
|
||||
);
|
||||
this.domElement.ownerDocument.removeEventListener(
|
||||
'wheel',
|
||||
this.boundOnScroll
|
||||
);
|
||||
window.removeEventListener('keydown', this.boundOnKeyDown);
|
||||
window.removeEventListener('keyup', this.boundOnKeyUp);
|
||||
}
|
||||
|
@ -91,6 +104,14 @@ class CameraControls extends EventDispatcher {
|
|||
if (this.movement.left !== 0) {
|
||||
this.moveRight(-this.movement.left * dt);
|
||||
}
|
||||
|
||||
if (this.movement.up !== 0) {
|
||||
this.moveUp(this.movement.up * dt);
|
||||
}
|
||||
|
||||
if (this.movement.down !== 0) {
|
||||
this.moveUp(-this.movement.down * dt);
|
||||
}
|
||||
}
|
||||
|
||||
getDirection(v: Vector3) {
|
||||
|
@ -110,6 +131,14 @@ class CameraControls extends EventDispatcher {
|
|||
camera.position.addScaledVector(this.look, distance);
|
||||
}
|
||||
|
||||
moveUp(distance: number) {
|
||||
const camera = this.camera;
|
||||
|
||||
this.look.copy(camera.up.clone().applyEuler(this.rotation));
|
||||
|
||||
camera.position.addScaledVector(this.look, distance);
|
||||
}
|
||||
|
||||
moveRight(distance: number) {
|
||||
const camera = this.camera;
|
||||
|
||||
|
@ -119,16 +148,24 @@ class CameraControls extends EventDispatcher {
|
|||
}
|
||||
|
||||
private onMouseDown(event: MouseEvent) {
|
||||
if (event.button === 1) this.cameraPanning = true;
|
||||
if (event.button === 2) this.cameraMoving = true;
|
||||
}
|
||||
|
||||
private onMouseUp(event: MouseEvent) {
|
||||
if (event.button === 1) this.cameraPanning = false;
|
||||
if (event.button === 2) this.cameraMoving = false;
|
||||
}
|
||||
|
||||
private onMouseMove(event: MouseEvent) {
|
||||
if (this.cameraMoving === false) return;
|
||||
private onScroll(event: WheelEvent) {
|
||||
if (event.deltaY < 0) {
|
||||
this.moveForward(this.movementSpeed * this.zoomScale);
|
||||
} else if (event.deltaY > 0) {
|
||||
this.moveForward(-this.movementSpeed * this.zoomScale);
|
||||
}
|
||||
}
|
||||
|
||||
private rotate(event: MouseEvent) {
|
||||
const movementX = event.movementX || 0;
|
||||
const movementY = event.movementY || 0;
|
||||
|
||||
|
@ -144,6 +181,38 @@ class CameraControls extends EventDispatcher {
|
|||
);
|
||||
|
||||
camera.quaternion.setFromEuler(this.rotation);
|
||||
}
|
||||
|
||||
private pan(event: MouseEvent) {
|
||||
const movementX = event.movementX || 0;
|
||||
const movementY = event.movementY || 0;
|
||||
|
||||
const camera = this.camera;
|
||||
|
||||
this.look.setFromMatrixColumn(camera.matrix, 0);
|
||||
camera.position.addScaledVector(
|
||||
this.look,
|
||||
-movementX * 0.02 * this.panSpeed
|
||||
);
|
||||
|
||||
if (this.screenSpacePanning) {
|
||||
this.look.setFromMatrixColumn(camera.matrix, 1);
|
||||
} else {
|
||||
this.look.setFromMatrixColumn(camera.matrix, 0);
|
||||
this.look.crossVectors(camera.up, this.look);
|
||||
}
|
||||
|
||||
camera.position.addScaledVector(
|
||||
this.look,
|
||||
movementY * 0.02 * this.panSpeed
|
||||
);
|
||||
}
|
||||
|
||||
private onMouseMove(event: MouseEvent) {
|
||||
if (this.cameraMoving === false && this.cameraPanning === false) return;
|
||||
|
||||
this.cameraMoving && this.rotate(event);
|
||||
this.cameraPanning && this.pan(event);
|
||||
|
||||
this.dispatchEvent(_changeEvent);
|
||||
}
|
||||
|
@ -155,6 +224,12 @@ class CameraControls extends EventDispatcher {
|
|||
if (event.altKey || event.ctrlKey) return;
|
||||
|
||||
switch (event.code) {
|
||||
case 'KeyE':
|
||||
this.movement.up = this.movementSpeed;
|
||||
break;
|
||||
case 'KeyQ':
|
||||
this.movement.down = this.movementSpeed;
|
||||
break;
|
||||
case 'KeyW':
|
||||
this.movement.forward = this.movementSpeed;
|
||||
break;
|
||||
|
@ -177,6 +252,12 @@ class CameraControls extends EventDispatcher {
|
|||
if (event.altKey || event.ctrlKey) return;
|
||||
|
||||
switch (event.code) {
|
||||
case 'KeyE':
|
||||
this.movement.up = 0;
|
||||
break;
|
||||
case 'KeyQ':
|
||||
this.movement.down = 0;
|
||||
break;
|
||||
case 'KeyW':
|
||||
this.movement.forward = 0;
|
||||
break;
|
||||
|
|
|
@ -95,6 +95,7 @@ export class WorkspaceComponent extends EngineComponent {
|
|||
this.removeFromScene(this.renderer.scene);
|
||||
this.cleanUpEvents?.call(this);
|
||||
this.viewHelper?.dispose();
|
||||
this.cameraControls?.dispose();
|
||||
}
|
||||
|
||||
private addToScene(scene: Object3D) {
|
||||
|
|
Loading…
Reference in New Issue