|
@@ -12,17 +12,26 @@
|
|
|
THREE.VREffect = function ( renderer, onError ) {
|
|
|
|
|
|
var vrHMD;
|
|
|
- var eyeTranslationL, eyeFOVL, renderRectL;
|
|
|
- var eyeTranslationR, eyeFOVR, renderRectR;
|
|
|
+ var deprecatedAPI = false;
|
|
|
+ var eyeTranslationL = new THREE.Vector3();
|
|
|
+ var eyeTranslationR = new THREE.Vector3();
|
|
|
+ var renderRectL, renderRectR;
|
|
|
+ var eyeFOVL, eyeFOVR;
|
|
|
|
|
|
function gotVRDevices( devices ) {
|
|
|
|
|
|
for ( var i = 0; i < devices.length; i ++ ) {
|
|
|
|
|
|
- if ( devices[ i ] instanceof HMDVRDevice ) {
|
|
|
+ if ( 'VRDisplay' in window && devices[ i ] instanceof VRDisplay ) {
|
|
|
|
|
|
vrHMD = devices[ i ];
|
|
|
+ deprecatedAPI = false;
|
|
|
+ break; // We keep the first we encounter
|
|
|
+
|
|
|
+ } else if ( 'HMDVRDevice' in window && devices[ i ] instanceof HMDVRDevice ) {
|
|
|
|
|
|
+ vrHMD = devices[ i ];
|
|
|
+ deprecatedAPI = true;
|
|
|
break; // We keep the first we encounter
|
|
|
|
|
|
}
|
|
@@ -37,8 +46,13 @@ THREE.VREffect = function ( renderer, onError ) {
|
|
|
|
|
|
}
|
|
|
|
|
|
- if ( navigator.getVRDevices ) {
|
|
|
+ if ( navigator.getVRDisplays ) {
|
|
|
+
|
|
|
+ navigator.getVRDisplays().then( gotVRDevices );
|
|
|
+
|
|
|
+ } else if ( navigator.getVRDevices ) {
|
|
|
|
|
|
+ // Deprecated API.
|
|
|
navigator.getVRDevices().then( gotVRDevices );
|
|
|
|
|
|
}
|
|
@@ -55,31 +69,90 @@ THREE.VREffect = function ( renderer, onError ) {
|
|
|
|
|
|
// fullscreen
|
|
|
|
|
|
- var isFullscreen = false;
|
|
|
+ var isPresenting = false;
|
|
|
|
|
|
var canvas = renderer.domElement;
|
|
|
var fullscreenchange = canvas.mozRequestFullScreen ? 'mozfullscreenchange' : 'webkitfullscreenchange';
|
|
|
|
|
|
- document.addEventListener( fullscreenchange, function ( event ) {
|
|
|
+ document.addEventListener( fullscreenchange, function () {
|
|
|
|
|
|
- isFullscreen = document.mozFullScreenElement || document.webkitFullscreenElement;
|
|
|
+ if ( vrHMD && deprecatedAPI ) {
|
|
|
+
|
|
|
+ isPresenting = document.mozFullScreenElement || document.webkitFullscreenElement;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }, false );
|
|
|
+
|
|
|
+ window.addEventListener( 'vrdisplaypresentchange', function () {
|
|
|
+
|
|
|
+ isPresenting = vrHMD && vrHMD.isPresenting;
|
|
|
|
|
|
}, false );
|
|
|
|
|
|
this.setFullScreen = function ( boolean ) {
|
|
|
|
|
|
- if ( vrHMD === undefined ) return;
|
|
|
- if ( isFullscreen === boolean ) return;
|
|
|
+ return new Promise( function ( resolve, reject ) {
|
|
|
+
|
|
|
+ if ( vrHMD === undefined ) {
|
|
|
|
|
|
- if ( canvas.mozRequestFullScreen ) {
|
|
|
+ reject( new Error( 'No VR hardware found.' ) );
|
|
|
+ return;
|
|
|
|
|
|
- canvas.mozRequestFullScreen( { vrDisplay: vrHMD } );
|
|
|
+ }
|
|
|
+ if ( isPresenting === boolean ) {
|
|
|
+
|
|
|
+ resolve();
|
|
|
+ return;
|
|
|
|
|
|
- } else if ( canvas.webkitRequestFullscreen ) {
|
|
|
+ }
|
|
|
|
|
|
- canvas.webkitRequestFullscreen( { vrDisplay: vrHMD } );
|
|
|
+ if ( !deprecatedAPI ) {
|
|
|
|
|
|
- }
|
|
|
+ if ( boolean ) {
|
|
|
+
|
|
|
+ resolve( vrHMD.requestPresent( { source: canvas } ) );
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+ resolve( vrHMD.exitPresent() );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+ if ( canvas.mozRequestFullScreen ) {
|
|
|
+
|
|
|
+ canvas.mozRequestFullScreen( { vrDisplay: vrHMD } );
|
|
|
+ resolve();
|
|
|
+
|
|
|
+ } else if ( canvas.webkitRequestFullscreen ) {
|
|
|
+
|
|
|
+ canvas.webkitRequestFullscreen( { vrDisplay: vrHMD } );
|
|
|
+ resolve();
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+ console.error( 'No compatible requestFullscreen method found.' );
|
|
|
+ reject( new Error( 'No compatible requestFullscreen method found.' ) );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ });
|
|
|
+
|
|
|
+ };
|
|
|
+
|
|
|
+ this.requestPresent = function () {
|
|
|
+
|
|
|
+ return this.setFullScreen( true );
|
|
|
+
|
|
|
+ };
|
|
|
+
|
|
|
+ this.exitPresent = function () {
|
|
|
+
|
|
|
+ return this.setFullScreen( false );
|
|
|
|
|
|
};
|
|
|
|
|
@@ -93,17 +166,35 @@ THREE.VREffect = function ( renderer, onError ) {
|
|
|
|
|
|
this.render = function ( scene, camera ) {
|
|
|
|
|
|
- if ( vrHMD ) {
|
|
|
+ if ( vrHMD && isPresenting ) {
|
|
|
+
|
|
|
+ var autoUpdate = scene.autoUpdate;
|
|
|
+
|
|
|
+ if ( autoUpdate ) {
|
|
|
+
|
|
|
+ scene.updateMatrixWorld();
|
|
|
+ scene.autoUpdate = false;
|
|
|
+
|
|
|
+ }
|
|
|
|
|
|
var eyeParamsL = vrHMD.getEyeParameters( 'left' );
|
|
|
var eyeParamsR = vrHMD.getEyeParameters( 'right' );
|
|
|
|
|
|
- eyeTranslationL = eyeParamsL.eyeTranslation;
|
|
|
- eyeTranslationR = eyeParamsR.eyeTranslation;
|
|
|
- eyeFOVL = eyeParamsL.recommendedFieldOfView;
|
|
|
- eyeFOVR = eyeParamsR.recommendedFieldOfView;
|
|
|
- renderRectL = eyeParamsL.renderRect;
|
|
|
- renderRectR = eyeParamsR.renderRect;
|
|
|
+ if ( !deprecatedAPI ) {
|
|
|
+
|
|
|
+ eyeTranslationL.fromArray( eyeParamsL.offset );
|
|
|
+ eyeTranslationR.fromArray( eyeParamsR.offset );
|
|
|
+ eyeFOVL = eyeParamsL.fieldOfView;
|
|
|
+ eyeFOVR = eyeParamsR.fieldOfView;
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+ eyeTranslationL.copy( eyeParamsL.eyeTranslation );
|
|
|
+ eyeTranslationR.copy( eyeParamsR.eyeTranslation );
|
|
|
+ eyeFOVL = eyeParamsL.recommendedFieldOfView;
|
|
|
+ eyeFOVR = eyeParamsR.recommendedFieldOfView;
|
|
|
+
|
|
|
+ }
|
|
|
|
|
|
if ( Array.isArray( scene ) ) {
|
|
|
|
|
@@ -112,7 +203,11 @@ THREE.VREffect = function ( renderer, onError ) {
|
|
|
|
|
|
}
|
|
|
|
|
|
+ // When rendering we don't care what the recommended size is, only what the actual size
|
|
|
+ // of the backbuffer is.
|
|
|
var size = renderer.getSize();
|
|
|
+ renderRectL = { x: 0, y: 0, width: size.width / 2, height: size.height };
|
|
|
+ renderRectR = { x: size.width / 2, y: 0, width: size.width / 2, height: size.height };
|
|
|
|
|
|
renderer.setScissorTest( true );
|
|
|
renderer.clear();
|
|
@@ -129,28 +224,29 @@ THREE.VREffect = function ( renderer, onError ) {
|
|
|
cameraR.translateX( eyeTranslationR.x * this.scale );
|
|
|
|
|
|
// render left eye
|
|
|
- if ( renderRectL === undefined ) {
|
|
|
-
|
|
|
- renderRectL = { x: 0, y: 0, width: size.width / 2, height: size.height };
|
|
|
-
|
|
|
- }
|
|
|
renderer.setViewport( renderRectL.x, renderRectL.y, renderRectL.width, renderRectL.height );
|
|
|
renderer.setScissor( renderRectL.x, renderRectL.y, renderRectL.width, renderRectL.height );
|
|
|
renderer.render( scene, cameraL );
|
|
|
|
|
|
// render right eye
|
|
|
- if ( renderRectR === undefined ) {
|
|
|
-
|
|
|
- renderRectR = { x: size.width / 2, y: 0, width: size.width / 2, height: size.height };
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
renderer.setViewport( renderRectR.x, renderRectR.y, renderRectR.width, renderRectR.height );
|
|
|
renderer.setScissor( renderRectR.x, renderRectR.y, renderRectR.width, renderRectR.height );
|
|
|
renderer.render( scene, cameraR );
|
|
|
|
|
|
renderer.setScissorTest( false );
|
|
|
|
|
|
+ if ( autoUpdate ) {
|
|
|
+
|
|
|
+ scene.autoUpdate = true;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( !deprecatedAPI ) {
|
|
|
+
|
|
|
+ vrHMD.submitFrame();
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
return;
|
|
|
|
|
|
}
|