Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

webvr-polyfill

Package Overview
Dependencies
Maintainers
3
Versions
59
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

webvr-polyfill - npm Package Compare versions

Comparing version 0.9.41 to 0.10.0

.babelrc

36

package.json
{
"name": "webvr-polyfill",
"version": "0.9.41",
"version": "0.10.0",
"homepage": "https://github.com/googlevr/webvr-polyfill",

@@ -12,10 +12,19 @@ "authors": [

"devDependencies": {
"babel-core": "^6.24.1",
"babel-plugin-external-helpers": "^6.22.0",
"babel-preset-env": "^1.6.1",
"chai": "^3.5.0",
"jsdom": "^9.12.0",
"localStorage": "^1.0.3",
"mocha": "^3.2.0",
"semver": "^5.3.0",
"webpack": "^2.6.1",
"webpack-dev-server": "2.7.1"
"rollup": "^0.52.1",
"rollup-plugin-babel": "^3.0.2",
"rollup-plugin-cleanup": "^2.0.0",
"rollup-plugin-commonjs": "^8.2.6",
"rollup-plugin-json": "^2.3.0",
"rollup-plugin-node-resolve": "^3.0.0",
"rollup-plugin-uglify": "^2.0.1",
"semver": "^5.3.0"
},
"main": "src/node-entry",
"main": "build/webvr-polyfill.js",
"keywords": [

@@ -27,6 +36,10 @@ "vr",

"scripts": {
"start": "npm run watch",
"watch": "webpack-dev-server",
"build": "webpack",
"test": "mocha"
"build": "rollup -c",
"build-min": "rollup -c rollup.config.min.js",
"build-all": "npm run build && npm run build-min",
"watch": "rollup -c -w",
"test": "mocha -r test/init.js --compilers js:babel-core/register test/*.test.js",
"preversion": "npm test",
"version": "npm run build-all && git add build/*",
"postversion": "git push && git push --tags && npm publish"
},

@@ -36,3 +49,6 @@ "repository": "googlevr/webvr-polyfill",

"url": "https://github.com/googlevr/webvr-polyfill/issues"
},
"dependencies": {
"cardboard-vr-display": "1.0.2"
}
}
}

@@ -6,138 +6,111 @@ # WebVR Polyfill

A JavaScript implementation of the [WebVR spec][spec]. This project ensures
your WebVR content works on any platform, whether or not the browser/device has
native WebVR support, or when there are inconsistencies in implementation.
A JavaScript implementation of the [WebVR spec][spec]. This project lets you use
WebVR today, without requiring a [special][moz] [browser][cr] build. It also
lets you view the same content without requiring a virtual reality viewer.
Take a look at [basic WebVR samples][samples] that use this polyfill.
[moz]: http://mozvr.com/
[cr]: https://drive.google.com/folderview?id=0BzudLt22BqGRbW9WTHMtOWMzNjQ
[samples]: https://webvr.info/samples/
[spec]: https://mozvr.github.io/webvr-spec/
## Installing
## Implementation
### Script
The polyfill decides which VRDisplays to provide, depending on the configuration
of your browser. Mobile devices provide the `CardboardVRDisplay`. Desktop devices
use the `MouseKeyboardVRDisplay`.
Download the build at [dist/webvr-polyfill.js](dist/webvr-polyfill.js) and include it as a script tag,
or use a CDN. You can also use the minified file in the same location as `webvr-polyfill.min.js`.
`CardboardVRDisplay` uses DeviceMotionEvents to implement a complementary
filter which does [sensor fusion and pose prediction][fusion] to provide
orientation tracking. It can also render in stereo mode, and includes mesh-based
lens distortion. This display also includes user interface elements in VR mode
to make the VR experience more intuitive, including:
```html
<script src='webvr-polyfill.js'></script>
<!-- or use a link to a CDN -->
<script src='https://cdn.jsdelivr.net/npm/webvr-polyfill@latest/build/webvr-polyfill.js'></script>
```
- A gear icon to select your VR viewer.
- A back button to exit VR mode.
- An interstitial which only appears in portrait orientation, requesting you switch
into landscape orientation (if [orientation lock][ol] is not available).
### npm
`MouseKeyboardVRDisplay` uses mouse events to allow you to do the equivalent of
mouselook. It also uses keyboard arrows keys to look around the scene
with the keyboard.
If you're using a build tool like [browserify] or [webpack], install it via [npm].
[fusion]: http://smus.com/sensor-fusion-prediction-webvr/
[ol]: https://www.w3.org/TR/screen-orientation/
```
$ npm install --save webvr-polyfill
```
## Using
## Configuration
Instructions for using versions `>=0.10.0`. For `<=0.9.x` versions, see [0.9.40 tag](https://github.com/googlevr/webvr-polyfill/tree/v0.9.40).
The polyfill can be configured and debugged with various options. The following
are supported:
The webvr-polyfill exposes a single constructor, `WebVRPolyfill` that takes an
object for configuration. See full configuration options at [src/config.js](src/config.js).
```javascript
WebVRConfig = {
// Flag to disabled the UI in VR Mode.
CARDBOARD_UI_DISABLED: false, // Default: false
Be sure to instantiate the polyfill before calling any of your VR code! The
polyfill needs to patch the API if it does not exist so your content code can
assume that the WebVR API will just work.
// Forces availability of VR mode, even for non-mobile devices.
FORCE_ENABLE_VR: true, // Default: false.
If using script tags, a `WebVRPolyfill` global constructor will exist.
// Complementary filter coefficient. 0 for accelerometer, 1 for gyro.
K_FILTER: 0.98, // Default: 0.98.
```js
var polyfill = new WebVRPolyfill();
```
// Flag to disable the instructions to rotate your device.
ROTATE_INSTRUCTIONS_DISABLED: false, // Default: false.
In a modular ES6 world, import and instantiate the constructor similarly.
// How far into the future to predict during fast motion (in seconds).
PREDICTION_TIME_S: 0.040, // Default: 0.040.
```js
import WebVRPolyfill from 'webvr-polyfill';
const polyfill = WebVRPolyfill();
```
// Flag to disable touch panner. In case you have your own touch controls.
TOUCH_PANNER_DISABLED: false, // Default: true.
## Goals
// Enable yaw panning only, disabling roll and pitch. This can be useful
// for panoramas with nothing interesting above or below.
YAW_ONLY: true, // Default: false.
The polyfill's goal is to provide a library so that developers can create
content targeting the WebVR API without worrying about what browsers and devices
their users have in a world of growing, [but fragmented](caniuse) support.
// To disable keyboard and mouse controls, if you want to use your own
// implementation.
MOUSE_KEYBOARD_CONTROLS_DISABLED: true, // Default: false.
The three main components of the polyfill are:
// Prevent the polyfill from initializing immediately. Requires the app
// to call InitializeWebVRPolyfill() before it can be used.
DEFER_INITIALIZATION: true, // Default: false.
* Injects a [WebVR 1.1](spec) JavaScript implementation if one does not exist
* Patches browsers that have an incomplete or inconsistent implementation of the API
* Provide a synthesized [CardboardVRDisplay] on mobile when WebVR is not supported, or if it does have native support but no native VRDisplays and `PROVIDE_MOBILE_VRDISPLAY` is true (default).
// Enable the deprecated version of the API (navigator.getVRDevices).
ENABLE_DEPRECATED_API: true, // Default: false.
## Performance
// Scales the recommended buffer size reported by WebVR, which can improve
// performance.
BUFFER_SCALE: 0.5, // Default: 0.5.
Performance is critical for VR. If you find your application is too sluggish,
consider tweaking some of the above parameters. In particular, keeping
`BUFFER_SCALE` at 0.5 (the default) will likely help a lot.
// Allow VRDisplay.submitFrame to change gl bindings, which is more
// efficient if the application code will re-bind its resources on the
// next frame anyway. This has been seen to cause rendering glitches with
// THREE.js.
// Dirty bindings include: gl.FRAMEBUFFER_BINDING, gl.CURRENT_PROGRAM,
// gl.ARRAY_BUFFER_BINDING, gl.ELEMENT_ARRAY_BUFFER_BINDING,
// and gl.TEXTURE_BINDING_2D for texture unit 0.
DIRTY_SUBMIT_FRAME_BINDINGS: true, // Default: false.
## Developing
// When set to true, this will cause a polyfilled VRDisplay to always be
// appended to the list returned by navigator.getVRDisplays(), even if that
// list includes a native VRDisplay.
ALWAYS_APPEND_POLYFILL_DISPLAY: false,
If you're interested in developing and contributing on the polyfill itself, you'll need to
have [npm] installed and familiarize yourself with some commands below. For full list
of commands available, see `package.json` scripts.
// There are versions of Chrome (M58-M60?) where the native WebVR API exists,
// and instead of returning 0 VR displays when none are detected,
// `navigator.getVRDisplays()`'s promise never resolves. This results
// in the polyfill hanging and not being able to provide fallback
// displays, so set a timeout in milliseconds to stop waiting for a response
// and just use polyfilled displays.
// https://bugs.chromium.org/p/chromium/issues/detail?id=727969
GET_VR_DISPLAYS_TIMEOUT: 1000,
}
```
$ git clone git@github.com:googlevr/webvr-polyfill.git
$ cd webvr-polyfill/
## Performance
# Install dependencies
$ npm install
Performance is critical for VR. If you find your application is too sluggish,
consider tweaking some of the above parameters. In particular, keeping
`BUFFER_SCALE` at 0.5 (the default) will likely help a lot.
# Build uncompressed JS file
$ npm run build
## WebVR 1.1 Shim
# Run tests
$ npm test
The polyfill exposes a helper method `WebVRPolyfill.InstallWebVRSpecShim` which
installs a shim that updates a WebVR 1.0 spec implementation to WebVR 1.1.
# Watch src/* directory and auto-rebuild on changes
$ npm watch
```
## Development
### Testing
If you'd like to contribute to the `webvr-poyfill` library, check out
the repository and install
[Node](https://nodejs.org/en/download/package-manager/) and the dependencies:
Right now there are some unit tests in the configuration and logic for how things get polyfilled.
Be sure to run tests before submitting any PRs, and bonus points for having new tests!
```bash
git clone https://github.com/googlevr/webvr-polyfill
cd webvr-polyfill
npm install
```
$ npm test
```
### Development Commands
Due to the nature of the polyfill, be also sure to test the examples with your changes where appropriate.
* `npm install`: installs the dependencies.
* `npm start`: auto-builds the module whenever any source changes and serves the example
content on `http://0.0.0.0:8080/`.
* `npm run build`: builds the module.
### Releasing a new version
For maintainers only, to cut a new release for npm, use the [npm version] command. The `preversion`, `version` and `postversion` npm scripts will run tests, build, add built files and tag to git, push to github, and publish the new npm version.
`npm version <semverstring>`
## License

@@ -148,16 +121,8 @@

## Thanks
- [Brandon Jones][bj] and [Vladimir Vukicevic][vv] for their work on the [WebVR
spec][spec].
- [Ricardo Cabello][doob] for THREE.js.
- [Diego Marcos][dm] for VREffect and VRControls.
- [Dmitriy Kovalev][dk] for help with lens distortion correction.
[dk]: https://github.com/dmitriykovalev/
[bj]: https://twitter.com/tojiro
[vv]: https://twitter.com/vvuk
[spec]: https://mozvr.github.io/webvr-spec/
[dm]: https://twitter.com/dmarcos
[doob]: https://twitter.com/mrdoob
[samples]: https://webvr.info/samples/
[npm]: https://www.npmjs.com
[browserify]: http://browserify.org/
[webpack]: https://webpack.github.io/
[caniuse]: https://caniuse.com/#search=webvr
[spec]: https://immersive-web.github.io/webvr/spec/1.1
[CardboardVRDisplay]: https://github.com/googlevr/cardboard-vr-display

@@ -18,9 +18,2 @@ /*

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) {

@@ -30,6 +23,2 @@ return Math.min(Math.max(min, value), max);

Util.lerp = function(a, b, t) {
return a + ((b - a) * t);
};
/**

@@ -54,171 +43,11 @@ * Light polyfill for `Promise.race`. Returns

Util.isIOS = (function() {
var isIOS = /iPad|iPhone|iPod/.test(navigator.platform);
return function() {
return isIOS;
};
})();
Util.isWebViewAndroid = (function() {
var isWebViewAndroid = navigator.userAgent.indexOf('Version') !== -1 &&
navigator.userAgent.indexOf('Android') !== -1 &&
navigator.userAgent.indexOf('Chrome') !== -1;
return function() {
return isWebViewAndroid;
};
})();
Util.isSafari = (function() {
var isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
return function() {
return isSafari;
};
})();
Util.isFirefoxAndroid = (function() {
var isFirefoxAndroid = navigator.userAgent.indexOf('Firefox') !== -1 &&
navigator.userAgent.indexOf('Android') !== -1;
return function() {
return isFirefoxAndroid;
};
})();
Util.isR7 = (function() {
var isR7 = navigator.userAgent.indexOf('R7 Build') !== -1;
return function() {
return isR7;
};
})();
Util.isLandscapeMode = function() {
var rtn = (window.orientation == 90 || window.orientation == -90);
return Util.isR7() ? !rtn : rtn;
Util.isIOS = function() {
return /iPad|iPhone|iPod/.test(navigator.platform);
};
// 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.isMobile = function() {
return /Android/i.test(navigator.userAgent) ||
/iPhone|iPad|iPod/i.test(navigator.userAgent);
};
Util.getScreenWidth = function() {
return Math.max(window.screen.width, window.screen.height) *
window.devicePixelRatio;
};
Util.getScreenHeight = function() {
return Math.min(window.screen.width, window.screen.height) *
window.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 (document.exitFullscreen) {
document.exitFullscreen();
} else if (document.webkitExitFullscreen) {
document.webkitExitFullscreen();
} else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen();
} else if (document.msExitFullscreen) {
document.msExitFullscreen();
} else {
return false;
}
return true;
};
Util.getFullscreenElement = function() {
return document.fullscreenElement ||
document.webkitFullscreenElement ||
document.mozFullScreenElement ||
document.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),
bt = 1 / (bottom - top),
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) {

@@ -230,8 +59,2 @@ for (var i = 0, n = source.length; i < n; 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})(navigator.userAgent||navigator.vendor||window.opera);
return check;
};
Util.extend = function(dest, src) {

@@ -247,240 +70,9 @@ for (var key in src) {

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 = canvas.style.width;
var height = canvas.style.height;
canvas.style.width = (parseInt(width) + 1) + 'px';
canvas.style.height = (parseInt(height)) + 'px';
setTimeout(function() {
canvas.style.width = width;
canvas.style.height = height;
}, 100);
}
// Debug only.
window.Util = Util;
window.canvas = canvas;
Util.isFullScreenAvailable = function() {
return (document.fullscreenEnabled ||
document.mozFullScreenEnabled ||
document.webkitFullscreenEnabled ||
false);
};
Util.isDebug = function() {
return Util.getQueryParameter('debug');
};
Util.getQueryParameter = function(name) {
var name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
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),
downTan = Math.tan(fov ? (fov.downDegrees * piOver180) : rad45),
leftTan = Math.tan(fov ? (fov.leftDegrees * piOver180) : rad45),
rightTan = Math.tan(fov ? (fov.rightDegrees * piOver180) : rad45),
xScale = 2.0 / (leftTan + rightTan),
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], y = q[1], z = q[2], w = q[3],
x2 = x + x,
y2 = y + y,
z2 = z + z,
xx = x * x2,
xy = x * y2,
xz = x * z2,
yy = y * y2,
yz = y * z2,
zz = z * z2,
wx = w * x2,
wy = w * y2,
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], y = v[1], z = v[2],
a00, a01, a02, a03,
a10, a11, a12, a13,
a20, a21, a22, 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], 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],
a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15],
b00 = a00 * a11 - a01 * a10,
b01 = a00 * a12 - a02 * a10,
b02 = a00 * a13 - a03 * a10,
b03 = a01 * a12 - a02 * a11,
b04 = a01 * a13 - a03 * a11,
b05 = a02 * a13 - a03 * a12,
b06 = a20 * a31 - a21 * a30,
b07 = a20 * a32 - a22 * a30,
b08 = a20 * a33 - a23 * a30,
b09 = a21 * a32 - a22 * a31,
b10 = a21 * a33 - a23 * a31,
b11 = a22 * a33 - a23 * a32,
// Calculate the determinant
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 = (window.self !== window.top);
var refDomain = Util.getDomainFromUrl(document.referrer);
var thisDomain = Util.getDomainFromUrl(window.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;
}
module.exports = Util;

@@ -17,102 +17,75 @@ /*

var Util = require('./util.js');
var CardboardVRDisplay = require('./cardboard-vr-display.js');
var MouseKeyboardVRDisplay = require('./mouse-keyboard-vr-display.js');
// Uncomment to add positional tracking via webcam.
//var WebcamPositionSensorVRDevice = require('./webcam-position-sensor-vr-device.js');
var VRDisplay = require('./base.js').VRDisplay;
var VRFrameData = require('./base.js').VRFrameData;
var HMDVRDevice = require('./base.js').HMDVRDevice;
var PositionSensorVRDevice = require('./base.js').PositionSensorVRDevice;
var VRDisplayHMDDevice = require('./display-wrappers.js').VRDisplayHMDDevice;
var VRDisplayPositionSensorDevice = require('./display-wrappers.js').VRDisplayPositionSensorDevice;
var CardboardVRDisplay = require('cardboard-vr-display');
var VRDisplay = require('cardboard-vr-display/src/base.js').VRDisplay;
var VRFrameData = require('cardboard-vr-display/src/base.js').VRFrameData;
var version = require('../package.json').version;
var DefaultConfig = require('./config');
function WebVRPolyfill() {
this.displays = [];
this.devices = []; // For deprecated objects
this.devicesPopulated = false;
this.nativeWebVRAvailable = this.isWebVRAvailable();
this.nativeLegacyWebVRAvailable = this.isDeprecatedWebVRAvailable();
this.nativeGetVRDisplaysFunc = this.nativeWebVRAvailable ?
navigator.getVRDisplays :
null;
function WebVRPolyfill(config) {
this.config = Util.extend(Util.extend({}, DefaultConfig), config);
this.polyfillDisplays = [];
this.enabled = false;
if (!this.nativeLegacyWebVRAvailable && !this.nativeWebVRAvailable) {
this.enablePolyfill();
if (window.WebVRConfig.ENABLE_DEPRECATED_API) {
this.enableDeprecatedPolyfill();
}
// Must handle this in constructor before we start
// destructively polyfilling `navigator`
this.hasNative = 'getVRDisplays' in navigator;
// Store initial references to native constructors
// and functions
this.native = {};
this.native.getVRDisplays = navigator.getVRDisplays;
this.native.VRFrameData = window.VRFrameData;
this.native.VRDisplay = window.VRDisplay;
// If we don't have native 1.1 support, or if we want to provide
// a CardboardVRDisplay in the event of native support with no displays,
// inject our own polyfill
if (!this.hasNative || this.config.PROVIDE_MOBILE_VRDISPLAY && Util.isMobile()) {
this.enable();
}
// Put a shim in place to update the API to 1.1 if needed.
InstallWebVRSpecShim();
}
WebVRPolyfill.prototype.isWebVRAvailable = function() {
return ('getVRDisplays' in navigator);
};
WebVRPolyfill.prototype.isDeprecatedWebVRAvailable = function() {
return ('getVRDevices' in navigator) || ('mozGetVRDevices' in navigator);
};
WebVRPolyfill.prototype.connectDisplay = function(vrDisplay) {
vrDisplay.fireVRDisplayConnect_();
this.displays.push(vrDisplay);
};
WebVRPolyfill.prototype.populateDevices = function() {
if (this.devicesPopulated) {
return;
WebVRPolyfill.prototype.getPolyfillDisplays = function() {
if (this._polyfillDisplaysPopulated) {
return this.polyfillDisplays;
}
// Initialize our virtual VR devices.
var vrDisplay = null;
// Add a Cardboard VRDisplay on compatible mobile devices
if (this.isCardboardCompatible()) {
vrDisplay = new CardboardVRDisplay();
if (Util.isMobile()) {
var vrDisplay = new CardboardVRDisplay({
DEBUG: this.config.DEBUG,
DPDB_URL: this.config.DPDB_URL,
CARDBOARD_UI_DISABLED: this.config.CARDBOARD_UI_DISABLED,
K_FILTER: this.config.K_FILTER,
PREDICTION_TIME_S: this.config.PREDICTION_TIME_S,
TOUCH_PANNER_DISABLED: this.config.TOUCH_PANNER_DISABLED,
ROTATE_INSTRUCTIONS_DISABLED: this.config.ROTATE_INSTRUCTIONS_DISABLED,
YAW_ONLY: this.config.YAW_ONLY,
BUFFER_SCALE: this.config.BUFFER_SCALE,
DIRTY_SUBMIT_FRAME_BINDINGS: this.config.DIRTY_SUBMIT_FRAME_BINDINGS,
});
this.connectDisplay(vrDisplay);
// For backwards compatibility
if (window.WebVRConfig.ENABLE_DEPRECATED_API) {
this.devices.push(new VRDisplayHMDDevice(vrDisplay));
this.devices.push(new VRDisplayPositionSensorDevice(vrDisplay));
}
vrDisplay.fireVRDisplayConnect_();
this.polyfillDisplays.push(vrDisplay);
}
// Add a Mouse and Keyboard driven VRDisplay for desktops/laptops
if (!this.isMobile() && !window.WebVRConfig.MOUSE_KEYBOARD_CONTROLS_DISABLED) {
vrDisplay = new MouseKeyboardVRDisplay();
this.connectDisplay(vrDisplay);
// For backwards compatibility
if (window.WebVRConfig.ENABLE_DEPRECATED_API) {
this.devices.push(new VRDisplayHMDDevice(vrDisplay));
this.devices.push(new VRDisplayPositionSensorDevice(vrDisplay));
}
}
// Uncomment to add positional tracking via webcam.
//if (!this.isMobile() && window.WebVRConfig.ENABLE_DEPRECATED_API) {
// positionDevice = new WebcamPositionSensorVRDevice();
// this.devices.push(positionDevice);
//}
this.devicesPopulated = true;
this._polyfillDisplaysPopulated = true;
return this.polyfillDisplays;
};
WebVRPolyfill.prototype.enablePolyfill = function() {
// Provide navigator.getVRDisplays.
navigator.getVRDisplays = this.getVRDisplays.bind(this);
WebVRPolyfill.prototype.enable = function() {
this.enabled = true;
// Polyfill native VRDisplay.getFrameData
if (this.nativeWebVRAvailable && window.VRFrameData) {
var NativeVRFrameData = window.VRFrameData;
var nativeFrameData = new window.VRFrameData();
var nativeGetFrameData = window.VRDisplay.prototype.getFrameData;
window.VRFrameData = VRFrameData;
// Polyfill native VRDisplay.getFrameData when the platform
// has native WebVR support, but for use with a polyfilled
// CardboardVRDisplay
if (this.hasNative && this.native.VRFrameData) {
var NativeVRFrameData = this.native.VRFrameData;
var nativeFrameData = new this.native.VRFrameData();
var nativeGetFrameData = this.native.VRDisplay.prototype.getFrameData;
// When using a native display with a polyfilled VRFrameData
window.VRDisplay.prototype.getFrameData = function(frameData) {
// This should only be called in the event of code instantiating
// `window.VRFrameData` before the polyfill kicks in, which is
// unrecommended, but happens anyway
if (frameData instanceof NativeVRFrameData) {

@@ -137,36 +110,18 @@ nativeGetFrameData.call(this, frameData);

// Provide navigator.getVRDisplays.
navigator.getVRDisplays = this.getVRDisplays.bind(this);
// Provide the `VRDisplay` object.
window.VRDisplay = VRDisplay;
// Provide the `navigator.vrEnabled` property.
if (navigator && typeof navigator.vrEnabled === 'undefined') {
var self = this;
Object.defineProperty(navigator, 'vrEnabled', {
get: function () {
return self.isCardboardCompatible() &&
(self.isFullScreenAvailable() || Util.isIOS());
}
});
}
if (!('VRFrameData' in window)) {
// Provide the VRFrameData object.
window.VRFrameData = VRFrameData;
}
// Provide the VRFrameData object.
window.VRFrameData = VRFrameData;
};
WebVRPolyfill.prototype.enableDeprecatedPolyfill = function() {
// Provide navigator.getVRDevices.
navigator.getVRDevices = this.getVRDevices.bind(this);
// Provide the CardboardHMDVRDevice and PositionSensorVRDevice objects.
window.HMDVRDevice = HMDVRDevice;
window.PositionSensorVRDevice = PositionSensorVRDevice;
};
WebVRPolyfill.prototype.getVRDisplays = function() {
this.populateDevices();
var polyfillDisplays = this.displays;
this.getPolyfillDisplays();
var polyfillDisplays = this.polyfillDisplays;
var config = this.config;
if (!this.nativeWebVRAvailable) {
if (!this.hasNative) {
return Promise.resolve(polyfillDisplays);

@@ -178,3 +133,3 @@ }

var timeoutId;
var vrDisplaysNative = this.nativeGetVRDisplaysFunc.call(navigator);
var vrDisplaysNative = this.native.getVRDisplays.call(navigator);
var timeoutPromise = new Promise(function(resolve) {

@@ -184,3 +139,3 @@ timeoutId = setTimeout(function() {

resolve([]);
}, window.WebVRConfig.GET_VR_DISPLAYS_TIMEOUT);
}, config.GET_VR_DISPLAYS_TIMEOUT);
});

@@ -193,99 +148,8 @@

clearTimeout(timeoutId);
if (window.WebVRConfig.ALWAYS_APPEND_POLYFILL_DISPLAY) {
return nativeDisplays.concat(polyfillDisplays);
} else {
return nativeDisplays.length > 0 ? nativeDisplays : polyfillDisplays;
}
return nativeDisplays.length > 0 ? nativeDisplays : polyfillDisplays;
});
};
WebVRPolyfill.prototype.getVRDevices = function() {
console.warn('getVRDevices is deprecated. Please update your code to use getVRDisplays instead.');
var self = this;
return new Promise(function(resolve, reject) {
try {
if (!self.devicesPopulated) {
if (self.nativeWebVRAvailable) {
return navigator.getVRDisplays(function(displays) {
for (var i = 0; i < displays.length; ++i) {
self.devices.push(new VRDisplayHMDDevice(displays[i]));
self.devices.push(new VRDisplayPositionSensorDevice(displays[i]));
}
self.devicesPopulated = true;
resolve(self.devices);
}, reject);
}
if (self.nativeLegacyWebVRAvailable) {
return (navigator.getVRDDevices || navigator.mozGetVRDevices)(function(devices) {
for (var i = 0; i < devices.length; ++i) {
if (devices[i] instanceof HMDVRDevice) {
self.devices.push(devices[i]);
}
if (devices[i] instanceof PositionSensorVRDevice) {
self.devices.push(devices[i]);
}
}
self.devicesPopulated = true;
resolve(self.devices);
}, reject);
}
}
self.populateDevices();
resolve(self.devices);
} catch (e) {
reject(e);
}
});
};
WebVRPolyfill.prototype.NativeVRFrameData = window.VRFrameData;
/**
* Determine if a device is mobile.
*/
WebVRPolyfill.prototype.isMobile = function() {
return /Android/i.test(navigator.userAgent) ||
/iPhone|iPad|iPod/i.test(navigator.userAgent);
};
WebVRPolyfill.prototype.isCardboardCompatible = function() {
// For now, support all iOS and Android devices.
// Also enable the WebVRConfig.FORCE_VR flag for debugging.
return this.isMobile() || window.WebVRConfig.FORCE_ENABLE_VR;
};
WebVRPolyfill.prototype.isFullScreenAvailable = function() {
return (document.fullscreenEnabled ||
document.mozFullScreenEnabled ||
document.webkitFullscreenEnabled ||
false);
};
// Installs a shim that updates a WebVR 1.0 spec implementation to WebVR 1.1
function InstallWebVRSpecShim() {
if ('VRDisplay' in window && !('VRFrameData' in window)) {
// Provide the VRFrameData object.
window.VRFrameData = VRFrameData;
// A lot of Chrome builds don't have depthNear and depthFar, even
// though they're in the WebVR 1.0 spec. Patch them in if they're not present.
if(!('depthNear' in window.VRDisplay.prototype)) {
window.VRDisplay.prototype.depthNear = 0.01;
}
if(!('depthFar' in window.VRDisplay.prototype)) {
window.VRDisplay.prototype.depthFar = 10000.0;
}
window.VRDisplay.prototype.getFrameData = function(frameData) {
return Util.frameDataFromPose(frameData, this.getPose(), this);
}
}
};
WebVRPolyfill.InstallWebVRSpecShim = InstallWebVRSpecShim;
WebVRPolyfill.version = version;
module.exports.WebVRPolyfill = WebVRPolyfill;
module.exports = WebVRPolyfill;

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc