|
@@ -208,11 +208,9 @@ const GLSL3 = '300 es';
|
|
|
* https://github.com/mrdoob/eventdispatcher.js/
|
|
|
*/
|
|
|
|
|
|
-function EventDispatcher() {}
|
|
|
+class EventDispatcher {
|
|
|
|
|
|
-Object.assign( EventDispatcher.prototype, {
|
|
|
-
|
|
|
- addEventListener: function ( type, listener ) {
|
|
|
+ addEventListener( type, listener ) {
|
|
|
|
|
|
if ( this._listeners === undefined ) this._listeners = {};
|
|
|
|
|
@@ -230,9 +228,9 @@ Object.assign( EventDispatcher.prototype, {
|
|
|
|
|
|
}
|
|
|
|
|
|
- },
|
|
|
+ }
|
|
|
|
|
|
- hasEventListener: function ( type, listener ) {
|
|
|
+ hasEventListener( type, listener ) {
|
|
|
|
|
|
if ( this._listeners === undefined ) return false;
|
|
|
|
|
@@ -240,9 +238,9 @@ Object.assign( EventDispatcher.prototype, {
|
|
|
|
|
|
return listeners[ type ] !== undefined && listeners[ type ].indexOf( listener ) !== - 1;
|
|
|
|
|
|
- },
|
|
|
+ }
|
|
|
|
|
|
- removeEventListener: function ( type, listener ) {
|
|
|
+ removeEventListener( type, listener ) {
|
|
|
|
|
|
if ( this._listeners === undefined ) return;
|
|
|
|
|
@@ -261,9 +259,9 @@ Object.assign( EventDispatcher.prototype, {
|
|
|
|
|
|
}
|
|
|
|
|
|
- },
|
|
|
+ }
|
|
|
|
|
|
- dispatchEvent: function ( event ) {
|
|
|
+ dispatchEvent( event ) {
|
|
|
|
|
|
if ( this._listeners === undefined ) return;
|
|
|
|
|
@@ -289,7 +287,7 @@ Object.assign( EventDispatcher.prototype, {
|
|
|
|
|
|
}
|
|
|
|
|
|
-} );
|
|
|
+}
|
|
|
|
|
|
const _lut = [];
|
|
|
|
|
@@ -6470,119 +6468,114 @@ class Layers {
|
|
|
|
|
|
let _object3DId = 0;
|
|
|
|
|
|
-const _v1$4 = new Vector3();
|
|
|
-const _q1 = new Quaternion();
|
|
|
-const _m1$1 = new Matrix4();
|
|
|
-const _target = new Vector3();
|
|
|
+const _v1$4 = new /*@__PURE__*/ Vector3();
|
|
|
+const _q1 = new /*@__PURE__*/ Quaternion();
|
|
|
+const _m1$1 = new /*@__PURE__*/ Matrix4();
|
|
|
+const _target = new /*@__PURE__*/ Vector3();
|
|
|
|
|
|
-const _position$3 = new Vector3();
|
|
|
-const _scale$2 = new Vector3();
|
|
|
-const _quaternion$2 = new Quaternion();
|
|
|
+const _position$3 = new /*@__PURE__*/ Vector3();
|
|
|
+const _scale$2 = new /*@__PURE__*/ Vector3();
|
|
|
+const _quaternion$2 = new /*@__PURE__*/ Quaternion();
|
|
|
|
|
|
-const _xAxis = new Vector3( 1, 0, 0 );
|
|
|
-const _yAxis = new Vector3( 0, 1, 0 );
|
|
|
-const _zAxis = new Vector3( 0, 0, 1 );
|
|
|
+const _xAxis = new /*@__PURE__*/ Vector3( 1, 0, 0 );
|
|
|
+const _yAxis = new /*@__PURE__*/ Vector3( 0, 1, 0 );
|
|
|
+const _zAxis = new /*@__PURE__*/ Vector3( 0, 0, 1 );
|
|
|
|
|
|
const _addedEvent = { type: 'added' };
|
|
|
const _removedEvent = { type: 'removed' };
|
|
|
|
|
|
-function Object3D() {
|
|
|
+class Object3D extends EventDispatcher {
|
|
|
|
|
|
- Object.defineProperty( this, 'id', { value: _object3DId ++ } );
|
|
|
+ constructor() {
|
|
|
|
|
|
- this.uuid = MathUtils.generateUUID();
|
|
|
+ super();
|
|
|
|
|
|
- this.name = '';
|
|
|
- this.type = 'Object3D';
|
|
|
+ Object.defineProperty( this, 'id', { value: _object3DId ++ } );
|
|
|
|
|
|
- this.parent = null;
|
|
|
- this.children = [];
|
|
|
+ this.uuid = MathUtils.generateUUID();
|
|
|
|
|
|
- this.up = Object3D.DefaultUp.clone();
|
|
|
+ this.name = '';
|
|
|
+ this.type = 'Object3D';
|
|
|
|
|
|
- const position = new Vector3();
|
|
|
- const rotation = new Euler();
|
|
|
- const quaternion = new Quaternion();
|
|
|
- const scale = new Vector3( 1, 1, 1 );
|
|
|
+ this.parent = null;
|
|
|
+ this.children = [];
|
|
|
|
|
|
- function onRotationChange() {
|
|
|
+ this.up = Object3D.DefaultUp.clone();
|
|
|
|
|
|
- quaternion.setFromEuler( rotation, false );
|
|
|
+ const position = new Vector3();
|
|
|
+ const rotation = new Euler();
|
|
|
+ const quaternion = new Quaternion();
|
|
|
+ const scale = new Vector3( 1, 1, 1 );
|
|
|
|
|
|
- }
|
|
|
+ function onRotationChange() {
|
|
|
|
|
|
- function onQuaternionChange() {
|
|
|
+ quaternion.setFromEuler( rotation, false );
|
|
|
|
|
|
- rotation.setFromQuaternion( quaternion, undefined, false );
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
+ function onQuaternionChange() {
|
|
|
|
|
|
- rotation._onChange( onRotationChange );
|
|
|
- quaternion._onChange( onQuaternionChange );
|
|
|
+ rotation.setFromQuaternion( quaternion, undefined, false );
|
|
|
|
|
|
- Object.defineProperties( this, {
|
|
|
- position: {
|
|
|
- configurable: true,
|
|
|
- enumerable: true,
|
|
|
- value: position
|
|
|
- },
|
|
|
- rotation: {
|
|
|
- configurable: true,
|
|
|
- enumerable: true,
|
|
|
- value: rotation
|
|
|
- },
|
|
|
- quaternion: {
|
|
|
- configurable: true,
|
|
|
- enumerable: true,
|
|
|
- value: quaternion
|
|
|
- },
|
|
|
- scale: {
|
|
|
- configurable: true,
|
|
|
- enumerable: true,
|
|
|
- value: scale
|
|
|
- },
|
|
|
- modelViewMatrix: {
|
|
|
- value: new Matrix4()
|
|
|
- },
|
|
|
- normalMatrix: {
|
|
|
- value: new Matrix3()
|
|
|
}
|
|
|
- } );
|
|
|
-
|
|
|
- this.matrix = new Matrix4();
|
|
|
- this.matrixWorld = new Matrix4();
|
|
|
|
|
|
- this.matrixAutoUpdate = Object3D.DefaultMatrixAutoUpdate;
|
|
|
- this.matrixWorldNeedsUpdate = false;
|
|
|
-
|
|
|
- this.layers = new Layers();
|
|
|
- this.visible = true;
|
|
|
+ rotation._onChange( onRotationChange );
|
|
|
+ quaternion._onChange( onQuaternionChange );
|
|
|
|
|
|
- this.castShadow = false;
|
|
|
- this.receiveShadow = false;
|
|
|
+ Object.defineProperties( this, {
|
|
|
+ position: {
|
|
|
+ configurable: true,
|
|
|
+ enumerable: true,
|
|
|
+ value: position
|
|
|
+ },
|
|
|
+ rotation: {
|
|
|
+ configurable: true,
|
|
|
+ enumerable: true,
|
|
|
+ value: rotation
|
|
|
+ },
|
|
|
+ quaternion: {
|
|
|
+ configurable: true,
|
|
|
+ enumerable: true,
|
|
|
+ value: quaternion
|
|
|
+ },
|
|
|
+ scale: {
|
|
|
+ configurable: true,
|
|
|
+ enumerable: true,
|
|
|
+ value: scale
|
|
|
+ },
|
|
|
+ modelViewMatrix: {
|
|
|
+ value: new Matrix4()
|
|
|
+ },
|
|
|
+ normalMatrix: {
|
|
|
+ value: new Matrix3()
|
|
|
+ }
|
|
|
+ } );
|
|
|
|
|
|
- this.frustumCulled = true;
|
|
|
- this.renderOrder = 0;
|
|
|
+ this.matrix = new Matrix4();
|
|
|
+ this.matrixWorld = new Matrix4();
|
|
|
|
|
|
- this.animations = [];
|
|
|
+ this.matrixAutoUpdate = Object3D.DefaultMatrixAutoUpdate;
|
|
|
+ this.matrixWorldNeedsUpdate = false;
|
|
|
|
|
|
- this.userData = {};
|
|
|
+ this.layers = new Layers();
|
|
|
+ this.visible = true;
|
|
|
|
|
|
-}
|
|
|
+ this.castShadow = false;
|
|
|
+ this.receiveShadow = false;
|
|
|
|
|
|
-Object3D.DefaultUp = new Vector3( 0, 1, 0 );
|
|
|
-Object3D.DefaultMatrixAutoUpdate = true;
|
|
|
+ this.frustumCulled = true;
|
|
|
+ this.renderOrder = 0;
|
|
|
|
|
|
-Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
|
|
|
+ this.animations = [];
|
|
|
|
|
|
- constructor: Object3D,
|
|
|
+ this.userData = {};
|
|
|
|
|
|
- isObject3D: true,
|
|
|
+ }
|
|
|
|
|
|
- onBeforeRender: function () {},
|
|
|
- onAfterRender: function () {},
|
|
|
+ onBeforeRender() {}
|
|
|
+ onAfterRender() {}
|
|
|
|
|
|
- applyMatrix4: function ( matrix ) {
|
|
|
+ applyMatrix4( matrix ) {
|
|
|
|
|
|
if ( this.matrixAutoUpdate ) this.updateMatrix();
|
|
|
|
|
@@ -6590,47 +6583,47 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ),
|
|
|
|
|
|
this.matrix.decompose( this.position, this.quaternion, this.scale );
|
|
|
|
|
|
- },
|
|
|
+ }
|
|
|
|
|
|
- applyQuaternion: function ( q ) {
|
|
|
+ applyQuaternion( q ) {
|
|
|
|
|
|
this.quaternion.premultiply( q );
|
|
|
|
|
|
return this;
|
|
|
|
|
|
- },
|
|
|
+ }
|
|
|
|
|
|
- setRotationFromAxisAngle: function ( axis, angle ) {
|
|
|
+ setRotationFromAxisAngle( axis, angle ) {
|
|
|
|
|
|
// assumes axis is normalized
|
|
|
|
|
|
this.quaternion.setFromAxisAngle( axis, angle );
|
|
|
|
|
|
- },
|
|
|
+ }
|
|
|
|
|
|
- setRotationFromEuler: function ( euler ) {
|
|
|
+ setRotationFromEuler( euler ) {
|
|
|
|
|
|
this.quaternion.setFromEuler( euler, true );
|
|
|
|
|
|
- },
|
|
|
+ }
|
|
|
|
|
|
- setRotationFromMatrix: function ( m ) {
|
|
|
+ setRotationFromMatrix( m ) {
|
|
|
|
|
|
// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
|
|
|
|
|
|
this.quaternion.setFromRotationMatrix( m );
|
|
|
|
|
|
- },
|
|
|
+ }
|
|
|
|
|
|
- setRotationFromQuaternion: function ( q ) {
|
|
|
+ setRotationFromQuaternion( q ) {
|
|
|
|
|
|
// assumes q is normalized
|
|
|
|
|
|
this.quaternion.copy( q );
|
|
|
|
|
|
- },
|
|
|
+ }
|
|
|
|
|
|
- rotateOnAxis: function ( axis, angle ) {
|
|
|
+ rotateOnAxis( axis, angle ) {
|
|
|
|
|
|
// rotate object on axis in object space
|
|
|
// axis is assumed to be normalized
|
|
@@ -6641,9 +6634,9 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ),
|
|
|
|
|
|
return this;
|
|
|
|
|
|
- },
|
|
|
+ }
|
|
|
|
|
|
- rotateOnWorldAxis: function ( axis, angle ) {
|
|
|
+ rotateOnWorldAxis( axis, angle ) {
|
|
|
|
|
|
// rotate object on axis in world space
|
|
|
// axis is assumed to be normalized
|
|
@@ -6655,27 +6648,27 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ),
|
|
|
|
|
|
return this;
|
|
|
|
|
|
- },
|
|
|
+ }
|
|
|
|
|
|
- rotateX: function ( angle ) {
|
|
|
+ rotateX( angle ) {
|
|
|
|
|
|
return this.rotateOnAxis( _xAxis, angle );
|
|
|
|
|
|
- },
|
|
|
+ }
|
|
|
|
|
|
- rotateY: function ( angle ) {
|
|
|
+ rotateY( angle ) {
|
|
|
|
|
|
return this.rotateOnAxis( _yAxis, angle );
|
|
|
|
|
|
- },
|
|
|
+ }
|
|
|
|
|
|
- rotateZ: function ( angle ) {
|
|
|
+ rotateZ( angle ) {
|
|
|
|
|
|
return this.rotateOnAxis( _zAxis, angle );
|
|
|
|
|
|
- },
|
|
|
+ }
|
|
|
|
|
|
- translateOnAxis: function ( axis, distance ) {
|
|
|
+ translateOnAxis( axis, distance ) {
|
|
|
|
|
|
// translate object by distance along axis in object space
|
|
|
// axis is assumed to be normalized
|
|
@@ -6686,39 +6679,39 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ),
|
|
|
|
|
|
return this;
|
|
|
|
|
|
- },
|
|
|
+ }
|
|
|
|
|
|
- translateX: function ( distance ) {
|
|
|
+ translateX( distance ) {
|
|
|
|
|
|
return this.translateOnAxis( _xAxis, distance );
|
|
|
|
|
|
- },
|
|
|
+ }
|
|
|
|
|
|
- translateY: function ( distance ) {
|
|
|
+ translateY( distance ) {
|
|
|
|
|
|
return this.translateOnAxis( _yAxis, distance );
|
|
|
|
|
|
- },
|
|
|
+ }
|
|
|
|
|
|
- translateZ: function ( distance ) {
|
|
|
+ translateZ( distance ) {
|
|
|
|
|
|
return this.translateOnAxis( _zAxis, distance );
|
|
|
|
|
|
- },
|
|
|
+ }
|
|
|
|
|
|
- localToWorld: function ( vector ) {
|
|
|
+ localToWorld( vector ) {
|
|
|
|
|
|
return vector.applyMatrix4( this.matrixWorld );
|
|
|
|
|
|
- },
|
|
|
+ }
|
|
|
|
|
|
- worldToLocal: function ( vector ) {
|
|
|
+ worldToLocal( vector ) {
|
|
|
|
|
|
return vector.applyMatrix4( _m1$1.copy( this.matrixWorld ).invert() );
|
|
|
|
|
|
- },
|
|
|
+ }
|
|
|
|
|
|
- lookAt: function ( x, y, z ) {
|
|
|
+ lookAt( x, y, z ) {
|
|
|
|
|
|
// This method does not support objects having non-uniformly-scaled parent(s)
|
|
|
|
|
@@ -6758,9 +6751,9 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ),
|
|
|
|
|
|
}
|
|
|
|
|
|
- },
|
|
|
+ }
|
|
|
|
|
|
- add: function ( object ) {
|
|
|
+ add( object ) {
|
|
|
|
|
|
if ( arguments.length > 1 ) {
|
|
|
|
|
@@ -6802,9 +6795,9 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ),
|
|
|
|
|
|
return this;
|
|
|
|
|
|
- },
|
|
|
+ }
|
|
|
|
|
|
- remove: function ( object ) {
|
|
|
+ remove( object ) {
|
|
|
|
|
|
if ( arguments.length > 1 ) {
|
|
|
|
|
@@ -6831,9 +6824,9 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ),
|
|
|
|
|
|
return this;
|
|
|
|
|
|
- },
|
|
|
+ }
|
|
|
|
|
|
- clear: function () {
|
|
|
+ clear() {
|
|
|
|
|
|
for ( let i = 0; i < this.children.length; i ++ ) {
|
|
|
|
|
@@ -6850,9 +6843,9 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ),
|
|
|
return this;
|
|
|
|
|
|
|
|
|
- },
|
|
|
+ }
|
|
|
|
|
|
- attach: function ( object ) {
|
|
|
+ attach( object ) {
|
|
|
|
|
|
// adds object as a child of this, while maintaining the object's world transform
|
|
|
|
|
@@ -6876,21 +6869,21 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ),
|
|
|
|
|
|
return this;
|
|
|
|
|
|
- },
|
|
|
+ }
|
|
|
|
|
|
- getObjectById: function ( id ) {
|
|
|
+ getObjectById( id ) {
|
|
|
|
|
|
return this.getObjectByProperty( 'id', id );
|
|
|
|
|
|
- },
|
|
|
+ }
|
|
|
|
|
|
- getObjectByName: function ( name ) {
|
|
|
+ getObjectByName( name ) {
|
|
|
|
|
|
return this.getObjectByProperty( 'name', name );
|
|
|
|
|
|
- },
|
|
|
+ }
|
|
|
|
|
|
- getObjectByProperty: function ( name, value ) {
|
|
|
+ getObjectByProperty( name, value ) {
|
|
|
|
|
|
if ( this[ name ] === value ) return this;
|
|
|
|
|
@@ -6909,9 +6902,9 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ),
|
|
|
|
|
|
return undefined;
|
|
|
|
|
|
- },
|
|
|
+ }
|
|
|
|
|
|
- getWorldPosition: function ( target ) {
|
|
|
+ getWorldPosition( target ) {
|
|
|
|
|
|
if ( target === undefined ) {
|
|
|
|
|
@@ -6924,9 +6917,9 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ),
|
|
|
|
|
|
return target.setFromMatrixPosition( this.matrixWorld );
|
|
|
|
|
|
- },
|
|
|
+ }
|
|
|
|
|
|
- getWorldQuaternion: function ( target ) {
|
|
|
+ getWorldQuaternion( target ) {
|
|
|
|
|
|
if ( target === undefined ) {
|
|
|
|
|
@@ -6941,9 +6934,9 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ),
|
|
|
|
|
|
return target;
|
|
|
|
|
|
- },
|
|
|
+ }
|
|
|
|
|
|
- getWorldScale: function ( target ) {
|
|
|
+ getWorldScale( target ) {
|
|
|
|
|
|
if ( target === undefined ) {
|
|
|
|
|
@@ -6958,9 +6951,9 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ),
|
|
|
|
|
|
return target;
|
|
|
|
|
|
- },
|
|
|
+ }
|
|
|
|
|
|
- getWorldDirection: function ( target ) {
|
|
|
+ getWorldDirection( target ) {
|
|
|
|
|
|
if ( target === undefined ) {
|
|
|
|
|
@@ -6975,11 +6968,11 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ),
|
|
|
|
|
|
return target.set( e[ 8 ], e[ 9 ], e[ 10 ] ).normalize();
|
|
|
|
|
|
- },
|
|
|
+ }
|
|
|
|
|
|
- raycast: function () {},
|
|
|
+ raycast() {}
|
|
|
|
|
|
- traverse: function ( callback ) {
|
|
|
+ traverse( callback ) {
|
|
|
|
|
|
callback( this );
|
|
|
|
|
@@ -6991,9 +6984,9 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ),
|
|
|
|
|
|
}
|
|
|
|
|
|
- },
|
|
|
+ }
|
|
|
|
|
|
- traverseVisible: function ( callback ) {
|
|
|
+ traverseVisible( callback ) {
|
|
|
|
|
|
if ( this.visible === false ) return;
|
|
|
|
|
@@ -7007,9 +7000,9 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ),
|
|
|
|
|
|
}
|
|
|
|
|
|
- },
|
|
|
+ }
|
|
|
|
|
|
- traverseAncestors: function ( callback ) {
|
|
|
+ traverseAncestors( callback ) {
|
|
|
|
|
|
const parent = this.parent;
|
|
|
|
|
@@ -7021,17 +7014,17 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ),
|
|
|
|
|
|
}
|
|
|
|
|
|
- },
|
|
|
+ }
|
|
|
|
|
|
- updateMatrix: function () {
|
|
|
+ updateMatrix() {
|
|
|
|
|
|
this.matrix.compose( this.position, this.quaternion, this.scale );
|
|
|
|
|
|
this.matrixWorldNeedsUpdate = true;
|
|
|
|
|
|
- },
|
|
|
+ }
|
|
|
|
|
|
- updateMatrixWorld: function ( force ) {
|
|
|
+ updateMatrixWorld( force ) {
|
|
|
|
|
|
if ( this.matrixAutoUpdate ) this.updateMatrix();
|
|
|
|
|
@@ -7063,9 +7056,9 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ),
|
|
|
|
|
|
}
|
|
|
|
|
|
- },
|
|
|
+ }
|
|
|
|
|
|
- updateWorldMatrix: function ( updateParents, updateChildren ) {
|
|
|
+ updateWorldMatrix( updateParents, updateChildren ) {
|
|
|
|
|
|
const parent = this.parent;
|
|
|
|
|
@@ -7101,9 +7094,9 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ),
|
|
|
|
|
|
}
|
|
|
|
|
|
- },
|
|
|
+ }
|
|
|
|
|
|
- toJSON: function ( meta ) {
|
|
|
+ toJSON( meta ) {
|
|
|
|
|
|
// meta is a string when called from JSON.stringify
|
|
|
const isRootObject = ( meta === undefined || typeof meta === 'string' );
|
|
@@ -7318,15 +7311,15 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ),
|
|
|
|
|
|
}
|
|
|
|
|
|
- },
|
|
|
+ }
|
|
|
|
|
|
- clone: function ( recursive ) {
|
|
|
+ clone( recursive ) {
|
|
|
|
|
|
return new this.constructor().copy( this, recursive );
|
|
|
|
|
|
- },
|
|
|
+ }
|
|
|
|
|
|
- copy: function ( source, recursive = true ) {
|
|
|
+ copy( source, recursive = true ) {
|
|
|
|
|
|
this.name = source.name;
|
|
|
|
|
@@ -7369,7 +7362,12 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ),
|
|
|
|
|
|
}
|
|
|
|
|
|
-} );
|
|
|
+}
|
|
|
+
|
|
|
+Object3D.DefaultUp = new Vector3( 0, 1, 0 );
|
|
|
+Object3D.DefaultMatrixAutoUpdate = true;
|
|
|
+
|
|
|
+Object3D.prototype.isObject3D = true;
|
|
|
|
|
|
const _vector1 = /*@__PURE__*/ new Vector3();
|
|
|
const _vector2$1 = /*@__PURE__*/ new Vector3();
|
|
@@ -22057,487 +22055,491 @@ Object.assign( WebXRController.prototype, {
|
|
|
|
|
|
} );
|
|
|
|
|
|
-function WebXRManager( renderer, gl ) {
|
|
|
+class WebXRManager extends EventDispatcher {
|
|
|
|
|
|
- const scope = this;
|
|
|
- const state = renderer.state;
|
|
|
+ constructor( renderer, gl ) {
|
|
|
|
|
|
- let session = null;
|
|
|
+ super();
|
|
|
|
|
|
- let framebufferScaleFactor = 1.0;
|
|
|
+ const scope = this;
|
|
|
+ const state = renderer.state;
|
|
|
|
|
|
- let referenceSpace = null;
|
|
|
- let referenceSpaceType = 'local-floor';
|
|
|
+ let session = null;
|
|
|
|
|
|
- let pose = null;
|
|
|
+ let framebufferScaleFactor = 1.0;
|
|
|
|
|
|
- const controllers = [];
|
|
|
- const inputSourcesMap = new Map();
|
|
|
+ let referenceSpace = null;
|
|
|
+ let referenceSpaceType = 'local-floor';
|
|
|
|
|
|
- //
|
|
|
+ let pose = null;
|
|
|
|
|
|
- const cameraL = new PerspectiveCamera();
|
|
|
- cameraL.layers.enable( 1 );
|
|
|
- cameraL.viewport = new Vector4();
|
|
|
+ const controllers = [];
|
|
|
+ const inputSourcesMap = new Map();
|
|
|
|
|
|
- const cameraR = new PerspectiveCamera();
|
|
|
- cameraR.layers.enable( 2 );
|
|
|
- cameraR.viewport = new Vector4();
|
|
|
+ //
|
|
|
|
|
|
- const cameras = [ cameraL, cameraR ];
|
|
|
+ const cameraL = new PerspectiveCamera();
|
|
|
+ cameraL.layers.enable( 1 );
|
|
|
+ cameraL.viewport = new Vector4();
|
|
|
|
|
|
- const cameraVR = new ArrayCamera();
|
|
|
- cameraVR.layers.enable( 1 );
|
|
|
- cameraVR.layers.enable( 2 );
|
|
|
+ const cameraR = new PerspectiveCamera();
|
|
|
+ cameraR.layers.enable( 2 );
|
|
|
+ cameraR.viewport = new Vector4();
|
|
|
|
|
|
- let _currentDepthNear = null;
|
|
|
- let _currentDepthFar = null;
|
|
|
+ const cameras = [ cameraL, cameraR ];
|
|
|
|
|
|
- //
|
|
|
+ const cameraVR = new ArrayCamera();
|
|
|
+ cameraVR.layers.enable( 1 );
|
|
|
+ cameraVR.layers.enable( 2 );
|
|
|
|
|
|
- this.enabled = false;
|
|
|
+ let _currentDepthNear = null;
|
|
|
+ let _currentDepthFar = null;
|
|
|
|
|
|
- this.isPresenting = false;
|
|
|
+ //
|
|
|
|
|
|
- this.getController = function ( index ) {
|
|
|
+ this.enabled = false;
|
|
|
|
|
|
- let controller = controllers[ index ];
|
|
|
+ this.isPresenting = false;
|
|
|
|
|
|
- if ( controller === undefined ) {
|
|
|
+ this.getController = function ( index ) {
|
|
|
|
|
|
- controller = new WebXRController();
|
|
|
- controllers[ index ] = controller;
|
|
|
+ let controller = controllers[ index ];
|
|
|
|
|
|
- }
|
|
|
+ if ( controller === undefined ) {
|
|
|
|
|
|
- return controller.getTargetRaySpace();
|
|
|
+ controller = new WebXRController();
|
|
|
+ controllers[ index ] = controller;
|
|
|
|
|
|
- };
|
|
|
+ }
|
|
|
|
|
|
- this.getControllerGrip = function ( index ) {
|
|
|
+ return controller.getTargetRaySpace();
|
|
|
|
|
|
- let controller = controllers[ index ];
|
|
|
+ };
|
|
|
|
|
|
- if ( controller === undefined ) {
|
|
|
+ this.getControllerGrip = function ( index ) {
|
|
|
|
|
|
- controller = new WebXRController();
|
|
|
- controllers[ index ] = controller;
|
|
|
+ let controller = controllers[ index ];
|
|
|
|
|
|
- }
|
|
|
+ if ( controller === undefined ) {
|
|
|
|
|
|
- return controller.getGripSpace();
|
|
|
+ controller = new WebXRController();
|
|
|
+ controllers[ index ] = controller;
|
|
|
|
|
|
- };
|
|
|
+ }
|
|
|
|
|
|
- this.getHand = function ( index ) {
|
|
|
+ return controller.getGripSpace();
|
|
|
|
|
|
- let controller = controllers[ index ];
|
|
|
+ };
|
|
|
|
|
|
- if ( controller === undefined ) {
|
|
|
+ this.getHand = function ( index ) {
|
|
|
|
|
|
- controller = new WebXRController();
|
|
|
- controllers[ index ] = controller;
|
|
|
+ let controller = controllers[ index ];
|
|
|
|
|
|
- }
|
|
|
+ if ( controller === undefined ) {
|
|
|
|
|
|
- return controller.getHandSpace();
|
|
|
+ controller = new WebXRController();
|
|
|
+ controllers[ index ] = controller;
|
|
|
|
|
|
- };
|
|
|
+ }
|
|
|
|
|
|
- //
|
|
|
+ return controller.getHandSpace();
|
|
|
|
|
|
- function onSessionEvent( event ) {
|
|
|
+ };
|
|
|
+
|
|
|
+ //
|
|
|
+
|
|
|
+ function onSessionEvent( event ) {
|
|
|
|
|
|
- const controller = inputSourcesMap.get( event.inputSource );
|
|
|
+ const controller = inputSourcesMap.get( event.inputSource );
|
|
|
|
|
|
- if ( controller ) {
|
|
|
+ if ( controller ) {
|
|
|
+
|
|
|
+ controller.dispatchEvent( { type: event.type, data: event.inputSource } );
|
|
|
|
|
|
- controller.dispatchEvent( { type: event.type, data: event.inputSource } );
|
|
|
+ }
|
|
|
|
|
|
}
|
|
|
|
|
|
- }
|
|
|
+ function onSessionEnd() {
|
|
|
|
|
|
- function onSessionEnd() {
|
|
|
+ inputSourcesMap.forEach( function ( controller, inputSource ) {
|
|
|
|
|
|
- inputSourcesMap.forEach( function ( controller, inputSource ) {
|
|
|
+ controller.disconnect( inputSource );
|
|
|
|
|
|
- controller.disconnect( inputSource );
|
|
|
+ } );
|
|
|
|
|
|
- } );
|
|
|
+ inputSourcesMap.clear();
|
|
|
|
|
|
- inputSourcesMap.clear();
|
|
|
+ _currentDepthNear = null;
|
|
|
+ _currentDepthFar = null;
|
|
|
|
|
|
- _currentDepthNear = null;
|
|
|
- _currentDepthFar = null;
|
|
|
+ // restore framebuffer/rendering state
|
|
|
|
|
|
- // restore framebuffer/rendering state
|
|
|
+ state.bindXRFramebuffer( null );
|
|
|
+ renderer.setRenderTarget( renderer.getRenderTarget() );
|
|
|
|
|
|
- state.bindXRFramebuffer( null );
|
|
|
- renderer.setRenderTarget( renderer.getRenderTarget() );
|
|
|
+ //
|
|
|
|
|
|
- //
|
|
|
+ animation.stop();
|
|
|
|
|
|
- animation.stop();
|
|
|
+ scope.isPresenting = false;
|
|
|
|
|
|
- scope.isPresenting = false;
|
|
|
+ scope.dispatchEvent( { type: 'sessionend' } );
|
|
|
|
|
|
- scope.dispatchEvent( { type: 'sessionend' } );
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
+ this.setFramebufferScaleFactor = function ( value ) {
|
|
|
|
|
|
- this.setFramebufferScaleFactor = function ( value ) {
|
|
|
+ framebufferScaleFactor = value;
|
|
|
|
|
|
- framebufferScaleFactor = value;
|
|
|
+ if ( scope.isPresenting === true ) {
|
|
|
|
|
|
- if ( scope.isPresenting === true ) {
|
|
|
+ console.warn( 'THREE.WebXRManager: Cannot change framebuffer scale while presenting.' );
|
|
|
|
|
|
- console.warn( 'THREE.WebXRManager: Cannot change framebuffer scale while presenting.' );
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
+ };
|
|
|
|
|
|
- };
|
|
|
+ this.setReferenceSpaceType = function ( value ) {
|
|
|
|
|
|
- this.setReferenceSpaceType = function ( value ) {
|
|
|
+ referenceSpaceType = value;
|
|
|
|
|
|
- referenceSpaceType = value;
|
|
|
+ if ( scope.isPresenting === true ) {
|
|
|
|
|
|
- if ( scope.isPresenting === true ) {
|
|
|
+ console.warn( 'THREE.WebXRManager: Cannot change reference space type while presenting.' );
|
|
|
|
|
|
- console.warn( 'THREE.WebXRManager: Cannot change reference space type while presenting.' );
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
+ };
|
|
|
|
|
|
- };
|
|
|
+ this.getReferenceSpace = function () {
|
|
|
|
|
|
- this.getReferenceSpace = function () {
|
|
|
+ return referenceSpace;
|
|
|
|
|
|
- return referenceSpace;
|
|
|
+ };
|
|
|
|
|
|
- };
|
|
|
+ this.getSession = function () {
|
|
|
|
|
|
- this.getSession = function () {
|
|
|
+ return session;
|
|
|
|
|
|
- return session;
|
|
|
+ };
|
|
|
|
|
|
- };
|
|
|
+ this.setSession = async function ( value ) {
|
|
|
|
|
|
- this.setSession = async function ( value ) {
|
|
|
+ session = value;
|
|
|
|
|
|
- session = value;
|
|
|
+ if ( session !== null ) {
|
|
|
|
|
|
- if ( session !== null ) {
|
|
|
+ session.addEventListener( 'select', onSessionEvent );
|
|
|
+ session.addEventListener( 'selectstart', onSessionEvent );
|
|
|
+ session.addEventListener( 'selectend', onSessionEvent );
|
|
|
+ session.addEventListener( 'squeeze', onSessionEvent );
|
|
|
+ session.addEventListener( 'squeezestart', onSessionEvent );
|
|
|
+ session.addEventListener( 'squeezeend', onSessionEvent );
|
|
|
+ session.addEventListener( 'end', onSessionEnd );
|
|
|
+ session.addEventListener( 'inputsourceschange', onInputSourcesChange );
|
|
|
|
|
|
- session.addEventListener( 'select', onSessionEvent );
|
|
|
- session.addEventListener( 'selectstart', onSessionEvent );
|
|
|
- session.addEventListener( 'selectend', onSessionEvent );
|
|
|
- session.addEventListener( 'squeeze', onSessionEvent );
|
|
|
- session.addEventListener( 'squeezestart', onSessionEvent );
|
|
|
- session.addEventListener( 'squeezeend', onSessionEvent );
|
|
|
- session.addEventListener( 'end', onSessionEnd );
|
|
|
- session.addEventListener( 'inputsourceschange', onInputSourcesChange );
|
|
|
+ const attributes = gl.getContextAttributes();
|
|
|
|
|
|
- const attributes = gl.getContextAttributes();
|
|
|
+ if ( attributes.xrCompatible !== true ) {
|
|
|
|
|
|
- if ( attributes.xrCompatible !== true ) {
|
|
|
+ await gl.makeXRCompatible();
|
|
|
|
|
|
- await gl.makeXRCompatible();
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
+ const layerInit = {
|
|
|
+ antialias: attributes.antialias,
|
|
|
+ alpha: attributes.alpha,
|
|
|
+ depth: attributes.depth,
|
|
|
+ stencil: attributes.stencil,
|
|
|
+ framebufferScaleFactor: framebufferScaleFactor
|
|
|
+ };
|
|
|
|
|
|
- const layerInit = {
|
|
|
- antialias: attributes.antialias,
|
|
|
- alpha: attributes.alpha,
|
|
|
- depth: attributes.depth,
|
|
|
- stencil: attributes.stencil,
|
|
|
- framebufferScaleFactor: framebufferScaleFactor
|
|
|
- };
|
|
|
+ // eslint-disable-next-line no-undef
|
|
|
+ const baseLayer = new XRWebGLLayer( session, gl, layerInit );
|
|
|
|
|
|
- // eslint-disable-next-line no-undef
|
|
|
- const baseLayer = new XRWebGLLayer( session, gl, layerInit );
|
|
|
+ session.updateRenderState( { baseLayer: baseLayer } );
|
|
|
|
|
|
- session.updateRenderState( { baseLayer: baseLayer } );
|
|
|
+ referenceSpace = await session.requestReferenceSpace( referenceSpaceType );
|
|
|
|
|
|
- referenceSpace = await session.requestReferenceSpace( referenceSpaceType );
|
|
|
+ animation.setContext( session );
|
|
|
+ animation.start();
|
|
|
|
|
|
- animation.setContext( session );
|
|
|
- animation.start();
|
|
|
+ scope.isPresenting = true;
|
|
|
|
|
|
- scope.isPresenting = true;
|
|
|
+ scope.dispatchEvent( { type: 'sessionstart' } );
|
|
|
|
|
|
- scope.dispatchEvent( { type: 'sessionstart' } );
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
+ };
|
|
|
|
|
|
- };
|
|
|
+ function onInputSourcesChange( event ) {
|
|
|
|
|
|
- function onInputSourcesChange( event ) {
|
|
|
+ const inputSources = session.inputSources;
|
|
|
|
|
|
- const inputSources = session.inputSources;
|
|
|
+ // Assign inputSources to available controllers
|
|
|
|
|
|
- // Assign inputSources to available controllers
|
|
|
+ for ( let i = 0; i < controllers.length; i ++ ) {
|
|
|
|
|
|
- for ( let i = 0; i < controllers.length; i ++ ) {
|
|
|
+ inputSourcesMap.set( inputSources[ i ], controllers[ i ] );
|
|
|
|
|
|
- inputSourcesMap.set( inputSources[ i ], controllers[ i ] );
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
+ // Notify disconnected
|
|
|
|
|
|
- // Notify disconnected
|
|
|
+ for ( let i = 0; i < event.removed.length; i ++ ) {
|
|
|
|
|
|
- for ( let i = 0; i < event.removed.length; i ++ ) {
|
|
|
+ const inputSource = event.removed[ i ];
|
|
|
+ const controller = inputSourcesMap.get( inputSource );
|
|
|
|
|
|
- const inputSource = event.removed[ i ];
|
|
|
- const controller = inputSourcesMap.get( inputSource );
|
|
|
+ if ( controller ) {
|
|
|
|
|
|
- if ( controller ) {
|
|
|
+ controller.dispatchEvent( { type: 'disconnected', data: inputSource } );
|
|
|
+ inputSourcesMap.delete( inputSource );
|
|
|
|
|
|
- controller.dispatchEvent( { type: 'disconnected', data: inputSource } );
|
|
|
- inputSourcesMap.delete( inputSource );
|
|
|
+ }
|
|
|
|
|
|
}
|
|
|
|
|
|
- }
|
|
|
+ // Notify connected
|
|
|
|
|
|
- // Notify connected
|
|
|
+ for ( let i = 0; i < event.added.length; i ++ ) {
|
|
|
|
|
|
- for ( let i = 0; i < event.added.length; i ++ ) {
|
|
|
+ const inputSource = event.added[ i ];
|
|
|
+ const controller = inputSourcesMap.get( inputSource );
|
|
|
|
|
|
- const inputSource = event.added[ i ];
|
|
|
- const controller = inputSourcesMap.get( inputSource );
|
|
|
+ if ( controller ) {
|
|
|
|
|
|
- if ( controller ) {
|
|
|
+ controller.dispatchEvent( { type: 'connected', data: inputSource } );
|
|
|
|
|
|
- controller.dispatchEvent( { type: 'connected', data: inputSource } );
|
|
|
+ }
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
- }
|
|
|
+ //
|
|
|
|
|
|
- //
|
|
|
+ const cameraLPos = new Vector3();
|
|
|
+ const cameraRPos = new Vector3();
|
|
|
|
|
|
- const cameraLPos = new Vector3();
|
|
|
- const cameraRPos = new Vector3();
|
|
|
+ /**
|
|
|
+ * Assumes 2 cameras that are parallel and share an X-axis, and that
|
|
|
+ * the cameras' projection and world matrices have already been set.
|
|
|
+ * And that near and far planes are identical for both cameras.
|
|
|
+ * Visualization of this technique: https://computergraphics.stackexchange.com/a/4765
|
|
|
+ */
|
|
|
+ function setProjectionFromUnion( camera, cameraL, cameraR ) {
|
|
|
|
|
|
- /**
|
|
|
- * Assumes 2 cameras that are parallel and share an X-axis, and that
|
|
|
- * the cameras' projection and world matrices have already been set.
|
|
|
- * And that near and far planes are identical for both cameras.
|
|
|
- * Visualization of this technique: https://computergraphics.stackexchange.com/a/4765
|
|
|
- */
|
|
|
- function setProjectionFromUnion( camera, cameraL, cameraR ) {
|
|
|
+ cameraLPos.setFromMatrixPosition( cameraL.matrixWorld );
|
|
|
+ cameraRPos.setFromMatrixPosition( cameraR.matrixWorld );
|
|
|
+
|
|
|
+ const ipd = cameraLPos.distanceTo( cameraRPos );
|
|
|
|
|
|
- cameraLPos.setFromMatrixPosition( cameraL.matrixWorld );
|
|
|
- cameraRPos.setFromMatrixPosition( cameraR.matrixWorld );
|
|
|
+ const projL = cameraL.projectionMatrix.elements;
|
|
|
+ const projR = cameraR.projectionMatrix.elements;
|
|
|
|
|
|
- const ipd = cameraLPos.distanceTo( cameraRPos );
|
|
|
+ // VR systems will have identical far and near planes, and
|
|
|
+ // most likely identical top and bottom frustum extents.
|
|
|
+ // Use the left camera for these values.
|
|
|
+ const near = projL[ 14 ] / ( projL[ 10 ] - 1 );
|
|
|
+ const far = projL[ 14 ] / ( projL[ 10 ] + 1 );
|
|
|
+ const topFov = ( projL[ 9 ] + 1 ) / projL[ 5 ];
|
|
|
+ const bottomFov = ( projL[ 9 ] - 1 ) / projL[ 5 ];
|
|
|
|
|
|
- const projL = cameraL.projectionMatrix.elements;
|
|
|
- const projR = cameraR.projectionMatrix.elements;
|
|
|
+ const leftFov = ( projL[ 8 ] - 1 ) / projL[ 0 ];
|
|
|
+ const rightFov = ( projR[ 8 ] + 1 ) / projR[ 0 ];
|
|
|
+ const left = near * leftFov;
|
|
|
+ const right = near * rightFov;
|
|
|
|
|
|
- // VR systems will have identical far and near planes, and
|
|
|
- // most likely identical top and bottom frustum extents.
|
|
|
- // Use the left camera for these values.
|
|
|
- const near = projL[ 14 ] / ( projL[ 10 ] - 1 );
|
|
|
- const far = projL[ 14 ] / ( projL[ 10 ] + 1 );
|
|
|
- const topFov = ( projL[ 9 ] + 1 ) / projL[ 5 ];
|
|
|
- const bottomFov = ( projL[ 9 ] - 1 ) / projL[ 5 ];
|
|
|
+ // Calculate the new camera's position offset from the
|
|
|
+ // left camera. xOffset should be roughly half `ipd`.
|
|
|
+ const zOffset = ipd / ( - leftFov + rightFov );
|
|
|
+ const xOffset = zOffset * - leftFov;
|
|
|
|
|
|
- const leftFov = ( projL[ 8 ] - 1 ) / projL[ 0 ];
|
|
|
- const rightFov = ( projR[ 8 ] + 1 ) / projR[ 0 ];
|
|
|
- const left = near * leftFov;
|
|
|
- const right = near * rightFov;
|
|
|
+ // TODO: Better way to apply this offset?
|
|
|
+ cameraL.matrixWorld.decompose( camera.position, camera.quaternion, camera.scale );
|
|
|
+ camera.translateX( xOffset );
|
|
|
+ camera.translateZ( zOffset );
|
|
|
+ camera.matrixWorld.compose( camera.position, camera.quaternion, camera.scale );
|
|
|
+ camera.matrixWorldInverse.copy( camera.matrixWorld ).invert();
|
|
|
|
|
|
- // Calculate the new camera's position offset from the
|
|
|
- // left camera. xOffset should be roughly half `ipd`.
|
|
|
- const zOffset = ipd / ( - leftFov + rightFov );
|
|
|
- const xOffset = zOffset * - leftFov;
|
|
|
+ // Find the union of the frustum values of the cameras and scale
|
|
|
+ // the values so that the near plane's position does not change in world space,
|
|
|
+ // although must now be relative to the new union camera.
|
|
|
+ const near2 = near + zOffset;
|
|
|
+ const far2 = far + zOffset;
|
|
|
+ const left2 = left - xOffset;
|
|
|
+ const right2 = right + ( ipd - xOffset );
|
|
|
+ const top2 = topFov * far / far2 * near2;
|
|
|
+ const bottom2 = bottomFov * far / far2 * near2;
|
|
|
|
|
|
- // TODO: Better way to apply this offset?
|
|
|
- cameraL.matrixWorld.decompose( camera.position, camera.quaternion, camera.scale );
|
|
|
- camera.translateX( xOffset );
|
|
|
- camera.translateZ( zOffset );
|
|
|
- camera.matrixWorld.compose( camera.position, camera.quaternion, camera.scale );
|
|
|
- camera.matrixWorldInverse.copy( camera.matrixWorld ).invert();
|
|
|
+ camera.projectionMatrix.makePerspective( left2, right2, top2, bottom2, near2, far2 );
|
|
|
|
|
|
- // Find the union of the frustum values of the cameras and scale
|
|
|
- // the values so that the near plane's position does not change in world space,
|
|
|
- // although must now be relative to the new union camera.
|
|
|
- const near2 = near + zOffset;
|
|
|
- const far2 = far + zOffset;
|
|
|
- const left2 = left - xOffset;
|
|
|
- const right2 = right + ( ipd - xOffset );
|
|
|
- const top2 = topFov * far / far2 * near2;
|
|
|
- const bottom2 = bottomFov * far / far2 * near2;
|
|
|
+ }
|
|
|
|
|
|
- camera.projectionMatrix.makePerspective( left2, right2, top2, bottom2, near2, far2 );
|
|
|
+ function updateCamera( camera, parent ) {
|
|
|
|
|
|
- }
|
|
|
+ if ( parent === null ) {
|
|
|
|
|
|
- function updateCamera( camera, parent ) {
|
|
|
+ camera.matrixWorld.copy( camera.matrix );
|
|
|
|
|
|
- if ( parent === null ) {
|
|
|
+ } else {
|
|
|
|
|
|
- camera.matrixWorld.copy( camera.matrix );
|
|
|
+ camera.matrixWorld.multiplyMatrices( parent.matrixWorld, camera.matrix );
|
|
|
|
|
|
- } else {
|
|
|
+ }
|
|
|
|
|
|
- camera.matrixWorld.multiplyMatrices( parent.matrixWorld, camera.matrix );
|
|
|
+ camera.matrixWorldInverse.copy( camera.matrixWorld ).invert();
|
|
|
|
|
|
}
|
|
|
|
|
|
- camera.matrixWorldInverse.copy( camera.matrixWorld ).invert();
|
|
|
-
|
|
|
- }
|
|
|
+ this.getCamera = function ( camera ) {
|
|
|
|
|
|
- this.getCamera = function ( camera ) {
|
|
|
+ cameraVR.near = cameraR.near = cameraL.near = camera.near;
|
|
|
+ cameraVR.far = cameraR.far = cameraL.far = camera.far;
|
|
|
|
|
|
- cameraVR.near = cameraR.near = cameraL.near = camera.near;
|
|
|
- cameraVR.far = cameraR.far = cameraL.far = camera.far;
|
|
|
+ if ( _currentDepthNear !== cameraVR.near || _currentDepthFar !== cameraVR.far ) {
|
|
|
|
|
|
- if ( _currentDepthNear !== cameraVR.near || _currentDepthFar !== cameraVR.far ) {
|
|
|
+ // Note that the new renderState won't apply until the next frame. See #18320
|
|
|
|
|
|
- // Note that the new renderState won't apply until the next frame. See #18320
|
|
|
+ session.updateRenderState( {
|
|
|
+ depthNear: cameraVR.near,
|
|
|
+ depthFar: cameraVR.far
|
|
|
+ } );
|
|
|
|
|
|
- session.updateRenderState( {
|
|
|
- depthNear: cameraVR.near,
|
|
|
- depthFar: cameraVR.far
|
|
|
- } );
|
|
|
+ _currentDepthNear = cameraVR.near;
|
|
|
+ _currentDepthFar = cameraVR.far;
|
|
|
|
|
|
- _currentDepthNear = cameraVR.near;
|
|
|
- _currentDepthFar = cameraVR.far;
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
+ const parent = camera.parent;
|
|
|
+ const cameras = cameraVR.cameras;
|
|
|
|
|
|
- const parent = camera.parent;
|
|
|
- const cameras = cameraVR.cameras;
|
|
|
+ updateCamera( cameraVR, parent );
|
|
|
|
|
|
- updateCamera( cameraVR, parent );
|
|
|
+ for ( let i = 0; i < cameras.length; i ++ ) {
|
|
|
|
|
|
- for ( let i = 0; i < cameras.length; i ++ ) {
|
|
|
+ updateCamera( cameras[ i ], parent );
|
|
|
|
|
|
- updateCamera( cameras[ i ], parent );
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
+ // update camera and its children
|
|
|
|
|
|
- // update camera and its children
|
|
|
+ camera.matrixWorld.copy( cameraVR.matrixWorld );
|
|
|
+ camera.matrix.copy( cameraVR.matrix );
|
|
|
+ camera.matrix.decompose( camera.position, camera.quaternion, camera.scale );
|
|
|
|
|
|
- camera.matrixWorld.copy( cameraVR.matrixWorld );
|
|
|
- camera.matrix.copy( cameraVR.matrix );
|
|
|
- camera.matrix.decompose( camera.position, camera.quaternion, camera.scale );
|
|
|
+ const children = camera.children;
|
|
|
|
|
|
- const children = camera.children;
|
|
|
+ for ( let i = 0, l = children.length; i < l; i ++ ) {
|
|
|
|
|
|
- for ( let i = 0, l = children.length; i < l; i ++ ) {
|
|
|
+ children[ i ].updateMatrixWorld( true );
|
|
|
|
|
|
- children[ i ].updateMatrixWorld( true );
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
+ // update projection matrix for proper view frustum culling
|
|
|
|
|
|
- // update projection matrix for proper view frustum culling
|
|
|
+ if ( cameras.length === 2 ) {
|
|
|
|
|
|
- if ( cameras.length === 2 ) {
|
|
|
+ setProjectionFromUnion( cameraVR, cameraL, cameraR );
|
|
|
|
|
|
- setProjectionFromUnion( cameraVR, cameraL, cameraR );
|
|
|
+ } else {
|
|
|
|
|
|
- } else {
|
|
|
+ // assume single camera setup (AR)
|
|
|
|
|
|
- // assume single camera setup (AR)
|
|
|
+ cameraVR.projectionMatrix.copy( cameraL.projectionMatrix );
|
|
|
|
|
|
- cameraVR.projectionMatrix.copy( cameraL.projectionMatrix );
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
+ return cameraVR;
|
|
|
|
|
|
- return cameraVR;
|
|
|
+ };
|
|
|
|
|
|
- };
|
|
|
+ // Animation Loop
|
|
|
|
|
|
- // Animation Loop
|
|
|
+ let onAnimationFrameCallback = null;
|
|
|
|
|
|
- let onAnimationFrameCallback = null;
|
|
|
+ function onAnimationFrame( time, frame ) {
|
|
|
|
|
|
- function onAnimationFrame( time, frame ) {
|
|
|
+ pose = frame.getViewerPose( referenceSpace );
|
|
|
|
|
|
- pose = frame.getViewerPose( referenceSpace );
|
|
|
+ if ( pose !== null ) {
|
|
|
|
|
|
- if ( pose !== null ) {
|
|
|
+ const views = pose.views;
|
|
|
+ const baseLayer = session.renderState.baseLayer;
|
|
|
|
|
|
- const views = pose.views;
|
|
|
- const baseLayer = session.renderState.baseLayer;
|
|
|
+ state.bindXRFramebuffer( baseLayer.framebuffer );
|
|
|
|
|
|
- state.bindXRFramebuffer( baseLayer.framebuffer );
|
|
|
+ let cameraVRNeedsUpdate = false;
|
|
|
|
|
|
- let cameraVRNeedsUpdate = false;
|
|
|
+ // check if it's necessary to rebuild cameraVR's camera list
|
|
|
|
|
|
- // check if it's necessary to rebuild cameraVR's camera list
|
|
|
+ if ( views.length !== cameraVR.cameras.length ) {
|
|
|
|
|
|
- if ( views.length !== cameraVR.cameras.length ) {
|
|
|
+ cameraVR.cameras.length = 0;
|
|
|
+ cameraVRNeedsUpdate = true;
|
|
|
|
|
|
- cameraVR.cameras.length = 0;
|
|
|
- cameraVRNeedsUpdate = true;
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
+ for ( let i = 0; i < views.length; i ++ ) {
|
|
|
|
|
|
- for ( let i = 0; i < views.length; i ++ ) {
|
|
|
+ const view = views[ i ];
|
|
|
+ const viewport = baseLayer.getViewport( view );
|
|
|
|
|
|
- const view = views[ i ];
|
|
|
- const viewport = baseLayer.getViewport( view );
|
|
|
+ const camera = cameras[ i ];
|
|
|
+ camera.matrix.fromArray( view.transform.matrix );
|
|
|
+ camera.projectionMatrix.fromArray( view.projectionMatrix );
|
|
|
+ camera.viewport.set( viewport.x, viewport.y, viewport.width, viewport.height );
|
|
|
|
|
|
- const camera = cameras[ i ];
|
|
|
- camera.matrix.fromArray( view.transform.matrix );
|
|
|
- camera.projectionMatrix.fromArray( view.projectionMatrix );
|
|
|
- camera.viewport.set( viewport.x, viewport.y, viewport.width, viewport.height );
|
|
|
+ if ( i === 0 ) {
|
|
|
|
|
|
- if ( i === 0 ) {
|
|
|
+ cameraVR.matrix.copy( camera.matrix );
|
|
|
|
|
|
- cameraVR.matrix.copy( camera.matrix );
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
+ if ( cameraVRNeedsUpdate === true ) {
|
|
|
|
|
|
- if ( cameraVRNeedsUpdate === true ) {
|
|
|
+ cameraVR.cameras.push( camera );
|
|
|
|
|
|
- cameraVR.cameras.push( camera );
|
|
|
+ }
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
- }
|
|
|
+ //
|
|
|
|
|
|
- //
|
|
|
+ const inputSources = session.inputSources;
|
|
|
|
|
|
- const inputSources = session.inputSources;
|
|
|
+ for ( let i = 0; i < controllers.length; i ++ ) {
|
|
|
|
|
|
- for ( let i = 0; i < controllers.length; i ++ ) {
|
|
|
+ const controller = controllers[ i ];
|
|
|
+ const inputSource = inputSources[ i ];
|
|
|
|
|
|
- const controller = controllers[ i ];
|
|
|
- const inputSource = inputSources[ i ];
|
|
|
+ controller.update( inputSource, frame, referenceSpace );
|
|
|
|
|
|
- controller.update( inputSource, frame, referenceSpace );
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
+ if ( onAnimationFrameCallback ) onAnimationFrameCallback( time, frame );
|
|
|
|
|
|
- if ( onAnimationFrameCallback ) onAnimationFrameCallback( time, frame );
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
+ const animation = new WebGLAnimation();
|
|
|
+ animation.setAnimationLoop( onAnimationFrame );
|
|
|
|
|
|
- const animation = new WebGLAnimation();
|
|
|
- animation.setAnimationLoop( onAnimationFrame );
|
|
|
+ this.setAnimationLoop = function ( callback ) {
|
|
|
|
|
|
- this.setAnimationLoop = function ( callback ) {
|
|
|
+ onAnimationFrameCallback = callback;
|
|
|
|
|
|
- onAnimationFrameCallback = callback;
|
|
|
+ };
|
|
|
|
|
|
- };
|
|
|
+ this.dispose = function () {};
|
|
|
|
|
|
- this.dispose = function () {};
|
|
|
+ }
|
|
|
|
|
|
}
|
|
|
|
|
|
-Object.assign( WebXRManager.prototype, EventDispatcher.prototype );
|
|
|
-
|
|
|
function WebGLMaterials( properties ) {
|
|
|
|
|
|
function refreshFogUniforms( uniforms, fog ) {
|