UNPKG

@polygonjs/polygonjs

Version:

node-based WebGL 3D engine https://polygonjs.com

106 lines (97 loc) 4 kB
/* This table summarizes the requirements/quirks of the different browsers and devices for deviceorientation controls | https required | start orientation consistent | permission required | | android + chrome: | yes | yes | no anroid + firefox: | no | no | no ios + safari: | yes | no | yes ios + firefox: | ? | ? | ? ios + chrome: | yes | no | yes */ import {Quaternion} from 'three'; import {NamedFunction2} from './_Base'; import {DeviceOrientationControls} from '../../core/camera/controls/DeviceOrientationControls'; import {PolyScene} from '../scene/PolyScene'; import {dummyReadRefVal} from '../../core/reactivity/CoreReactivity'; // import {CoreUserAgent} from '../../core/UserAgent'; // const ROTATION_ORDER = 'YXZ'; // const magicWindowAbsoluteEuler = new Euler(); // const magicWindowDeltaEuler = new Euler(); // const compensateQuat = new Quaternion().setFromAxisAngle(new Vector3(0, 1, 0), Math.PI / 2); // compensate for the inconsistency in rotation when starting in landscape vs starting in portrait, // but only if we are in landscape, and NOT in android + chrome // const compensateRotation = false; //CoreUserAgent.isLandscape() && !(CoreUserAgent.isAndroid() && CoreUserAgent.isChrome()); class DeviceOrientationControlsHandler { // private _dummyObject = new Object3D(); private _lastUpdatedFrame = -1; private _controls: DeviceOrientationControls | undefined; // private previousMagicWindowYaw: number | undefined; constructor(public readonly scene: PolyScene) { // this._controls = new DeviceOrientationControls(); } update() { const currentFrame = this.scene.frame(); if (currentFrame == this._lastUpdatedFrame) { return; } // the controls are created in the update method, // instead of the constructor, so that // it does not get created until the scene plays. // This allows loading the scene with autoPlay=false, // and only start playing once DeviceOrientationEvent permission has been granted. this._controls = this._controls || new DeviceOrientationControls(); if (this._controls.enabled) { this._controls.update(); // if (compensateRotation) { // this._compensate(); // } } this._lastUpdatedFrame = currentFrame; } quaternion(target: Quaternion) { // update must be before checking for controls, // otherwise the controls are never created. this.update(); if (!this._controls) { console.warn('no controls'); return; } this._controls.quaternion(target); // if (compensateRotation) { // target.premultiply(compensateQuat); // // target.setFromEuler(magicWindowDeltaEuler, false); // } else { // // target.copy(this._dummyObject.quaternion); // } } setSmoothAmount(smoothAmount: number) { this._controls?.setSmoothAmount(smoothAmount); } // from aframe look-controls .updateMagicWindowOrientation() // protected _compensate() { // magicWindowAbsoluteEuler.setFromQuaternion(this._dummyObject.quaternion, ROTATION_ORDER); // if (!this.previousMagicWindowYaw && magicWindowAbsoluteEuler.y !== 0) { // this.previousMagicWindowYaw = magicWindowAbsoluteEuler.y; // } // if (this.previousMagicWindowYaw) { // magicWindowDeltaEuler.x = magicWindowAbsoluteEuler.x; // magicWindowDeltaEuler.y += magicWindowAbsoluteEuler.y - this.previousMagicWindowYaw; // magicWindowDeltaEuler.z = magicWindowAbsoluteEuler.z; // this.previousMagicWindowYaw = magicWindowAbsoluteEuler.y; // } // } } let _handler: DeviceOrientationControlsHandler | undefined; export class deviceOrientation extends NamedFunction2<[Quaternion, number]> { static override type() { return 'deviceOrientation'; } func(target: Quaternion, smoothAmount: number): Quaternion { // force time dependency dummyReadRefVal(this.timeController.timeUniform().value); _handler = _handler || new DeviceOrientationControlsHandler(this.scene); _handler.setSmoothAmount(smoothAmount); _handler.quaternion(target); return target; } }