-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add DeviceOrientationControls2, FirstPersonControls2, OrbitControls2,…
… PointerLockControls2, RGBM to linear conversion functions on cpu.
- Loading branch information
Showing
10 changed files
with
853 additions
and
8 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,182 @@ | ||
import {Euler, EulerOrder, EventDispatcher, MathUtils, Object3D, Quaternion, Vector3} from 'three' | ||
import {IEvent, now, serialize} from 'ts-browser-helpers' | ||
import {uiPanelContainer, uiSlider} from 'uiconfig.js' | ||
import {ICameraControls} from '../../core' | ||
|
||
// eslint-disable-next-line @typescript-eslint/naming-convention | ||
const _zee = new Vector3(0, 0, 1) | ||
// eslint-disable-next-line @typescript-eslint/naming-convention | ||
const _euler = new Euler() | ||
// eslint-disable-next-line @typescript-eslint/naming-convention | ||
const _q0 = new Quaternion() | ||
// eslint-disable-next-line @typescript-eslint/naming-convention | ||
const _q1 = new Quaternion(-Math.sqrt(0.5), 0, 0, Math.sqrt(0.5)) // - PI/2 around the x-axis | ||
// eslint-disable-next-line @typescript-eslint/naming-convention | ||
const _q2 = new Quaternion() // - PI/2 around the x-axis | ||
|
||
// eslint-disable-next-line @typescript-eslint/naming-convention | ||
const _changeEvent: IEvent<'change'> = {type: 'change'} | ||
|
||
const EPS = 0.000001 | ||
|
||
@uiPanelContainer('Device Orientation Controls') | ||
export class DeviceOrientationControls2 extends EventDispatcher implements ICameraControls<'change'> { | ||
object: Object3D | ||
enabled = false // do not serialize this as it signifies weather this is active. | ||
deviceOrientation?: DeviceOrientationEvent | ||
screenOrientation?: ScreenOrientation | ||
lastOrder: EulerOrder = 'XYZ' | ||
@serialize() | ||
@uiSlider('Damping', [0, 1], 0.01) | ||
dampingFactor = 0.05 | ||
lastQuaternion = new Quaternion() | ||
|
||
constructor(object: Object3D) { | ||
|
||
super() | ||
|
||
if (window.isSecureContext === false) { | ||
|
||
console.error('DeviceOrientationControls2: DeviceOrientationEvent is only available in secure contexts (https)') | ||
|
||
} | ||
|
||
this.object = object | ||
|
||
this.lastOrder = this.object.rotation.order | ||
this.object.rotation.reorder('YXZ') | ||
|
||
// this.enabled = true | ||
|
||
this.connect() | ||
|
||
} | ||
|
||
onDeviceOrientationChangeEvent = (event: DeviceOrientationEvent) => { | ||
this.deviceOrientation = event | ||
} | ||
|
||
onScreenOrientationChangeEvent = () => { | ||
this.screenOrientation = screen.orientation | ||
} | ||
|
||
private _initQuaternion = new Quaternion() | ||
private _initQuaternionInvert = new Quaternion() | ||
private _initQuaternionDest = new Quaternion() | ||
connect() { | ||
|
||
this.onScreenOrientationChangeEvent() // run once on load | ||
|
||
// iOS 13+ | ||
|
||
if (window.DeviceOrientationEvent !== undefined && typeof (window.DeviceOrientationEvent as any).requestPermission === 'function') { | ||
|
||
(window.DeviceOrientationEvent as any).requestPermission().then((response: string)=>{ | ||
|
||
if (response == 'granted') { | ||
|
||
window.addEventListener('orientationchange', this.onScreenOrientationChangeEvent) | ||
window.addEventListener('deviceorientation', this.onDeviceOrientationChangeEvent) | ||
|
||
} | ||
|
||
}).catch((error: any)=>{ | ||
|
||
console.error('DeviceOrientationControls2: Unable to use DeviceOrientation API:', error) | ||
|
||
}) | ||
|
||
} else { | ||
|
||
window.addEventListener('orientationchange', this.onScreenOrientationChangeEvent) | ||
window.addEventListener('deviceorientation', this.onDeviceOrientationChangeEvent) | ||
|
||
} | ||
|
||
this.enabled = true | ||
this._initQuaternion.copy(this.object.quaternion) | ||
this._initQuaternionInvert.copy(this.object.quaternion).invert() | ||
|
||
} | ||
|
||
disconnect() { | ||
|
||
window.removeEventListener('orientationchange', this.onScreenOrientationChangeEvent) | ||
window.removeEventListener('deviceorientation', this.onDeviceOrientationChangeEvent) | ||
this._initQuaternion.identity() | ||
this._initQuaternionInvert.identity() | ||
this._initQuaternionDest = new Quaternion() // need to set a new instance here. | ||
this.object.rotation.reorder(this.lastOrder) | ||
this.lastOrder = 'XYZ' | ||
|
||
this.enabled = false | ||
|
||
} | ||
|
||
update() { | ||
|
||
if (!this.enabled) return | ||
|
||
const device = this.deviceOrientation | ||
|
||
if (device) { | ||
|
||
const alpha = device.alpha !== null ? MathUtils.degToRad(device.alpha) : 0 // Z | ||
|
||
const beta = device.beta !== null ? MathUtils.degToRad(device.beta) : 0 // X' | ||
|
||
const gamma = device.gamma !== null ? MathUtils.degToRad(device.gamma) : 0 // Y'' | ||
|
||
const orient = this.screenOrientation ? MathUtils.degToRad(this.screenOrientation.angle) : 0 // O | ||
|
||
this.setObjectQuaternion(alpha, beta, gamma, orient) | ||
|
||
if (8 * (1 - this.lastQuaternion.dot(this.object.quaternion)) > EPS) { | ||
|
||
this.lastQuaternion.copy(this.object.quaternion) | ||
this.dispatchEvent(_changeEvent) | ||
|
||
} | ||
|
||
} | ||
|
||
} | ||
|
||
dispose() { | ||
|
||
this.disconnect() | ||
|
||
} | ||
|
||
private _lastTime = -1 | ||
|
||
// The angles alpha, beta and gamma form a set of intrinsic Tait-Bryan angles of type Z-X'-Y'' | ||
setObjectQuaternion(alpha: number, beta: number, gamma: number, orient: number): void { | ||
// if(_lastTime < 0) | ||
const time = now() / 1000 | ||
|
||
_euler.set(beta, alpha, -gamma, 'YXZ') // 'ZXY' for the device, but 'YXZ' for us | ||
|
||
_q2.setFromEuler(_euler) // orient the device | ||
|
||
_q2.multiply(_q1) // camera looks out the back of the device, not the top | ||
|
||
_q2.multiply(_q0.setFromAxisAngle(_zee, -orient)) // adjust for screen orientation | ||
|
||
if (!(this._initQuaternionDest as any).__init) { | ||
this._initQuaternionDest.copy(_q2).invert() | ||
;(this._initQuaternionDest as any).__init = true | ||
} | ||
|
||
_q2.premultiply(this._initQuaternionDest) | ||
|
||
const mTime = 1 / 60 | ||
// this.object.quaternion.multiply(this._initQuaternionInvert) | ||
this.object.quaternion.slerp(_q2, this.dampingFactor / (Math.min(1, time - this._lastTime) / mTime)) | ||
// this.object.quaternion.multiply(this._initQuaternion) | ||
// console.log(time - this._lastTime, mTime) | ||
|
||
this._lastTime = time | ||
} | ||
|
||
} |
Oops, something went wrong.