camera controls improvements

This commit is contained in:
Evert Prants 2023-06-09 18:32:30 +03:00
parent 4fe6c2ac6c
commit c26292e441
Signed by: evert
GPG Key ID: 1688DA83D222D0B5
2 changed files with 84 additions and 2 deletions

View File

@ -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;

View File

@ -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) {