Browse Source

Implemented WebVRCamera in WebGLRenderer.

Mr.doob 8 years ago
parent
commit
07b089637d
2 changed files with 69 additions and 40 deletions
  1. 23 0
      src/renderers/WebGLRenderer.js
  2. 46 40
      src/renderers/webvr/WebVRManager.js

+ 23 - 0
src/renderers/WebGLRenderer.js

@@ -28,6 +28,7 @@ import { WebGLTextures } from './webgl/WebGLTextures';
 import { WebGLProperties } from './webgl/WebGLProperties';
 import { WebGLState } from './webgl/WebGLState';
 import { WebGLCapabilities } from './webgl/WebGLCapabilities';
+import { WebVRManager } from './webvr/WebVRManager';
 import { BufferGeometry } from '../core/BufferGeometry';
 import { WebGLExtensions } from './webgl/WebGLExtensions';
 import { Vector3 } from '../math/Vector3';
@@ -295,6 +296,7 @@ function WebGLRenderer( parameters ) {
 	var programCache = new WebGLPrograms( this, capabilities );
 	var lightCache = new WebGLLights();
 	var renderLists = new WebGLRenderLists();
+	var vr = new WebVRManager( this );
 
 	this.info.programs = programCache.programs;
 
@@ -345,6 +347,7 @@ function WebGLRenderer( parameters ) {
 	this.properties = properties;
 	this.renderLists = renderLists;
 	this.state = state;
+	this.vr = vr;
 
 	// shadow map
 
@@ -1082,6 +1085,20 @@ function WebGLRenderer( parameters ) {
 
 	// Rendering
 
+	this.animate = function ( callback ) {
+
+		function onFrame() {
+
+			callback();
+
+			( vr.getDevice() || window ).requestAnimationFrame( onFrame );
+
+		}
+
+		( vr.getDevice() || window ).requestAnimationFrame( onFrame );
+
+	};
+
 	this.render = function ( scene, camera, renderTarget, forceClear ) {
 
 		if ( ! ( camera && camera.isCamera ) ) {
@@ -1107,6 +1124,12 @@ function WebGLRenderer( parameters ) {
 
 		if ( camera.parent === null ) camera.updateMatrixWorld();
 
+		if ( vr.enabled ) {
+
+			camera = vr.getCamera( camera );
+
+		}
+
 		_projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
 		_frustum.setFromMatrix( _projScreenMatrix );
 

+ 46 - 40
examples/js/vr/WebVRCamera.js → src/renderers/webvr/WebVRManager.js

@@ -2,10 +2,11 @@
  * @author mrdoob / http://mrdoob.com/
  */
 
-THREE.WebVRCamera = function ( display, renderer ) {
+function WebVRManager( renderer ) {
 
 	var scope = this;
 
+	var device = null;
 	var frameData = null;
 
 	if ( 'VRFrameData' in window ) {
@@ -22,7 +23,7 @@ THREE.WebVRCamera = function ( display, renderer ) {
 	cameraR.bounds = new THREE.Vector4( 0.5, 0.0, 0.5, 1.0 );
 	cameraR.layers.enable( 2 );
 
-	var matrixWorldInverse = new THREE.Matrix4();
+	var cameraVR = new THREE.ArrayCamera( [ cameraL, cameraR ] );
 
 	//
 
@@ -30,9 +31,9 @@ THREE.WebVRCamera = function ( display, renderer ) {
 
 	function onVRDisplayPresentChange() {
 
-		if ( display.isPresenting ) {
+		if ( device.isPresenting ) {
 
-			var eyeParameters = display.getEyeParameters( 'left' );
+			var eyeParameters = device.getEyeParameters( 'left' );
 			var renderWidth = eyeParameters.renderWidth;
 			var renderHeight = eyeParameters.renderHeight;
 
@@ -42,12 +43,8 @@ THREE.WebVRCamera = function ( display, renderer ) {
 			renderer.setPixelRatio( 1 );
 			renderer.setSize( renderWidth * 2, renderHeight, false );
 
-			scope.enabled = true;
-
 		} else if ( scope.enabled ) {
 
-			scope.enabled = false;
-
 			renderer.setPixelRatio( currentPixelRatio );
 			renderer.setSize( currentSize.width, currentSize.height, true );
 
@@ -59,48 +56,67 @@ THREE.WebVRCamera = function ( display, renderer ) {
 
 	//
 
-	THREE.ArrayCamera.call( this, [ cameraL, cameraR ] );
+	this.enabled = false;
 
-	//
+	this.getDevice = function () {
 
-	this.onBeforeRender = function () {
+		return device;
 
-		display.depthNear = scope.near;
-		display.depthFar = scope.far;
+	};
 
-		display.getFrameData( frameData );
+	this.setDevice = function ( value ) {
 
-		//
+		if ( value !== undefined ) device = value;
 
-		var pose = frameData.pose;
+	};
 
-		if ( pose.orientation !== null ) {
+	this.getCamera = function ( camera ) {
 
-			scope.quaternion.fromArray( pose.orientation );
+		if ( device === null ) return camera;
 
-		}
+		device.depthNear = camera.near;
+		device.depthFar = camera.far;
+
+		device.getFrameData( frameData );
+
+		//
+
+		var pose = frameData.pose;
 
 		if ( pose.position !== null ) {
 
-			scope.position.fromArray( pose.position );
+			camera.position.fromArray( pose.position );
 
 		} else {
 
-			scope.position.set( 0, 0, 0 );
+			camera.position.set( 0, 0, 0 );
 
 		}
 
+		if ( pose.orientation !== null ) {
+
+			camera.quaternion.fromArray( pose.orientation );
+
+		}
+
+		camera.updateMatrixWorld();
+
+		if ( device.isPresenting === false ) return camera;
+
 		//
 
+		cameraVR.matrixWorld.copy( camera.matrixWorld );
+		cameraVR.matrixWorldInverse.copy( camera.matrixWorldInverse );
+
 		cameraL.matrixWorldInverse.fromArray( frameData.leftViewMatrix );
 		cameraR.matrixWorldInverse.fromArray( frameData.rightViewMatrix );
 
-		if ( scope.parent !== null ) {
+		var parent = camera.parent;
 
-			matrixWorldInverse.getInverse( scope.parent.matrixWorld );
+		if ( parent !== null ) {
 
-			cameraL.matrixWorldInverse.multiply( matrixWorldInverse );
-			cameraR.matrixWorldInverse.multiply( matrixWorldInverse );
+			cameraL.matrixWorldInverse.multiply( parent.matrixWorldInverse );
+			cameraR.matrixWorldInverse.multiply( parent.matrixWorldInverse );
 
 		}
 
@@ -110,11 +126,11 @@ THREE.WebVRCamera = function ( display, renderer ) {
 		// HACK @mrdoob
 		// https://github.com/w3c/webvr/issues/203
 
-		scope.projectionMatrix.copy( cameraL.projectionMatrix );
+		cameraVR.projectionMatrix.copy( cameraL.projectionMatrix );
 
 		//
 
-		var layers = display.getLayers();
+		var layers = device.getLayers();
 
 		if ( layers.length ) {
 
@@ -134,20 +150,10 @@ THREE.WebVRCamera = function ( display, renderer ) {
 
 		}
 
-	};
-
-	this.onAfterRender = function () {
-
-		if ( display.isPresenting ) display.submitFrame();
+		return cameraVR;
 
 	};
 
-};
-
-THREE.WebVRCamera.prototype = Object.assign( Object.create( THREE.ArrayCamera.prototype ), {
-
-	constructor: THREE.WebVRCamera,
-
-	isWebVRCamera: true
+}
 
-} );
+export { WebVRManager };