WebXRManager.js 5.6 KB
Newer Older
M
Mr.doob 已提交
1 2 3 4
/**
 * @author mrdoob / http://mrdoob.com/
 */

5
import { Group } from '../../objects/Group.js';
M
Mr.doob 已提交
6 7 8
import { Vector4 } from '../../math/Vector4.js';
import { ArrayCamera } from '../../cameras/ArrayCamera.js';
import { PerspectiveCamera } from '../../cameras/PerspectiveCamera.js';
M
Mr.doob 已提交
9
import { WebGLAnimation } from '../webgl/WebGLAnimation.js';
M
Mr.doob 已提交
10

11
function WebXRManager( renderer ) {
M
Mr.doob 已提交
12

13
	var gl = renderer.context;
14

M
Mr.doob 已提交
15 16 17 18 19 20
	var device = null;
	var session = null;

	var frameOfRef = null;

	var pose = null;
21 22 23

	var controllers = [];
	var inputSources = [];
M
Mr.doob 已提交
24 25 26 27 28

	function isPresenting() {

		return session !== null && frameOfRef !== null;

29

M
Mr.doob 已提交
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
	}

	//

	var cameraL = new PerspectiveCamera();
	cameraL.layers.enable( 1 );
	cameraL.viewport = new Vector4();

	var cameraR = new PerspectiveCamera();
	cameraR.layers.enable( 2 );
	cameraR.viewport = new Vector4();

	var cameraVR = new ArrayCamera( [ cameraL, cameraR ] );
	cameraVR.layers.enable( 1 );
	cameraVR.layers.enable( 2 );

	//

	this.enabled = false;

50 51 52 53 54 55 56 57
	this.getController = function ( id ) {

		var controller = controllers[ id ];

		if ( controller === undefined ) {

			controller = new Group();
			controller.matrixAutoUpdate = false;
58
			controller.visible = false;
59 60 61 62 63 64 65 66 67

			controllers[ id ] = controller;

		}

		return controller;

	};

M
Mr.doob 已提交
68 69 70 71 72 73
	this.getDevice = function () {

		return device;

	};

M
Mr.doob 已提交
74
	this.setDevice = function ( _device ) {
M
Mr.doob 已提交
75

M
Mr.doob 已提交
76 77
		if ( _device !== undefined ) device = _device;
		if ( _device instanceof XRDevice ) gl.setCompatibleXRDevice( _device );
M
Mr.doob 已提交
78 79 80

	};

M
Mr.doob 已提交
81 82
	//

83 84 85 86 87 88 89
	function onSessionEvent( event ) {

		var controller = controllers[ inputSources.indexOf( event.inputSource ) ];
		if ( controller ) controller.dispatchEvent( { type: event.type } );

	}

M
Mr.doob 已提交
90
	function onSessionEnd() {
91 92 93 94 95 96

		renderer.setFramebuffer( null );
		animation.stop();

	}

M
Mr.doob 已提交
97
	this.setSession = function ( _session, _options ) {
M
Mr.doob 已提交
98

M
Mr.doob 已提交
99
		session = _session;
M
Mr.doob 已提交
100 101 102

		if ( session !== null ) {

103 104 105 106
			session.addEventListener( 'select', onSessionEvent );
			session.addEventListener( 'selectstart', onSessionEvent );
			session.addEventListener( 'selectend', onSessionEvent );
			session.addEventListener( 'end', onSessionEnd );
M
Mr.doob 已提交
107

M
Mr.doob 已提交
108
			session.baseLayer = new XRWebGLLayer( session, gl );
M
Mr.doob 已提交
109
			session.requestFrameOfReference( _options.frameOfReferenceType ).then( function ( _frameOfRef ) {
M
Mr.doob 已提交
110

M
Mr.doob 已提交
111
				frameOfRef = _frameOfRef;
M
Mr.doob 已提交
112

113 114
				renderer.setFramebuffer( session.baseLayer.framebuffer );

M
Mr.doob 已提交
115 116 117
				animation.setContext( session );
				animation.start();

M
Mr.doob 已提交
118 119
			} );

120 121 122 123 124 125 126 127 128 129 130
			//

			inputSources = session.getInputSources();

			session.addEventListener( 'inputsourceschange', function () {

				inputSources = session.getInputSources();
				console.log( inputSources );

			} );

M
Mr.doob 已提交
131 132 133 134
		}

	};

135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
	function updateCamera( camera, parent ) {

		if ( parent === null ) {

			camera.matrixWorld.copy( camera.matrix );

		} else {

			camera.matrixWorld.multiplyMatrices( parent.matrixWorld, camera.matrix );

		}

		camera.matrixWorldInverse.getInverse( camera.matrixWorld );

	}

M
Mr.doob 已提交
151 152
	this.getCamera = function ( camera ) {

153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
		if ( isPresenting() ) {

			var parent = camera.parent;
			var cameras = cameraVR.cameras;

			// apply camera.parent to cameraVR

			updateCamera( cameraVR, parent );

			for ( var i = 0; i < cameras.length; i ++ ) {

				updateCamera( cameras[ i ], parent );

			}

			// update camera and its children

			camera.matrixWorld.copy( cameraVR.matrixWorld );

			var children = camera.children;

			for ( var i = 0, l = children.length; i < l; i ++ ) {

				children[ i ].updateMatrixWorld( true );

			}

			return cameraVR;

		}

		return camera;
M
Mr.doob 已提交
185 186 187 188 189

	};

	this.isPresenting = isPresenting;

M
Mr.doob 已提交
190
	// Animation Loop
M
Mr.doob 已提交
191

M
Mr.doob 已提交
192
	var onAnimationFrameCallback = null;
M
Mr.doob 已提交
193

M
Mr.doob 已提交
194
	function onAnimationFrame( time, frame ) {
M
Mr.doob 已提交
195

M
Mr.doob 已提交
196
		pose = frame.getDevicePose( frameOfRef );
M
Mr.doob 已提交
197

M
Mr.doob 已提交
198
		if ( pose !== null ) {
M
Mr.doob 已提交
199

M
Mr.doob 已提交
200 201
			var layer = session.baseLayer;
			var views = frame.views;
M
Mr.doob 已提交
202

M
Mr.doob 已提交
203
			for ( var i = 0; i < views.length; i ++ ) {
M
Mr.doob 已提交
204

M
Mr.doob 已提交
205 206 207
				var view = views[ i ];
				var viewport = layer.getViewport( view );
				var viewMatrix = pose.getViewMatrix( view );
M
Mr.doob 已提交
208

M
Mr.doob 已提交
209 210 211 212
				var camera = cameraVR.cameras[ i ];
				camera.matrix.fromArray( viewMatrix ).getInverse( camera.matrix );
				camera.projectionMatrix.fromArray( view.projectionMatrix );
				camera.viewport.set( viewport.x, viewport.y, viewport.width, viewport.height );
M
Mr.doob 已提交
213

M
Mr.doob 已提交
214
				if ( i === 0 ) {
M
Mr.doob 已提交
215

M
Mr.doob 已提交
216
					cameraVR.matrix.copy( camera.matrix );
M
Mr.doob 已提交
217

M
Mr.doob 已提交
218 219 220 221 222 223
					// HACK (mrdoob)
					// https://github.com/w3c/webvr/issues/203

					cameraVR.projectionMatrix.copy( camera.projectionMatrix );

				}
M
Mr.doob 已提交
224 225 226

			}

M
Mr.doob 已提交
227
		}
M
Mr.doob 已提交
228

229 230
		//

231 232 233
		for ( var i = 0; i < controllers.length; i ++ ) {

			var controller = controllers[ i ];
234 235 236

			var inputSource = inputSources[ i ];

237 238 239
			if ( inputSource ) {

				var inputPose = frame.getInputPose( inputSource, frameOfRef );
240

241 242
				if ( inputPose !== null ) {

M
Mr.doob 已提交
243
					if ( 'targetRay' in inputPose ) {
244 245 246

						controller.matrix.elements = inputPose.targetRay.transformMatrix;

M
Mr.doob 已提交
247 248 249
					} else if ( 'pointerMatrix' in inputPose ) {

						// DEPRECATED
250 251 252 253 254

						controller.matrix.elements = inputPose.pointerMatrix;

					}

255
					controller.matrix.decompose( controller.position, controller.rotation, controller.scale );
256
					controller.visible = true;
257 258 259 260

					continue;

				}
261 262 263

			}

264 265
			controller.visible = false;

266 267
		}

268
		if ( onAnimationFrameCallback ) onAnimationFrameCallback( time );
M
Mr.doob 已提交
269 270

	}
M
Mr.doob 已提交
271

M
Mr.doob 已提交
272 273 274 275 276 277
	var animation = new WebGLAnimation();
	animation.setAnimationLoop( onAnimationFrame );

	this.setAnimationLoop = function ( callback ) {

		onAnimationFrameCallback = callback;
M
Mr.doob 已提交
278 279 280

	};

M
Mr.doob 已提交
281 282
	this.dispose = function () {};

283
	// DEPRECATED
M
Mr.doob 已提交
284

285 286 287 288
	this.getStandingMatrix = function () {

		console.warn( 'THREE.WebXRManager: getStandingMatrix() is no longer needed.' );
		return new THREE.Matrix4();
M
Mr.doob 已提交
289 290 291

	};

292 293
	this.submitFrame = function () {};

M
Mr.doob 已提交
294 295 296
}

export { WebXRManager };