Skip to content

Commit cbfc2d2

Browse files
committed
WebVR 1.0 updates.
1 parent 2231d8c commit cbfc2d2

File tree

4 files changed

+178
-52
lines changed

4 files changed

+178
-52
lines changed

examples/js/controls/VRControls.js

Lines changed: 48 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,30 +7,37 @@ THREE.VRControls = function ( object, onError ) {
77

88
var scope = this;
99

10-
var vrInputs = [];
10+
var vrInput;
1111

1212
function gotVRDevices( devices ) {
1313

1414
for ( var i = 0; i < devices.length; i ++ ) {
1515

16-
if ( devices[ i ] instanceof PositionSensorVRDevice ) {
16+
if ( ( 'VRDisplay' in window && devices[ i ] instanceof VRDisplay ) ||
17+
( 'PositionSensorVRDevice' in window && devices[ i ] instanceof PositionSensorVRDevice ) ) {
1718

18-
vrInputs.push( devices[ i ] );
19+
vrInput = devices[ i ];
20+
break; // We keep the first we encounter
1921

2022
}
2123

2224
}
2325

24-
if ( vrInputs.length === 0 ) {
26+
if ( !vrInput ) {
2527

26-
if ( onError ) onError( 'PositionSensorVRDevice not available' );
28+
if ( onError ) onError( 'VR input not available.' );
2729

2830
}
2931

3032
}
3133

32-
if ( navigator.getVRDevices ) {
34+
if ( navigator.getVRDisplays ) {
3335

36+
navigator.getVRDisplays().then( gotVRDevices );
37+
38+
} else if ( navigator.getVRDevices ) {
39+
40+
// Deprecated API.
3441
navigator.getVRDevices().then( gotVRDevices );
3542

3643
}
@@ -43,21 +50,40 @@ THREE.VRControls = function ( object, onError ) {
4350

4451
this.update = function () {
4552

46-
for ( var i = 0; i < vrInputs.length; i ++ ) {
53+
if ( vrInput ) {
4754

48-
var vrInput = vrInputs[ i ];
55+
if ( vrInput.getPose ) {
4956

50-
var state = vrInput.getState();
57+
var pose = vrInput.getPose();
5158

52-
if ( state.orientation !== null ) {
59+
if ( pose.orientation !== null ) {
5360

54-
object.quaternion.copy( state.orientation );
61+
object.quaternion.fromArray( pose.orientation );
5562

56-
}
63+
}
64+
65+
if ( pose.position !== null ) {
66+
67+
object.position.fromArray( pose.position ).multiplyScalar( scope.scale );
68+
69+
}
70+
71+
} else {
5772

58-
if ( state.position !== null ) {
73+
// Deprecated API.
74+
var state = vrInput.getState();
5975

60-
object.position.copy( state.position ).multiplyScalar( scope.scale );
76+
if ( state.orientation !== null ) {
77+
78+
object.quaternion.copy( state.orientation );
79+
80+
}
81+
82+
if ( state.position !== null ) {
83+
84+
object.position.copy( state.position ).multiplyScalar( scope.scale );
85+
86+
}
6187

6288
}
6389

@@ -67,16 +93,20 @@ THREE.VRControls = function ( object, onError ) {
6793

6894
this.resetSensor = function () {
6995

70-
for ( var i = 0; i < vrInputs.length; i ++ ) {
96+
if ( vrInput ) {
97+
98+
if ( vrInput.resetPose !== undefined ) {
7199

72-
var vrInput = vrInputs[ i ];
100+
vrInput.resetPose();
73101

74-
if ( vrInput.resetSensor !== undefined ) {
102+
} else if ( vrInput.resetSensor !== undefined ) {
75103

104+
// Deprecated API.
76105
vrInput.resetSensor();
77106

78107
} else if ( vrInput.zeroSensor !== undefined ) {
79108

109+
// Really deprecated API.
80110
vrInput.zeroSensor();
81111

82112
}
@@ -94,7 +124,7 @@ THREE.VRControls = function ( object, onError ) {
94124

95125
this.dispose = function () {
96126

97-
vrInputs = [];
127+
vrInput = null;
98128

99129
};
100130

examples/js/effects/VREffect.js

Lines changed: 128 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,26 @@
1212
THREE.VREffect = function ( renderer, onError ) {
1313

1414
var vrHMD;
15-
var eyeTranslationL, eyeFOVL, renderRectL;
16-
var eyeTranslationR, eyeFOVR, renderRectR;
15+
var deprecatedAPI = false;
16+
var eyeTranslationL = new THREE.Vector3();
17+
var eyeTranslationR = new THREE.Vector3();
18+
var renderRectL, renderRectR;
19+
var eyeFOVL, eyeFOVR;
1720

1821
function gotVRDevices( devices ) {
1922

2023
for ( var i = 0; i < devices.length; i ++ ) {
2124

22-
if ( devices[ i ] instanceof HMDVRDevice ) {
25+
if ( 'VRDisplay' in window && devices[ i ] instanceof VRDisplay ) {
2326

2427
vrHMD = devices[ i ];
28+
deprecatedAPI = false;
29+
break; // We keep the first we encounter
30+
31+
} else if ( 'HMDVRDevice' in window && devices[ i ] instanceof HMDVRDevice ) {
2532

33+
vrHMD = devices[ i ];
34+
deprecatedAPI = true;
2635
break; // We keep the first we encounter
2736

2837
}
@@ -37,8 +46,13 @@ THREE.VREffect = function ( renderer, onError ) {
3746

3847
}
3948

40-
if ( navigator.getVRDevices ) {
49+
if ( navigator.getVRDisplays ) {
50+
51+
navigator.getVRDisplays().then( gotVRDevices );
52+
53+
} else if ( navigator.getVRDevices ) {
4154

55+
// Deprecated API.
4256
navigator.getVRDevices().then( gotVRDevices );
4357

4458
}
@@ -55,31 +69,90 @@ THREE.VREffect = function ( renderer, onError ) {
5569

5670
// fullscreen
5771

58-
var isFullscreen = false;
72+
var isPresenting = false;
5973

6074
var canvas = renderer.domElement;
6175
var fullscreenchange = canvas.mozRequestFullScreen ? 'mozfullscreenchange' : 'webkitfullscreenchange';
6276

63-
document.addEventListener( fullscreenchange, function ( event ) {
77+
document.addEventListener( fullscreenchange, function () {
6478

65-
isFullscreen = document.mozFullScreenElement || document.webkitFullscreenElement;
79+
if ( vrHMD && deprecatedAPI ) {
80+
81+
isPresenting = document.mozFullScreenElement || document.webkitFullscreenElement;
82+
83+
}
84+
85+
}, false );
86+
87+
window.addEventListener( 'vrdisplaypresentchange', function () {
88+
89+
isPresenting = vrHMD && vrHMD.isPresenting;
6690

6791
}, false );
6892

6993
this.setFullScreen = function ( boolean ) {
7094

71-
if ( vrHMD === undefined ) return;
72-
if ( isFullscreen === boolean ) return;
95+
return new Promise( function ( resolve, reject ) {
96+
97+
if ( vrHMD === undefined ) {
7398

74-
if ( canvas.mozRequestFullScreen ) {
99+
reject( new Error( 'No VR hardware found.' ) );
100+
return;
75101

76-
canvas.mozRequestFullScreen( { vrDisplay: vrHMD } );
102+
}
103+
if ( isPresenting === boolean ) {
104+
105+
resolve();
106+
return;
77107

78-
} else if ( canvas.webkitRequestFullscreen ) {
108+
}
79109

80-
canvas.webkitRequestFullscreen( { vrDisplay: vrHMD } );
110+
if ( !deprecatedAPI ) {
81111

82-
}
112+
if ( boolean ) {
113+
114+
resolve( vrHMD.requestPresent( { source: canvas } ) );
115+
116+
} else {
117+
118+
resolve( vrHMD.exitPresent() );
119+
120+
}
121+
122+
} else {
123+
124+
if ( canvas.mozRequestFullScreen ) {
125+
126+
canvas.mozRequestFullScreen( { vrDisplay: vrHMD } );
127+
resolve();
128+
129+
} else if ( canvas.webkitRequestFullscreen ) {
130+
131+
canvas.webkitRequestFullscreen( { vrDisplay: vrHMD } );
132+
resolve();
133+
134+
} else {
135+
136+
console.error( 'No compatible requestFullscreen method found.' );
137+
reject( new Error( 'No compatible requestFullscreen method found.' ) );
138+
139+
}
140+
141+
}
142+
143+
});
144+
145+
};
146+
147+
this.requestPresent = function () {
148+
149+
return this.setFullScreen( true );
150+
151+
};
152+
153+
this.exitPresent = function () {
154+
155+
return this.setFullScreen( false );
83156

84157
};
85158

@@ -93,17 +166,35 @@ THREE.VREffect = function ( renderer, onError ) {
93166

94167
this.render = function ( scene, camera ) {
95168

96-
if ( vrHMD ) {
169+
if ( vrHMD && isPresenting ) {
170+
171+
var autoUpdate = scene.autoUpdate;
172+
173+
if ( autoUpdate ) {
174+
175+
scene.updateMatrixWorld();
176+
scene.autoUpdate = false;
177+
178+
}
97179

98180
var eyeParamsL = vrHMD.getEyeParameters( 'left' );
99181
var eyeParamsR = vrHMD.getEyeParameters( 'right' );
100182

101-
eyeTranslationL = eyeParamsL.eyeTranslation;
102-
eyeTranslationR = eyeParamsR.eyeTranslation;
103-
eyeFOVL = eyeParamsL.recommendedFieldOfView;
104-
eyeFOVR = eyeParamsR.recommendedFieldOfView;
105-
renderRectL = eyeParamsL.renderRect;
106-
renderRectR = eyeParamsR.renderRect;
183+
if ( !deprecatedAPI ) {
184+
185+
eyeTranslationL.fromArray( eyeParamsL.offset );
186+
eyeTranslationR.fromArray( eyeParamsR.offset );
187+
eyeFOVL = eyeParamsL.fieldOfView;
188+
eyeFOVR = eyeParamsR.fieldOfView;
189+
190+
} else {
191+
192+
eyeTranslationL.copy( eyeParamsL.eyeTranslation );
193+
eyeTranslationR.copy( eyeParamsR.eyeTranslation );
194+
eyeFOVL = eyeParamsL.recommendedFieldOfView;
195+
eyeFOVR = eyeParamsR.recommendedFieldOfView;
196+
197+
}
107198

108199
if ( Array.isArray( scene ) ) {
109200

@@ -112,7 +203,11 @@ THREE.VREffect = function ( renderer, onError ) {
112203

113204
}
114205

206+
// When rendering we don't care what the recommended size is, only what the actual size
207+
// of the backbuffer is.
115208
var size = renderer.getSize();
209+
renderRectL = { x: 0, y: 0, width: size.width / 2, height: size.height };
210+
renderRectR = { x: size.width / 2, y: 0, width: size.width / 2, height: size.height };
116211

117212
renderer.setScissorTest( true );
118213
renderer.clear();
@@ -129,28 +224,29 @@ THREE.VREffect = function ( renderer, onError ) {
129224
cameraR.translateX( eyeTranslationR.x * this.scale );
130225

131226
// render left eye
132-
if ( renderRectL === undefined ) {
133-
134-
renderRectL = { x: 0, y: 0, width: size.width / 2, height: size.height };
135-
136-
}
137227
renderer.setViewport( renderRectL.x, renderRectL.y, renderRectL.width, renderRectL.height );
138228
renderer.setScissor( renderRectL.x, renderRectL.y, renderRectL.width, renderRectL.height );
139229
renderer.render( scene, cameraL );
140230

141231
// render right eye
142-
if ( renderRectR === undefined ) {
143-
144-
renderRectR = { x: size.width / 2, y: 0, width: size.width / 2, height: size.height };
145-
146-
}
147-
148232
renderer.setViewport( renderRectR.x, renderRectR.y, renderRectR.width, renderRectR.height );
149233
renderer.setScissor( renderRectR.x, renderRectR.y, renderRectR.width, renderRectR.height );
150234
renderer.render( scene, cameraR );
151235

152236
renderer.setScissorTest( false );
153237

238+
if ( autoUpdate ) {
239+
240+
scene.autoUpdate = true;
241+
242+
}
243+
244+
if ( !deprecatedAPI ) {
245+
246+
vrHMD.submitFrame();
247+
248+
}
249+
154250
return;
155251

156252
}

examples/webvr_cubes.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@
127127

128128
var fullScreenButton = document.querySelector( '.full-screen' );
129129

130-
if ( navigator.getVRDevices === undefined ) {
130+
if ( navigator.getVRDisplays === undefined && navigator.getVRDevices === undefined ) {
131131

132132
fullScreenButton.innerHTML = 'Your browser doesn\'t support WebVR';
133133
fullScreenButton.classList.add('error');

examples/webvr_stereo_pano.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@
5959
effect = new THREE.VREffect( renderer );
6060

6161

62-
if ( navigator.getVRDevices ) {
62+
if ( navigator.getVRDisplays || navigator.getVRDevices ) {
6363

6464
vrControls = new THREE.VRControls( camera, vrFallback );
6565

0 commit comments

Comments
 (0)