1
0
Fork 0
mirror of https://github.com/DanielnetoDotCom/YouPHPTube synced 2025-10-05 02:39:46 +02:00
Oinktube/node_modules/cardboard-vr-display/src/pose-sensor.js
2023-12-11 11:59:56 -03:00

171 lines
6 KiB
JavaScript

/*
* Copyright 2015 Google Inc. All Rights Reserved.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import FusionPoseSensor from './sensor-fusion/fusion-pose-sensor.js';
import { Vector3, Quaternion } from './math-util.js';
// Frequency which the Sensors will attempt to fire their
// `reading` functions at. Use 60hz since we generally
// can't get higher without native VR hardware.
const SENSOR_FREQUENCY = 60;
const X_AXIS = new Vector3(1, 0, 0);
const Z_AXIS = new Vector3(0, 0, 1);
// Quaternion to rotate from sensor coordinates to WebVR coordinates
const SENSOR_TO_VR = new Quaternion();
SENSOR_TO_VR.setFromAxisAngle(X_AXIS, -Math.PI / 2);
SENSOR_TO_VR.multiply(new Quaternion().setFromAxisAngle(Z_AXIS, Math.PI / 2));
/**
* An abstraction class around either using the new RelativeOrientationSensor,
* or `devicemotion` events with complimentary filter via fusion-pose-sensor.js.
*/
export default class PoseSensor {
constructor(config) {
this.config = config;
this.sensor = null;
this.fusionSensor = null;
this._out = new Float32Array(4);
// Can be 'sensor' (using RelativeOrientationSensor) or
// 'devicemotion' (using devicemotion events via FusionPoseSensor),
// or `null` if not yet set.
this.api = null;
// Store any errors from Sensors for debugging purposes
this.errors = [];
// Quaternions for caching transforms
this._sensorQ = new Quaternion();
this._outQ = new Quaternion();
this._onSensorRead = this._onSensorRead.bind(this);
this._onSensorError = this._onSensorError.bind(this);
this.init();
}
init() {
// Attempt to use the RelativeOrientationSensor from Generic Sensor APIs.
// First available in Chrome M63, this can fail for several reasons, and attempt
// to fallback to devicemotion. Failure scenarios include:
//
// * Generic Sensor APIs do not exist; fallback to devicemotion.
// * Underlying sensor does not exist; no fallback possible.
// * Feature Policy failure (in an iframe); no fallback.
// https://github.com/immersive-web/webxr/issues/86
// * Permission to sensor data denied; respect user agent; no fallback to devicemotion.
// Browsers are heading towards disabling devicemotion when sensors are denied as well.
// https://www.chromestatus.com/feature/5023919287304192
let sensor = null;
try {
sensor = new RelativeOrientationSensor({
frequency: SENSOR_FREQUENCY,
// Use `referenceFrame: screen` so we don't have to manage the orientation
// of the device. First available in Chrome m66 (in release at time of writing),
// and this will fail in earlier versions, kicking off `devicemotion` fallback.
// @see https://w3c.github.io/accelerometer/#screen-coordinate-system
referenceFrame: 'screen',
});
sensor.addEventListener('error', this._onSensorError);
} catch (error) {
this.errors.push(error);
// Sensors are available in Chrome M63, however the Feature Policy
// integration is not available until Chrome M65, resulting in Sensors
// only being available in main frames.
// https://developers.google.com/web/updates/2017/09/sensors-for-the-web#feature_policy_integration
if (error.name === 'SecurityError') {
console.error('Cannot construct sensors due to the Feature Policy');
console.warn('Attempting to fall back using "devicemotion"; however this will ' +
'fail in the future without correct permissions.');
this.useDeviceMotion();
} else if (error.name === 'ReferenceError') {
// Fall back to devicemotion.
this.useDeviceMotion();
} else {
console.error(error);
}
}
if (sensor) {
this.api = 'sensor';
this.sensor = sensor;
this.sensor.addEventListener('reading', this._onSensorRead);
this.sensor.start();
}
}
useDeviceMotion() {
this.api = 'devicemotion';
this.fusionSensor = new FusionPoseSensor(this.config.K_FILTER,
this.config.PREDICTION_TIME_S,
this.config.YAW_ONLY,
this.config.DEBUG);
if (this.sensor) {
this.sensor.removeEventListener('reading', this._onSensorRead);
this.sensor.removeEventListener('error', this._onSensorError);
this.sensor = null;
}
}
getOrientation() {
if (this.fusionSensor) {
return this.fusionSensor.getOrientation();
}
if (!this.sensor || !this.sensor.quaternion) {
this._out[0] = this._out[1] = this._out[2] = 0;
this._out[3] = 1;
return this._out;
}
// Convert to THREE coordinate system: -Z forward, Y up, X right.
const q = this.sensor.quaternion;
this._sensorQ.set(q[0], q[1], q[2], q[3]);
const out = this._outQ;
out.copy(SENSOR_TO_VR);
out.multiply(this._sensorQ);
// Handle the yaw-only case.
if (this.config.YAW_ONLY) {
// Make a quaternion that only turns around the Y-axis.
out.x = out.z = 0;
out.normalize();
}
this._out[0] = out.x;
this._out[1] = out.y;
this._out[2] = out.z;
this._out[3] = out.w;
return this._out;
}
_onSensorError(event) {
this.errors.push(event.error);
if (event.error.name === 'NotAllowedError') {
console.error('Permission to access sensor was denied');
} else if (event.error.name === 'NotReadableError') {
console.error('Sensor could not be read');
} else {
console.error(event.error);
}
this.useDeviceMotion();
}
_onSensorRead() {}
}