Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Camera controls rework #289

Merged
merged 43 commits into from
May 1, 2024
Merged
Show file tree
Hide file tree
Changes from 42 commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
1d54bbd
WIP: basic orbit camera
kpal81xd Apr 10, 2024
cea1b30
put setPosition inside update loop prep for smoothing
kpal81xd Apr 10, 2024
0dc8732
renamed orbit camera
kpal81xd Apr 10, 2024
ef2f329
removed space
kpal81xd Apr 10, 2024
08cf4b4
WIP: basic fly camera
kpal81xd Apr 10, 2024
c9de9c3
moved focus position closer and fixed double click for fly camera
kpal81xd Apr 10, 2024
42958dd
smoothing for fly camera done
kpal81xd Apr 11, 2024
875fade
hoisted out constants
kpal81xd Apr 11, 2024
f6d7bc7
extracted out common properties from fly and orbit into base camera
kpal81xd Apr 11, 2024
ca9de35
combined fly and orbit camera together with toggle to switch between
kpal81xd Apr 11, 2024
ff5e449
added controls button for fly and orbit
kpal81xd Apr 11, 2024
1b22b60
fixed pan speed and added context menu disabling to base camera
kpal81xd Apr 12, 2024
94e9550
cleared up attributes on detach
kpal81xd Apr 12, 2024
be4e560
removed setting from camera and just added as toggle button
kpal81xd Apr 12, 2024
a043a2b
cleanup of controls variables
kpal81xd Apr 12, 2024
341b8a8
changes quotes to single
kpal81xd Apr 12, 2024
e07c4b5
flipped pointer zoom direction
kpal81xd Apr 15, 2024
37ac1a8
removed controls from types
kpal81xd Apr 15, 2024
568902e
added zoom speed decay when closer
kpal81xd Apr 15, 2024
b373da9
added basic look smoothing
kpal81xd Apr 15, 2024
35f3942
removed velocity and use invariant lerp
kpal81xd Apr 15, 2024
50466d9
replaced orbit and fly with multi-camera
kpal81xd Apr 15, 2024
dc39a2c
added wasd to multi-camera and diff mouse keys between between fly an…
kpal81xd Apr 15, 2024
7e8f3a4
added panning with middle mouse button
kpal81xd Apr 15, 2024
a56fc57
hoisted out magic variables
kpal81xd Apr 15, 2024
13e6386
removed other cameras and forwarded from options in constructor
kpal81xd Apr 15, 2024
70f05b6
Merge branch 'main' into camera-rework
kpal81xd Apr 16, 2024
948c162
updated pinch speed
kpal81xd Apr 17, 2024
ea9a0ad
removed zoom scaling (for now) fixed panning rotation and near clippi…
kpal81xd Apr 17, 2024
6c7223c
added control keybind to slow down
kpal81xd Apr 18, 2024
7ec9258
added back zoom slowing and pointer move only occurs on canvas
kpal81xd Apr 18, 2024
08d13d0
adjusted panning speed relative to scene size
kpal81xd Apr 18, 2024
95aac17
modified panning to correctly calculate distance
kpal81xd Apr 18, 2024
7ae947d
removed unused variables
kpal81xd Apr 18, 2024
712fef4
adjusted zoom clipping
kpal81xd Apr 18, 2024
f9a09e7
cleaned up ray plane intersection code
kpal81xd Apr 18, 2024
cc40aa9
fixed panning
kpal81xd Apr 24, 2024
88443ae
fixed pointer up bug
kpal81xd Apr 25, 2024
534a5fd
added fullscreen button back
kpal81xd Apr 25, 2024
1672583
added name to entity and reset focus when exiting XR mode
kpal81xd Apr 25, 2024
23046ca
fixed XR positioning
kpal81xd Apr 25, 2024
26a345a
moved camera rotation reset inside attach and kept position from deta…
kpal81xd Apr 25, 2024
7d10653
fixed zoom for different fov and aspect ratios
kpal81xd May 1, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 118 additions & 0 deletions src/cameras/base-camera.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import { Entity, Vec3, Vec2, math } from 'playcanvas';

type PointerMoveEvent = PointerEvent & {
mozMovementX: number;
mozMovementY: number;
webkitMovementX: number;
webkitMovementY: number;
}

const LOOK_MAX_ANGLE = 90;

abstract class BaseCamera {
entity: Entity;

target: HTMLElement = document.documentElement;

sceneSize: number = 100;

lookSensitivity: number = 0.2;

lookDamping: number = 0.97;

moveDamping: number = 0.98;

protected _camera: Entity = null;

protected _origin: Vec3 = new Vec3(0, 1, 0);

protected _position: Vec3 = new Vec3();

protected _dir: Vec2 = new Vec2();

protected _angles: Vec3 = new Vec3();

constructor(target: HTMLElement, options: Record<string, any> = {}) {
this.entity = new Entity(options.name ?? 'base-camera');
this.target = target;
this.sceneSize = options.sceneSize ?? this.sceneSize;
this.lookSensitivity = options.lookSensitivity ?? this.lookSensitivity;
this.lookDamping = options.lookDamping ?? this.lookDamping;
this.moveDamping = options.moveDamping ?? this.moveDamping;

this._onPointerDown = this._onPointerDown.bind(this);
this._onPointerMove = this._onPointerMove.bind(this);
this._onPointerUp = this._onPointerUp.bind(this);
}

private _smoothLook(dt: number) {
const lerpRate = 1 - Math.pow(this.lookDamping, dt * 1000);
this._angles.x = math.lerp(this._angles.x, this._dir.x, lerpRate);
this._angles.y = math.lerp(this._angles.y, this._dir.y, lerpRate);
this.entity.setEulerAngles(this._angles);
}

private _smoothMove(dt: number) {
this._position.lerp(this._position, this._origin, 1 - Math.pow(this.moveDamping, dt * 1000));
this.entity.setPosition(this._position);
}

private _onContextMenu(event: MouseEvent) {
event.preventDefault();
}

protected abstract _onPointerDown(event: PointerEvent): void

protected abstract _onPointerMove(event: PointerMoveEvent): void

protected abstract _onPointerUp(event: PointerEvent): void

protected _look(event: PointerMoveEvent) {
if (event.target !== this.target) {
return;
}
const movementX = event.movementX || event.mozMovementX || event.webkitMovementX || 0;
const movementY = event.movementY || event.mozMovementY || event.webkitMovementY || 0;
this._dir.x = math.clamp(this._dir.x - movementY * this.lookSensitivity, -LOOK_MAX_ANGLE, LOOK_MAX_ANGLE);
this._dir.y -= movementX * this.lookSensitivity;
}

attach(camera: Entity) {
this._camera = camera;
this._camera.setLocalEulerAngles(0, 0, 0);

window.addEventListener('pointerdown', this._onPointerDown);
window.addEventListener('pointermove', this._onPointerMove);
window.addEventListener('pointerup', this._onPointerUp);
window.addEventListener('contextmenu', this._onContextMenu);

this.entity.addChild(camera);
}

detach() {
window.removeEventListener('pointermove', this._onPointerMove);
window.removeEventListener('pointerdown', this._onPointerDown);
window.removeEventListener('pointerup', this._onPointerUp);
window.removeEventListener('contextmenu', this._onContextMenu);

this.entity.removeChild(this._camera);
this._camera = null;

this._dir.x = this._angles.x;
this._dir.y = this._angles.y;

this._origin.copy(this._position);
}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
update(dt: number) {
if (!this._camera) {
return;
}

this._smoothLook(dt);
this._smoothMove(dt);
}
}

export { BaseCamera };
Loading
Loading