@egjs/view360
Version:
360 integrated viewing solution from inside-out view to outside-in view. It provides user-friendly service by rotating 360 degrees through various user interaction such as motion sensor and touch.
1,571 lines (1,345 loc) • 247 kB
JavaScript
/*
Copyright (c) 2017-present NAVER Corp.
name: @egjs/view360
license: MIT
author: NAVER Corp.
repository: https://github.com/naver/egjs-view360
version: 3.6.4
*/
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('@egjs/component'), require('promise-polyfill'), require('@egjs/agent'), require('@egjs/axes'), require('gl-matrix'), require('@egjs/imready')) :
typeof define === 'function' && define.amd ? define(['@egjs/component', 'promise-polyfill', '@egjs/agent', '@egjs/axes', 'gl-matrix', '@egjs/imready'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, (global.eg = global.eg || {}, global.eg.view360 = factory(global.eg.Component, global.Promise, global.eg.agent, global.eg.Axes, global.glMatrix, global.eg.ImReady)));
}(this, (function (Component, Promise$1, agent$1, Axes, glMatrix, ImReady) { 'use strict';
var VERSION = "3.6.4";
/*! *****************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
/* global Reflect, Promise */
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf || {
__proto__: []
} instanceof Array && function (d, b) {
d.__proto__ = b;
} || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
};
return extendStatics(d, b);
};
function __extends(d, b) {
extendStatics(d, b);
function __() {
this.constructor = d;
}
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
}
var __assign = function () {
__assign = Object.assign || function __assign(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
function __awaiter(thisArg, _arguments, P, generator) {
function adopt(value) {
return value instanceof P ? value : new P(function (resolve) {
resolve(value);
});
}
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
}
function rejected(value) {
try {
step(generator["throw"](value));
} catch (e) {
reject(e);
}
}
function step(result) {
result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
}
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
}
function __generator(thisArg, body) {
var _ = {
label: 0,
sent: function () {
if (t[0] & 1) throw t[1];
return t[1];
},
trys: [],
ops: []
},
f,
y,
t,
g;
return g = {
next: verb(0),
"throw": verb(1),
"return": verb(2)
}, typeof Symbol === "function" && (g[Symbol.iterator] = function () {
return this;
}), g;
function verb(n) {
return function (v) {
return step([n, v]);
};
}
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0:
case 1:
t = op;
break;
case 4:
_.label++;
return {
value: op[1],
done: false
};
case 5:
_.label++;
y = op[1];
op = [0];
continue;
case 7:
op = _.ops.pop();
_.trys.pop();
continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
_ = 0;
continue;
}
if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
_.label = op[1];
break;
}
if (op[0] === 6 && _.label < t[1]) {
_.label = t[1];
t = op;
break;
}
if (t && _.label < t[2]) {
_.label = t[2];
_.ops.push(op);
break;
}
if (t[2]) _.ops.pop();
_.trys.pop();
continue;
}
op = body.call(thisArg, _);
} catch (e) {
op = [6, e];
y = 0;
} finally {
f = t = 0;
}
if (op[0] & 5) throw op[1];
return {
value: op[0] ? op[1] : void 0,
done: true
};
}
}
function __values(o) {
var s = typeof Symbol === "function" && Symbol.iterator,
m = s && o[s],
i = 0;
if (m) return m.call(o);
if (o && typeof o.length === "number") return {
next: function () {
if (o && i >= o.length) o = void 0;
return {
value: o && o[i++],
done: !o
};
}
};
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
}
function __read(o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m) return o;
var i = m.call(o),
r,
ar = [],
e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
} catch (error) {
e = {
error: error
};
} finally {
try {
if (r && !r.done && (m = i["return"])) m.call(i);
} finally {
if (e) throw e.error;
}
}
return ar;
}
function __spread() {
for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read(arguments[i]));
return ar;
}
/* eslint-disable @typescript-eslint/no-implied-eval */
/* eslint-disable no-new-func, no-nested-ternary */
var win = typeof window !== "undefined" && window.Math === Math ? window : typeof self !== "undefined" && self.Math === Math ? self : Function("return this")();
/* eslint-enable no-new-func, no-nested-ternary */
var doc = win.document;
var nav = win.navigator;
var agent = agent$1();
var osName = agent.os.name;
var browserName = agent.browser.name;
var IS_IOS = osName === "ios";
var IS_SAFARI_ON_DESKTOP = osName === "mac" && browserName === "safari";
/* eslint-disable @typescript-eslint/naming-convention */
win.Float32Array = typeof win.Float32Array !== "undefined" ? win.Float32Array : win.Array;
var Float32Array$1 = win.Float32Array;
var getComputedStyle = win.getComputedStyle;
var userAgent = win.navigator && win.navigator.userAgent;
var SUPPORT_TOUCH = ("ontouchstart" in win);
var SUPPORT_DEVICEMOTION = ("ondevicemotion" in win);
var DeviceMotionEvent = win.DeviceMotionEvent;
var devicePixelRatio = win.devicePixelRatio;
var TRANSFORM = function () {
var _a;
var docStyle = (_a = doc === null || doc === void 0 ? void 0 : doc.documentElement.style) !== null && _a !== void 0 ? _a : {};
var target = ["transform", "webkitTransform", "msTransform", "mozTransform"];
for (var i = 0, len = target.length; i < len; i++) {
if (target[i] in docStyle) {
return target[i];
}
}
return "";
}(); // check for will-change support
var SUPPORT_WILLCHANGE = win.CSS && win.CSS.supports && win.CSS.supports("will-change", "transform");
var WEBXR_SUPPORTED = false;
var checkXRSupport = function () {
var navigator = window.navigator;
if (!navigator.xr) {
return;
}
if (navigator.xr.isSessionSupported) {
navigator.xr.isSessionSupported("immersive-vr").then(function (res) {
WEBXR_SUPPORTED = res;
}).catch(function () {
return void 0;
});
} else if (navigator.xr.supportsSession) {
navigator.xr.supportsSession("immersive-vr").then(function (res) {
WEBXR_SUPPORTED = res;
}).catch(function () {
return void 0;
});
}
};
/**
* Original Code
* https://github.com/toji/gl-matrix/blob/v2.3.2/src/gl-matrix.js
* Math Util
* modified by egjs
*/
var quatToVec3 = function (quaternion) {
var baseV = glMatrix.vec3.fromValues(0, 0, 1);
glMatrix.vec3.transformQuat(baseV, baseV, quaternion);
return baseV;
};
var toDegree = function (a) {
return a * 180 / Math.PI;
};
var util = {};
util.isPowerOfTwo = function (n) {
return n && (n & n - 1) === 0;
};
util.extractPitchFromQuat = function (quaternion) {
var baseV = quatToVec3(quaternion);
return -1 * Math.atan2(baseV[1], Math.sqrt(Math.pow(baseV[0], 2) + Math.pow(baseV[2], 2)));
};
util.hypot = Math.hypot || function (x, y) {
return Math.sqrt(x * x + y * y);
}; // implement reference
// the general equation of a plane : http://www.gisdeveloper.co.kr/entry/평면의-공식
// calculating angle between two vectors : http://darkpgmr.tistory.com/121
var ROTATE_CONSTANT = {
PITCH_DELTA: 1,
YAW_DELTA_BY_ROLL: 2,
YAW_DELTA_BY_YAW: 3
};
ROTATE_CONSTANT[ROTATE_CONSTANT.PITCH_DELTA] = {
targetAxis: [0, 1, 0],
meshPoint: [0, 0, 1]
};
ROTATE_CONSTANT[ROTATE_CONSTANT.YAW_DELTA_BY_ROLL] = {
targetAxis: [0, 1, 0],
meshPoint: [1, 0, 0]
};
ROTATE_CONSTANT[ROTATE_CONSTANT.YAW_DELTA_BY_YAW] = {
targetAxis: [1, 0, 0],
meshPoint: [0, 0, 1]
};
var getRotationDelta = function (prevQ, curQ, rotateKind) {
var targetAxis = glMatrix.vec3.fromValues(ROTATE_CONSTANT[rotateKind].targetAxis[0], ROTATE_CONSTANT[rotateKind].targetAxis[1], ROTATE_CONSTANT[rotateKind].targetAxis[2]);
var meshPoint = ROTATE_CONSTANT[rotateKind].meshPoint;
var prevQuaternion = glMatrix.quat.clone(prevQ);
var curQuaternion = glMatrix.quat.clone(curQ);
glMatrix.quat.normalize(prevQuaternion, prevQuaternion);
glMatrix.quat.normalize(curQuaternion, curQuaternion);
var prevPoint = glMatrix.vec3.fromValues(0, 0, 1);
var curPoint = glMatrix.vec3.fromValues(0, 0, 1);
glMatrix.vec3.transformQuat(prevPoint, prevPoint, prevQuaternion);
glMatrix.vec3.transformQuat(curPoint, curPoint, curQuaternion);
glMatrix.vec3.transformQuat(targetAxis, targetAxis, curQuaternion);
var rotateDistance = glMatrix.vec3.dot(targetAxis, glMatrix.vec3.cross(glMatrix.vec3.create(), prevPoint, curPoint));
var rotateDirection = rotateDistance > 0 ? 1 : -1; // when counter clock wise, use vec3.fromValues(0,1,0)
// when clock wise, use vec3.fromValues(0,-1,0)
// const meshPoint1 = vec3.fromValues(0, 0, 0);
var meshPoint2 = glMatrix.vec3.fromValues(meshPoint[0], meshPoint[1], meshPoint[2]);
var meshPoint3;
if (rotateKind !== ROTATE_CONSTANT.YAW_DELTA_BY_YAW) {
meshPoint3 = glMatrix.vec3.fromValues(0, rotateDirection, 0);
} else {
meshPoint3 = glMatrix.vec3.fromValues(rotateDirection, 0, 0);
}
glMatrix.vec3.transformQuat(meshPoint2, meshPoint2, curQuaternion);
glMatrix.vec3.transformQuat(meshPoint3, meshPoint3, curQuaternion);
var vecU = meshPoint2;
var vecV = meshPoint3;
var vecN = glMatrix.vec3.create();
glMatrix.vec3.cross(vecN, vecU, vecV);
glMatrix.vec3.normalize(vecN, vecN);
var coefficientA = vecN[0];
var coefficientB = vecN[1];
var coefficientC = vecN[2]; // const coefficientD = -1 * vec3.dot(vecN, meshPoint1);
// a point on the plane
curPoint = glMatrix.vec3.fromValues(meshPoint[0], meshPoint[1], meshPoint[2]);
glMatrix.vec3.transformQuat(curPoint, curPoint, curQuaternion); // a point should project on the plane
prevPoint = glMatrix.vec3.fromValues(meshPoint[0], meshPoint[1], meshPoint[2]);
glMatrix.vec3.transformQuat(prevPoint, prevPoint, prevQuaternion); // distance between prevPoint and the plane
var distance = Math.abs(prevPoint[0] * coefficientA + prevPoint[1] * coefficientB + prevPoint[2] * coefficientC);
var projectedPrevPoint = glMatrix.vec3.create();
glMatrix.vec3.subtract(projectedPrevPoint, prevPoint, glMatrix.vec3.scale(glMatrix.vec3.create(), vecN, distance));
var trigonometricRatio = (projectedPrevPoint[0] * curPoint[0] + projectedPrevPoint[1] * curPoint[1] + projectedPrevPoint[2] * curPoint[2]) / (glMatrix.vec3.length(projectedPrevPoint) * glMatrix.vec3.length(curPoint)); // defensive block
if (trigonometricRatio > 1) {
trigonometricRatio = 1;
}
var theta = Math.acos(trigonometricRatio);
var crossVec = glMatrix.vec3.cross(glMatrix.vec3.create(), curPoint, projectedPrevPoint);
distance = coefficientA * crossVec[0] + coefficientB * crossVec[1] + coefficientC * crossVec[2];
var thetaDirection;
if (rotateKind !== ROTATE_CONSTANT.YAW_DELTA_BY_YAW) {
thetaDirection = distance > 0 ? 1 : -1;
} else {
thetaDirection = distance < 0 ? 1 : -1;
}
var deltaRadian = theta * thetaDirection * rotateDirection;
return toDegree(deltaRadian);
};
var angleBetweenVec2 = function (v1, v2) {
var det = v1[0] * v2[1] - v2[0] * v1[1];
var theta = -Math.atan2(det, glMatrix.vec2.dot(v1, v2));
return theta;
};
util.yawOffsetBetween = function (viewDir, targetDir) {
var viewDirXZ = glMatrix.vec2.fromValues(viewDir[0], viewDir[2]);
var targetDirXZ = glMatrix.vec2.fromValues(targetDir[0], targetDir[2]);
glMatrix.vec2.normalize(viewDirXZ, viewDirXZ);
glMatrix.vec2.normalize(targetDirXZ, targetDirXZ);
var theta = -angleBetweenVec2(viewDirXZ, targetDirXZ);
return theta;
};
util.sign = function (x) {
return Math.sign ? Math.sign(x) : Number(x > 0) - Number(x < 0) || +x;
};
util.toDegree = toDegree;
util.getRotationDelta = getRotationDelta;
util.angleBetweenVec2 = angleBetweenVec2;
var toAxis = function (source, offset) {
return offset.reduce(function (acc, v, i) {
if (source[i]) {
acc[source[i]] = v;
}
return acc;
}, {});
};
/**
* Returns a number value indiciating the version of Chrome being used,
* or otherwise `null` if not on Chrome.
*
* Ref: https://github.com/immersive-web/cardboard-vr-display/pull/19
*/
/**
* In Chrome m65, `devicemotion` events are broken but subsequently fixed
* in 65.0.3325.148. Since many browsers use Chromium, ensure that
* we scope this detection by branch and build numbers to provide
* a proper fallback.
* https://github.com/immersive-web/webvr-polyfill/issues/307
*/
var version = -1; // It should not be null because it will be compared with number
var branch = null;
var build = null;
var match = /Chrome\/([0-9]+)\.(?:[0-9]*)\.([0-9]*)\.([0-9]*)/i.exec(userAgent);
if (match) {
version = parseInt(match[1], 10);
branch = match[2];
build = match[3];
}
var CHROME_VERSION = version;
var IS_CHROME_WITHOUT_DEVICE_MOTION = version === 65 && branch === "3325" && parseInt(build, 10) < 148;
var IS_ANDROID = /Android/i.test(userAgent);
var CONTROL_MODE_VR = 1;
var CONTROL_MODE_YAWPITCH = 2;
var TOUCH_DIRECTION_NONE = 1;
var TOUCH_DIRECTION_YAW = 2;
var TOUCH_DIRECTION_PITCH = 4;
var TOUCH_DIRECTION_ALL = TOUCH_DIRECTION_YAW | TOUCH_DIRECTION_PITCH;
/* Const for MovableCoord */
var MC_DECELERATION = 0.0014;
var MC_MAXIMUM_DURATION = 1000;
var MC_BIND_SCALE = [0.20, 0.20];
var MAX_FIELD_OF_VIEW = 110;
var PAN_SCALE = 320; // const DELTA_THRESHOLD = 0.015;
var YAW_RANGE_HALF = 180;
var PITCH_RANGE_HALF = 90;
var CIRCULAR_PITCH_RANGE_HALF = 180;
var GYRO_MODE = {
NONE: "none",
YAWPITCH: "yawPitch",
VR: "VR"
};
/* eslint-disable */
var MathUtil = win.MathUtil || {};
MathUtil.degToRad = Math.PI / 180;
MathUtil.radToDeg = 180 / Math.PI; // Some minimal math functionality borrowed from THREE.Math and stripped down
// for the purposes of this library.
MathUtil.Vector2 = function (x, y) {
this.x = x || 0;
this.y = y || 0;
};
MathUtil.Vector2.prototype = {
constructor: MathUtil.Vector2,
set: function (x, y) {
this.x = x;
this.y = y;
return this;
},
copy: function (v) {
this.x = v.x;
this.y = v.y;
return this;
},
subVectors: function (a, b) {
this.x = a.x - b.x;
this.y = a.y - b.y;
return this;
}
};
MathUtil.Vector3 = function (x, y, z) {
this.x = x || 0;
this.y = y || 0;
this.z = z || 0;
};
MathUtil.Vector3.prototype = {
constructor: MathUtil.Vector3,
set: function (x, y, z) {
this.x = x;
this.y = y;
this.z = z;
return this;
},
copy: function (v) {
this.x = v.x;
this.y = v.y;
this.z = v.z;
return this;
},
length: function () {
return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z);
},
normalize: function () {
var scalar = this.length();
if (scalar !== 0) {
var invScalar = 1 / scalar;
this.multiplyScalar(invScalar);
} else {
this.x = 0;
this.y = 0;
this.z = 0;
}
return this;
},
multiplyScalar: function (scalar) {
this.x *= scalar;
this.y *= scalar;
this.z *= scalar;
},
applyQuaternion: function (q) {
var x = this.x;
var y = this.y;
var z = this.z;
var qx = q.x;
var qy = q.y;
var qz = q.z;
var qw = q.w; // calculate quat * vector
var ix = qw * x + qy * z - qz * y;
var iy = qw * y + qz * x - qx * z;
var iz = qw * z + qx * y - qy * x;
var iw = -qx * x - qy * y - qz * z; // calculate result * inverse quat
this.x = ix * qw + iw * -qx + iy * -qz - iz * -qy;
this.y = iy * qw + iw * -qy + iz * -qx - ix * -qz;
this.z = iz * qw + iw * -qz + ix * -qy - iy * -qx;
return this;
},
dot: function (v) {
return this.x * v.x + this.y * v.y + this.z * v.z;
},
crossVectors: function (a, b) {
var ax = a.x;
var ay = a.y;
var az = a.z;
var bx = b.x;
var by = b.y;
var bz = b.z;
this.x = ay * bz - az * by;
this.y = az * bx - ax * bz;
this.z = ax * by - ay * bx;
return this;
}
};
MathUtil.Quaternion = function (x, y, z, w) {
this.x = x || 0;
this.y = y || 0;
this.z = z || 0;
this.w = w !== undefined ? w : 1;
};
MathUtil.Quaternion.prototype = {
constructor: MathUtil.Quaternion,
set: function (x, y, z, w) {
this.x = x;
this.y = y;
this.z = z;
this.w = w;
return this;
},
copy: function (quaternion) {
this.x = quaternion.x;
this.y = quaternion.y;
this.z = quaternion.z;
this.w = quaternion.w;
return this;
},
setFromEulerXYZ: function (x, y, z) {
var c1 = Math.cos(x / 2);
var c2 = Math.cos(y / 2);
var c3 = Math.cos(z / 2);
var s1 = Math.sin(x / 2);
var s2 = Math.sin(y / 2);
var s3 = Math.sin(z / 2);
this.x = s1 * c2 * c3 + c1 * s2 * s3;
this.y = c1 * s2 * c3 - s1 * c2 * s3;
this.z = c1 * c2 * s3 + s1 * s2 * c3;
this.w = c1 * c2 * c3 - s1 * s2 * s3;
return this;
},
setFromEulerYXZ: function (x, y, z) {
var c1 = Math.cos(x / 2);
var c2 = Math.cos(y / 2);
var c3 = Math.cos(z / 2);
var s1 = Math.sin(x / 2);
var s2 = Math.sin(y / 2);
var s3 = Math.sin(z / 2);
this.x = s1 * c2 * c3 + c1 * s2 * s3;
this.y = c1 * s2 * c3 - s1 * c2 * s3;
this.z = c1 * c2 * s3 - s1 * s2 * c3;
this.w = c1 * c2 * c3 + s1 * s2 * s3;
return this;
},
setFromAxisAngle: function (axis, angle) {
// http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm
// assumes axis is normalized
var halfAngle = angle / 2;
var s = Math.sin(halfAngle);
this.x = axis.x * s;
this.y = axis.y * s;
this.z = axis.z * s;
this.w = Math.cos(halfAngle);
return this;
},
multiply: function (q) {
return this.multiplyQuaternions(this, q);
},
multiplyQuaternions: function (a, b) {
// from http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm
var qax = a.x;
var qay = a.y;
var qaz = a.z;
var qaw = a.w;
var qbx = b.x;
var qby = b.y;
var qbz = b.z;
var qbw = b.w;
this.x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby;
this.y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz;
this.z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx;
this.w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz;
return this;
},
inverse: function () {
this.x *= -1;
this.y *= -1;
this.z *= -1;
this.normalize();
return this;
},
normalize: function () {
var l = Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w);
if (l === 0) {
this.x = 0;
this.y = 0;
this.z = 0;
this.w = 1;
} else {
l = 1 / l;
this.x = this.x * l;
this.y = this.y * l;
this.z = this.z * l;
this.w = this.w * l;
}
return this;
},
slerp: function (qb, t) {
if (t === 0) return this;
if (t === 1) return this.copy(qb);
var x = this.x;
var y = this.y;
var z = this.z;
var w = this.w; // http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/
var cosHalfTheta = w * qb.w + x * qb.x + y * qb.y + z * qb.z;
if (cosHalfTheta < 0) {
this.w = -qb.w;
this.x = -qb.x;
this.y = -qb.y;
this.z = -qb.z;
cosHalfTheta = -cosHalfTheta;
} else {
this.copy(qb);
}
if (cosHalfTheta >= 1.0) {
this.w = w;
this.x = x;
this.y = y;
this.z = z;
return this;
}
var halfTheta = Math.acos(cosHalfTheta);
var sinHalfTheta = Math.sqrt(1.0 - cosHalfTheta * cosHalfTheta);
if (Math.abs(sinHalfTheta) < 0.001) {
this.w = 0.5 * (w + this.w);
this.x = 0.5 * (x + this.x);
this.y = 0.5 * (y + this.y);
this.z = 0.5 * (z + this.z);
return this;
}
var ratioA = Math.sin((1 - t) * halfTheta) / sinHalfTheta;
var ratioB = Math.sin(t * halfTheta) / sinHalfTheta;
this.w = w * ratioA + this.w * ratioB;
this.x = x * ratioA + this.x * ratioB;
this.y = y * ratioA + this.y * ratioB;
this.z = z * ratioA + this.z * ratioB;
return this;
},
setFromUnitVectors: function () {
// http://lolengine.net/blog/2014/02/24/quaternion-from-two-vectors-final
// assumes direction vectors vFrom and vTo are normalized
var v1;
var r;
var EPS = 0.000001;
return function (vFrom, vTo) {
if (v1 === undefined) v1 = new MathUtil.Vector3();
r = vFrom.dot(vTo) + 1;
if (r < EPS) {
r = 0;
if (Math.abs(vFrom.x) > Math.abs(vFrom.z)) {
v1.set(-vFrom.y, vFrom.x, 0);
} else {
v1.set(0, -vFrom.z, vFrom.y);
}
} else {
v1.crossVectors(vFrom, vTo);
}
this.x = v1.x;
this.y = v1.y;
this.z = v1.z;
this.w = r;
this.normalize();
return this;
};
}()
};
/* eslint-disable */
/*
* 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.
*/
var _a; // tslint:disable: only-arrow-functions
var userAgent$1 = (_a = nav === null || nav === void 0 ? void 0 : nav.userAgent) !== null && _a !== void 0 ? _a : "";
var Util = win.Util || {};
Util.MIN_TIMESTEP = 0.001;
Util.MAX_TIMESTEP = 1;
Util.base64 = function (mimeType, base64) {
return "data:" + mimeType + ";base64," + base64;
};
Util.clamp = function (value, min, max) {
return Math.min(Math.max(min, value), max);
};
Util.lerp = function (a, b, t) {
return a + (b - a) * t;
};
Util.isIOS = function () {
var isIOS = /iPad|iPhone|iPod/.test(nav === null || nav === void 0 ? void 0 : nav.platform);
return function () {
return isIOS;
};
}();
Util.isWebViewAndroid = function () {
var isWebViewAndroid = userAgent$1.indexOf("Version") !== -1 && userAgent$1.indexOf("Android") !== -1 && userAgent$1.indexOf("Chrome") !== -1;
return function () {
return isWebViewAndroid;
};
}();
Util.isSafari = function () {
var isSafari = /^((?!chrome|android).)*safari/i.test(userAgent$1);
return function () {
return isSafari;
};
}();
Util.isFirefoxAndroid = function () {
var isFirefoxAndroid = userAgent$1.indexOf("Firefox") !== -1 && userAgent$1.indexOf("Android") !== -1;
return function () {
return isFirefoxAndroid;
};
}();
Util.isR7 = function () {
var isR7 = userAgent$1.indexOf("R7 Build") !== -1;
return function () {
return isR7;
};
}();
Util.isLandscapeMode = function () {
var rtn = win.orientation === 90 || win.orientation === -90;
return Util.isR7() ? !rtn : rtn;
}; // Helper method to validate the time steps of sensor timestamps.
Util.isTimestampDeltaValid = function (timestampDeltaS) {
if (isNaN(timestampDeltaS)) {
return false;
}
if (timestampDeltaS <= Util.MIN_TIMESTEP) {
return false;
}
if (timestampDeltaS > Util.MAX_TIMESTEP) {
return false;
}
return true;
};
Util.getScreenWidth = function () {
return Math.max(win.screen.width, win.screen.height) * win.devicePixelRatio;
};
Util.getScreenHeight = function () {
return Math.min(win.screen.width, win.screen.height) * win.devicePixelRatio;
};
Util.requestFullscreen = function (element) {
if (Util.isWebViewAndroid()) {
return false;
}
if (element.requestFullscreen) {
element.requestFullscreen();
} else if (element.webkitRequestFullscreen) {
element.webkitRequestFullscreen();
} else if (element.mozRequestFullScreen) {
element.mozRequestFullScreen();
} else if (element.msRequestFullscreen) {
element.msRequestFullscreen();
} else {
return false;
}
return true;
};
Util.exitFullscreen = function () {
if (doc.exitFullscreen) {
doc.exitFullscreen();
} else if (doc.webkitExitFullscreen) {
doc.webkitExitFullscreen();
} else if (doc.mozCancelFullScreen) {
doc.mozCancelFullScreen();
} else if (doc.msExitFullscreen) {
doc.msExitFullscreen();
} else {
return false;
}
return true;
};
Util.getFullscreenElement = function () {
return doc.fullscreenElement || doc.webkitFullscreenElement || doc.mozFullScreenElement || doc.msFullscreenElement;
};
Util.linkProgram = function (gl, vertexSource, fragmentSource, attribLocationMap) {
// No error checking for brevity.
var vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertexSource);
gl.compileShader(vertexShader);
var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragmentSource);
gl.compileShader(fragmentShader);
var program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
for (var attribName in attribLocationMap) gl.bindAttribLocation(program, attribLocationMap[attribName], attribName);
gl.linkProgram(program);
gl.deleteShader(vertexShader);
gl.deleteShader(fragmentShader);
return program;
};
Util.getProgramUniforms = function (gl, program) {
var uniforms = {};
var uniformCount = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
var uniformName = "";
for (var i = 0; i < uniformCount; i++) {
var uniformInfo = gl.getActiveUniform(program, i);
uniformName = uniformInfo.name.replace("[0]", "");
uniforms[uniformName] = gl.getUniformLocation(program, uniformName);
}
return uniforms;
};
Util.orthoMatrix = function (out, left, right, bottom, top, near, far) {
var lr = 1 / (left - right);
var bt = 1 / (bottom - top);
var nf = 1 / (near - far);
out[0] = -2 * lr;
out[1] = 0;
out[2] = 0;
out[3] = 0;
out[4] = 0;
out[5] = -2 * bt;
out[6] = 0;
out[7] = 0;
out[8] = 0;
out[9] = 0;
out[10] = 2 * nf;
out[11] = 0;
out[12] = (left + right) * lr;
out[13] = (top + bottom) * bt;
out[14] = (far + near) * nf;
out[15] = 1;
return out;
};
Util.copyArray = function (source, dest) {
for (var i = 0, n = source.length; i < n; i++) {
dest[i] = source[i];
}
};
Util.isMobile = function () {
var check = false;
(function (a) {
if (/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0, 4))) check = true;
})(userAgent$1 || (nav === null || nav === void 0 ? void 0 : nav.vendor) || win.opera);
return check;
};
Util.extend = function (dest, src) {
for (var key in src) {
if (src.hasOwnProperty(key)) {
dest[key] = src[key];
}
}
return dest;
};
Util.safariCssSizeWorkaround = function (canvas) {
// TODO(smus): Remove this workaround when Safari for iOS is fixed.
// iOS only workaround (for https://bugs.webkit.org/show_bug.cgi?id=152556).
//
// "To the last I grapple with thee;
// from hell's heart I stab at thee;
// for hate's sake I spit my last breath at thee."
// -- Moby Dick, by Herman Melville
if (Util.isIOS()) {
var width_1 = canvas.style.width;
var height_1 = canvas.style.height;
canvas.style.width = parseInt(width_1) + 1 + "px";
canvas.style.height = parseInt(height_1) + "px";
setTimeout(function () {
canvas.style.width = width_1;
canvas.style.height = height_1;
}, 100);
} // Debug only.
win.Util = Util;
win.canvas = canvas;
};
Util.isDebug = function () {
return Util.getQueryParameter("debug");
};
Util.getQueryParameter = function (name) {
name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
var regex = new RegExp("[\\?&]" + name + "=([^&#]*)");
var results = regex.exec(location.search);
return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
};
Util.frameDataFromPose = function () {
var piOver180 = Math.PI / 180.0;
var rad45 = Math.PI * 0.25; // Borrowed from glMatrix.
function mat4_perspectiveFromFieldOfView(out, fov, near, far) {
var upTan = Math.tan(fov ? fov.upDegrees * piOver180 : rad45);
var downTan = Math.tan(fov ? fov.downDegrees * piOver180 : rad45);
var leftTan = Math.tan(fov ? fov.leftDegrees * piOver180 : rad45);
var rightTan = Math.tan(fov ? fov.rightDegrees * piOver180 : rad45);
var xScale = 2.0 / (leftTan + rightTan);
var yScale = 2.0 / (upTan + downTan);
out[0] = xScale;
out[1] = 0.0;
out[2] = 0.0;
out[3] = 0.0;
out[4] = 0.0;
out[5] = yScale;
out[6] = 0.0;
out[7] = 0.0;
out[8] = -((leftTan - rightTan) * xScale * 0.5);
out[9] = (upTan - downTan) * yScale * 0.5;
out[10] = far / (near - far);
out[11] = -1.0;
out[12] = 0.0;
out[13] = 0.0;
out[14] = far * near / (near - far);
out[15] = 0.0;
return out;
}
function mat4_fromRotationTranslation(out, q, v) {
// Quaternion math
var x = q[0];
var y = q[1];
var z = q[2];
var w = q[3];
var x2 = x + x;
var y2 = y + y;
var z2 = z + z;
var xx = x * x2;
var xy = x * y2;
var xz = x * z2;
var yy = y * y2;
var yz = y * z2;
var zz = z * z2;
var wx = w * x2;
var wy = w * y2;
var wz = w * z2;
out[0] = 1 - (yy + zz);
out[1] = xy + wz;
out[2] = xz - wy;
out[3] = 0;
out[4] = xy - wz;
out[5] = 1 - (xx + zz);
out[6] = yz + wx;
out[7] = 0;
out[8] = xz + wy;
out[9] = yz - wx;
out[10] = 1 - (xx + yy);
out[11] = 0;
out[12] = v[0];
out[13] = v[1];
out[14] = v[2];
out[15] = 1;
return out;
}
function mat4_translate(out, a, v) {
var x = v[0];
var y = v[1];
var z = v[2];
var a00;
var a01;
var a02;
var a03;
var a10;
var a11;
var a12;
var a13;
var a20;
var a21;
var a22;
var a23;
if (a === out) {
out[12] = a[0] * x + a[4] * y + a[8] * z + a[12];
out[13] = a[1] * x + a[5] * y + a[9] * z + a[13];
out[14] = a[2] * x + a[6] * y + a[10] * z + a[14];
out[15] = a[3] * x + a[7] * y + a[11] * z + a[15];
} else {
a00 = a[0];
a01 = a[1];
a02 = a[2];
a03 = a[3];
a10 = a[4];
a11 = a[5];
a12 = a[6];
a13 = a[7];
a20 = a[8];
a21 = a[9];
a22 = a[10];
a23 = a[11];
out[0] = a00;
out[1] = a01;
out[2] = a02;
out[3] = a03;
out[4] = a10;
out[5] = a11;
out[6] = a12;
out[7] = a13;
out[8] = a20;
out[9] = a21;
out[10] = a22;
out[11] = a23;
out[12] = a00 * x + a10 * y + a20 * z + a[12];
out[13] = a01 * x + a11 * y + a21 * z + a[13];
out[14] = a02 * x + a12 * y + a22 * z + a[14];
out[15] = a03 * x + a13 * y + a23 * z + a[15];
}
return out;
}
function mat4_invert(out, a) {
var a00 = a[0];
var a01 = a[1];
var a02 = a[2];
var a03 = a[3];
var a10 = a[4];
var a11 = a[5];
var a12 = a[6];
var a13 = a[7];
var a20 = a[8];
var a21 = a[9];
var a22 = a[10];
var a23 = a[11];
var a30 = a[12];
var a31 = a[13];
var a32 = a[14];
var a33 = a[15];
var b00 = a00 * a11 - a01 * a10;
var b01 = a00 * a12 - a02 * a10;
var b02 = a00 * a13 - a03 * a10;
var b03 = a01 * a12 - a02 * a11;
var b04 = a01 * a13 - a03 * a11;
var b05 = a02 * a13 - a03 * a12;
var b06 = a20 * a31 - a21 * a30;
var b07 = a20 * a32 - a22 * a30;
var b08 = a20 * a33 - a23 * a30;
var b09 = a21 * a32 - a22 * a31;
var b10 = a21 * a33 - a23 * a31;
var b11 = a22 * a33 - a23 * a32; // Calculate the determinant
var det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
if (!det) {
return null;
}
det = 1.0 / det;
out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;
out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det;
out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det;
out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det;
out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det;
out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det;
out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det;
out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det;
out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det;
out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det;
out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det;
out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det;
out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det;
out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det;
out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det;
out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det;
return out;
}
var defaultOrientation = new Float32Array([0, 0, 0, 1]);
var defaultPosition = new Float32Array([0, 0, 0]);
function updateEyeMatrices(projection, view, pose, parameters, vrDisplay) {
mat4_perspectiveFromFieldOfView(projection, parameters ? parameters.fieldOfView : null, vrDisplay.depthNear, vrDisplay.depthFar);
var orientation = pose.orientation || defaultOrientation;
var position = pose.position || defaultPosition;
mat4_fromRotationTranslation(view, orientation, position);
if (parameters) mat4_translate(view, view, parameters.offset);
mat4_invert(view, view);
}
return function (frameData, pose, vrDisplay) {
if (!frameData || !pose) return false;
frameData.pose = pose;
frameData.timestamp = pose.timestamp;
updateEyeMatrices(frameData.leftProjectionMatrix, frameData.leftViewMatrix, pose, vrDisplay.getEyeParameters("left"), vrDisplay);
updateEyeMatrices(frameData.rightProjectionMatrix, frameData.rightViewMatrix, pose, vrDisplay.getEyeParameters("right"), vrDisplay);
return true;
};
}();
Util.isInsideCrossDomainIFrame = function () {
var isFramed = win.self !== win.top;
var refDomain = Util.getDomainFromUrl(doc.referrer);
var thisDomain = Util.getDomainFromUrl(win.location.href);
return isFramed && refDomain !== thisDomain;
}; // From http://stackoverflow.com/a/23945027.
Util.getDomainFromUrl = function (url) {
var domain; // Find & remove protocol (http, ftp, etc.) and get domain.
if (url.indexOf("://") > -1) {
domain = url.split("/")[2];
} else {
domain = url.split("/")[0];
} // find & remove port number
domain = domain.split(":")[0];
return domain;
};
/* eslint-disable */
/**
* Given an orientation and the gyroscope data, predicts the future orientation
* of the head. This makes rendering appear faster.
*
* Also see: http://msl.cs.uiuc.edu/~lavalle/papers/LavYerKatAnt14.pdf
* @param {Number} predictionTimeS time from head movement to the appearance of
* the corresponding image.
*/
var PosePredictor =
/*#__PURE__*/
function () {
function PosePredictor(predictionTimeS) {
this.predictionTimeS = predictionTimeS; // The quaternion corresponding to the previous state.
this.previousQ = new MathUtil.Quaternion(); // Previous time a prediction occurred.
this.previousTimestampS = null; // The delta quaternion that adjusts the current pose.
this.deltaQ = new MathUtil.Quaternion(); // The output quaternion.
this.outQ = new MathUtil.Quaternion();
}
var __proto = PosePredictor.prototype;
__proto.getPrediction = function (currentQ, gyro, timestampS) {
if (!this.previousTimestampS) {
this.previousQ.copy(currentQ);
this.previousTimestampS = timestampS;
return currentQ;
} // Calculate axis and angle based on gyroscope rotation rate data.
var axis = new MathUtil.Vector3();
axis.copy(gyro);
axis.normalize();
var angularSpeed = gyro.length(); // If we're rotating slowly, don't do prediction.
if (angularSpeed < MathUtil.degToRad * 20) {
if (Util.isDebug()) {
console.log("Moving slowly, at %s deg/s: no prediction", (MathUtil.radToDeg * angularSpeed).toFixed(1));
}
this.outQ.copy(currentQ);
this.previousQ.copy(currentQ);
return this.outQ;
} // Get the predicted angle based on the time delta and latency.
var deltaT = timestampS - this.previousTimestampS;
var predictAngle = angularSpeed * this.predictionTimeS;
this.deltaQ.setFromAxisAngle(axis, predictAngle);
this.outQ.copy(this.previousQ);
this.outQ.multiply(this.deltaQ);
this.previousQ.copy(currentQ);
this.previousTimestampS = timestampS;
return this.outQ;
};
return PosePredictor;
}();
var STILLNESS_THRESHOLD = 200; // millisecond
var DeviceMotion =
/*#__PURE__*/
function (_super) {
__extends(DeviceMotion, _super);
function DeviceMotion() {
var _this = _super.call(this) || this;
_this._onDeviceMotion = _this._onDeviceMotion.bind(_this);
_this._onDeviceOrientation = _this._onDeviceOrientation.bind(_this);
_this._onChromeWithoutDeviceMotion = _this._onChromeWithoutDeviceMotion.bind(_this);
_this.isWithoutDeviceMotion = IS_CHROME_WITHOUT_DEVICE_MOTION;
_this.isAndroid = IS_ANDROID;
_this.stillGyroVec = glMatrix.vec3.create();
_this.rawGyroVec = glMatrix.vec3.create();
_this.adjustedGyroVec = glMatrix.vec3.create();
_this._timer = -1;
_this.lastDevicemotionTimestamp = 0;
_this._isEnabled = false;
_this.enable();
return _this;
}
var __proto = DeviceMotion.prototype;
__proto.enable = function () {
if (this.isAndroid) {
win.addEventListener("deviceorientation", this._onDeviceOrientation);
}
if (this.isWithoutDeviceMotion) {
win.addEventListener("deviceorientation", this._onChromeWithoutDeviceMotion);
} else {
win.addEventListener("devicemotion", this._onDeviceMotion);
}
this._isEnabled = true;
};
__proto.disable = function () {
win.removeEventListener("deviceorientation", this._onDeviceOrientation);
win.removeEventListener("deviceorientation", this._onChromeWithoutDeviceMotion);
win.removeEventListener("devicemotion", this._onDeviceMotion);
this._isEnabled = false;
};
__proto._onChromeWithoutDeviceMotion = function (e) {
var alpha = e.alpha,
beta = e.beta,
gamma = e.gamma; // There is deviceorientation event trigged with empty values
// on Headless Chrome.
if (alpha === null) {
return;
} // convert to radian
alpha = (alpha || 0) * Math.PI / 180;
beta = (beta || 0) * Math.PI / 180;
gamma = (gamma || 0) * Math.PI / 180;
this.trigger(new Component.ComponentEvent("devicemotion", {
inputEvent: {
deviceorientation: {
alpha: alpha,
beta: beta,
gamma: -gamma
}
}
}));
};
__proto._onDeviceOrientation = function () {
var _this = this;
if (this._timer) {
clearTimeout(this._timer);
}
this._timer = win.setTimeout(function () {
if (new Date().getTime() - _this.lastDevicemotionTimestamp < STILLNESS_THRESHOLD) {
glMatrix.vec3.copy(_this.stillGyroVec, _this.rawGyroVec);
}
}, STILLNESS_THRESHOLD);
};
__proto._onDeviceMotion = function (e) {
// desktop chrome triggers devicemotion event with empthy sensor values.
// Those events should ignored.
var isGyroSensorAvailable = !(e.rotationRate.alpha == null);
var isGravitySensorAvailable = !(e.accelerationIncludingGravity.x == null);
if (e.interval === 0 || !(isGyroSensorAvailable && isGravitySensorAvailable)) {
return;
}
var devicemotionEvent = __assign({}, e);
devicemotionEvent.interval = e.interval;
devicemotionEvent.timeStamp = e.timeStamp;
devicemotionEvent.type = e.type;
devicemotionEvent.rotationRate = {
alpha: e.rotationRate.alpha,
beta: e.rotationRate.beta,
gamma: e.rotationRate.gamma
};
devicemotionEvent.accelerationIncludingGravity = {
x: e.accelerationIncludingGravity.x,
y: e.accelerationIncludingGravity.y,
z: e.accelerationIncludingGravity.z
};
devicemotionEvent.acceleration = {
x: e.acceleration.x,
y: e.acceleration.y,
z: e.acceleration.z
};
if (this.isAndroid) {
glMatrix.vec3.set(this.rawGyroVec, e.rotationRate.alpha || 0, e.rotationRate.beta || 0, e.rotationRate.gamma || 0);
glMatrix.vec3.subtract(this.adjustedGyroVec, this.rawGyroVec, this.stillGyroVec);
this.lastDevicemotionTimestamp = new Date().getTime();
devicemotionEvent.adjustedRotationRate = {
alpha: this.adjustedGyroVec[0],
beta: this.adjustedGyroVec[1],
gamma: this.adjustedGyroVec[2]
};
}
this.trigger(new Component.ComponentEvent("devicemotion", {
inputEvent: devicemotionEvent
}));
};
return DeviceMotion;
}(Component);
var SensorSample =
/*#__PURE__*/
function () {
function SensorSample(sample, timestampS) {
this.set(sample, timestampS);
}
var __proto = SensorSample.prototype;
__proto.set = function (sample, timestampS) {
this.sample = sample;
this.timestampS = timestampS;
};
__proto.copy = function (sensorSample) {
this.set(sensorSample.sample, sensorSample.timestampS);
};
return SensorSample;
}();
/* eslint-disable */
/**
* An implementation of a simple complementary filter, which fuses gyroscope and
* accelerometer data from the 'devicemotion' event.
*
* Accelerometer data is very noisy, but stable over the long term.
* Gyroscope data is smooth, but tends to drift over the long term.
*
* This fusion is relatively simple:
* 1. Get orientation estimates from accelerometer by applying a low-pass filter
* on that data.
* 2. Get orientation estimates from gyroscope by integrating over time.
* 3. Combine the two estimates, weighing (1) in the long term, but (2) for the
* short term.
*/
var ComplementaryFilter =
/*#__PURE__*/
function () {
function ComplementaryFilter(kFilter) {
this.addGyroMeasurement = function (vector, timestampS) {
this.currentGyroMeasurement.set(vector, timestampS);
var deltaT = timestampS - this.previousGyroMeasurement.timestampS;
if (Util.isTimestampDeltaValid(deltaT)) {
this.run_();
}
this.previousGyroMeasurement.copy(this.currentGyroMeasurement);
};
this.kFilter = kFilter; // Raw sensor measurements.
this.currentAccelMeasurement = new SensorSample();
this.currentGyroMeasurement = new SensorSample();
this.previousGyroMeasurement = new SensorSample(); // Set default look direction to be in the correct direction.
if (Util.isIOS()) {
this.filterQ = new MathUtil.Quaternion(-1, 0, 0, 1);
} else {
this.filterQ = new MathUtil.Quaternion(1, 0, 0, 1);
}
this.previousFilterQ = new MathUtil.Quaternion();
this.previousFilterQ.copy(this.filterQ); // Orientation based on the accelerometer.
this.accelQ = new MathUtil.Quaternion(); // Whether or not the orientation has been initialized.
this.isOrientationInitialized = false; // Running estimate of gravity based on the current orientation.
this.estimatedGravity = new MathUtil.Vector3(); // Measured gravity based on accelerometer.
this.measuredGravity = new MathUtil.Vector3(); // Debug only quaternion of g