]> gitweb.ps.run Git - cloth_sim/commitdiff
copy old files for refactoring, update Three.js
authorPatrick Schönberger <patrick.schoenberger@posteo.de>
Sat, 6 Feb 2021 09:40:52 +0000 (10:40 +0100)
committerPatrick Schönberger <patrick.schoenberger@posteo.de>
Sat, 6 Feb 2021 09:40:52 +0000 (10:40 +0100)
Scripts/OrbitControls.js
Scripts/_cloth.js [new file with mode: 0644]
Scripts/_main.js [new file with mode: 0644]
Scripts/cloth.js
Scripts/main.js
Scripts/three.js
Scripts/three.module.js

index 8695c999028cc29768a664a921d659cd9d8225c1..54a09ef88152270340c1c5dc130339f689140c0a 100644 (file)
-import {\r
-       EventDispatcher,\r
-       MOUSE,\r
-       Quaternion,\r
-       Spherical,\r
-       TOUCH,\r
-       Vector2,\r
-       Vector3\r
-} from './three.module.js';\r
-\r
-// This set of controls performs orbiting, dollying (zooming), and panning.\r
-// Unlike TrackballControls, it maintains the "up" direction object.up (+Y by default).\r
-//\r
-//    Orbit - left mouse / touch: one-finger move\r
-//    Zoom - middle mouse, or mousewheel / touch: two-finger spread or squish\r
-//    Pan - right mouse, or left mouse + ctrl/meta/shiftKey, or arrow keys / touch: two-finger move\r
-\r
-var OrbitControls = function ( object, domElement ) {\r
-\r
-       if ( domElement === undefined ) console.warn( 'THREE.OrbitControls: The second parameter "domElement" is now mandatory.' );\r
-       if ( domElement === document ) console.error( 'THREE.OrbitControls: "document" should not be used as the target "domElement". Please use "renderer.domElement" instead.' );\r
-\r
-       this.object = object;\r
-       this.domElement = domElement;\r
-\r
-       // Set to false to disable this control\r
-       this.enabled = true;\r
-\r
-       // "target" sets the location of focus, where the object orbits around\r
-       this.target = new Vector3();\r
-\r
-       // How far you can dolly in and out ( PerspectiveCamera only )\r
-       this.minDistance = 0;\r
-       this.maxDistance = Infinity;\r
-\r
-       // How far you can zoom in and out ( OrthographicCamera only )\r
-       this.minZoom = 0;\r
-       this.maxZoom = Infinity;\r
-\r
-       // How far you can orbit vertically, upper and lower limits.\r
-       // Range is 0 to Math.PI radians.\r
-       this.minPolarAngle = 0; // radians\r
-       this.maxPolarAngle = Math.PI; // radians\r
-\r
-       // How far you can orbit horizontally, upper and lower limits.\r
-       // If set, the interval [ min, max ] must be a sub-interval of [ - 2 PI, 2 PI ], with ( max - min < 2 PI )\r
-       this.minAzimuthAngle = - Infinity; // radians\r
-       this.maxAzimuthAngle = Infinity; // radians\r
-\r
-       // Set to true to enable damping (inertia)\r
-       // If damping is enabled, you must call controls.update() in your animation loop\r
-       this.enableDamping = false;\r
-       this.dampingFactor = 0.05;\r
-\r
-       // This option actually enables dollying in and out; left as "zoom" for backwards compatibility.\r
-       // Set to false to disable zooming\r
-       this.enableZoom = true;\r
-       this.zoomSpeed = 1.0;\r
-\r
-       // Set to false to disable rotating\r
-       this.enableRotate = true;\r
-       this.rotateSpeed = 1.0;\r
-\r
-       // Set to false to disable panning\r
-       this.enablePan = true;\r
-       this.panSpeed = 1.0;\r
-       this.screenSpacePanning = true; // if false, pan orthogonal to world-space direction camera.up\r
-       this.keyPanSpeed = 7.0; // pixels moved per arrow key push\r
-\r
-       // Set to true to automatically rotate around the target\r
-       // If auto-rotate is enabled, you must call controls.update() in your animation loop\r
-       this.autoRotate = false;\r
-       this.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60\r
-\r
-       // The four arrow keys\r
-       this.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40 };\r
-\r
-       // Mouse buttons\r
-       this.mouseButtons = { LEFT: MOUSE.ROTATE, MIDDLE: MOUSE.DOLLY, RIGHT: MOUSE.PAN };\r
-\r
-       // Touch fingers\r
-       this.touches = { ONE: TOUCH.ROTATE, TWO: TOUCH.DOLLY_PAN };\r
-\r
-       // for reset\r
-       this.target0 = this.target.clone();\r
-       this.position0 = this.object.position.clone();\r
-       this.zoom0 = this.object.zoom;\r
-\r
-       // the target DOM element for key events\r
-       this._domElementKeyEvents = null;\r
-\r
-       //\r
-       // public methods\r
-       //\r
-\r
-       this.getPolarAngle = function () {\r
-\r
-               return spherical.phi;\r
-\r
-       };\r
-\r
-       this.getAzimuthalAngle = function () {\r
-\r
-               return spherical.theta;\r
-\r
-       };\r
-\r
-       this.listenToKeyEvents = function ( domElement ) {\r
-\r
-               domElement.addEventListener( 'keydown', onKeyDown );\r
-               this._domElementKeyEvents = domElement;\r
-\r
-       };\r
-\r
-       this.saveState = function () {\r
-\r
-               scope.target0.copy( scope.target );\r
-               scope.position0.copy( scope.object.position );\r
-               scope.zoom0 = scope.object.zoom;\r
-\r
-       };\r
-\r
-       this.reset = function () {\r
-\r
-               scope.target.copy( scope.target0 );\r
-               scope.object.position.copy( scope.position0 );\r
-               scope.object.zoom = scope.zoom0;\r
-\r
-               scope.object.updateProjectionMatrix();\r
-               scope.dispatchEvent( changeEvent );\r
-\r
-               scope.update();\r
-\r
-               state = STATE.NONE;\r
-\r
-       };\r
-\r
-       // this method is exposed, but perhaps it would be better if we can make it private...\r
-       this.update = function () {\r
-\r
-               var offset = new Vector3();\r
-\r
-               // so camera.up is the orbit axis\r
-               var quat = new Quaternion().setFromUnitVectors( object.up, new Vector3( 0, 1, 0 ) );\r
-               var quatInverse = quat.clone().invert();\r
-\r
-               var lastPosition = new Vector3();\r
-               var lastQuaternion = new Quaternion();\r
-\r
-               var twoPI = 2 * Math.PI;\r
-\r
-               return function update() {\r
-\r
-                       var position = scope.object.position;\r
-\r
-                       offset.copy( position ).sub( scope.target );\r
-\r
-                       // rotate offset to "y-axis-is-up" space\r
-                       offset.applyQuaternion( quat );\r
-\r
-                       // angle from z-axis around y-axis\r
-                       spherical.setFromVector3( offset );\r
-\r
-                       if ( scope.autoRotate && state === STATE.NONE ) {\r
-\r
-                               rotateLeft( getAutoRotationAngle() );\r
-\r
-                       }\r
-\r
-                       if ( scope.enableDamping ) {\r
-\r
-                               spherical.theta += sphericalDelta.theta * scope.dampingFactor;\r
-                               spherical.phi += sphericalDelta.phi * scope.dampingFactor;\r
-\r
-                       } else {\r
-\r
-                               spherical.theta += sphericalDelta.theta;\r
-                               spherical.phi += sphericalDelta.phi;\r
-\r
-                       }\r
-\r
-                       // restrict theta to be between desired limits\r
-\r
-                       var min = scope.minAzimuthAngle;\r
-                       var max = scope.maxAzimuthAngle;\r
-\r
-                       if ( isFinite( min ) && isFinite( max ) ) {\r
-\r
-                               if ( min < - Math.PI ) min += twoPI; else if ( min > Math.PI ) min -= twoPI;\r
-\r
-                               if ( max < - Math.PI ) max += twoPI; else if ( max > Math.PI ) max -= twoPI;\r
-\r
-                               if ( min <= max ) {\r
-\r
-                                       spherical.theta = Math.max( min, Math.min( max, spherical.theta ) );\r
-\r
-                               } else {\r
-\r
-                                       spherical.theta = ( spherical.theta > ( min + max ) / 2 ) ?\r
-                                               Math.max( min, spherical.theta ) :\r
-                                               Math.min( max, spherical.theta );\r
-\r
-                               }\r
-\r
-                       }\r
-\r
-                       // restrict phi to be between desired limits\r
-                       spherical.phi = Math.max( scope.minPolarAngle, Math.min( scope.maxPolarAngle, spherical.phi ) );\r
-\r
-                       spherical.makeSafe();\r
-\r
-\r
-                       spherical.radius *= scale;\r
-\r
-                       // restrict radius to be between desired limits\r
-                       spherical.radius = Math.max( scope.minDistance, Math.min( scope.maxDistance, spherical.radius ) );\r
-\r
-                       // move target to panned location\r
-\r
-                       if ( scope.enableDamping === true ) {\r
-\r
-                               scope.target.addScaledVector( panOffset, scope.dampingFactor );\r
-\r
-                       } else {\r
-\r
-                               scope.target.add( panOffset );\r
-\r
-                       }\r
-\r
-                       offset.setFromSpherical( spherical );\r
-\r
-                       // rotate offset back to "camera-up-vector-is-up" space\r
-                       offset.applyQuaternion( quatInverse );\r
-\r
-                       position.copy( scope.target ).add( offset );\r
-\r
-                       scope.object.lookAt( scope.target );\r
-\r
-                       if ( scope.enableDamping === true ) {\r
-\r
-                               sphericalDelta.theta *= ( 1 - scope.dampingFactor );\r
-                               sphericalDelta.phi *= ( 1 - scope.dampingFactor );\r
-\r
-                               panOffset.multiplyScalar( 1 - scope.dampingFactor );\r
-\r
-                       } else {\r
-\r
-                               sphericalDelta.set( 0, 0, 0 );\r
-\r
-                               panOffset.set( 0, 0, 0 );\r
-\r
-                       }\r
-\r
-                       scale = 1;\r
-\r
-                       // update condition is:\r
-                       // min(camera displacement, camera rotation in radians)^2 > EPS\r
-                       // using small-angle approximation cos(x/2) = 1 - x^2 / 8\r
-\r
-                       if ( zoomChanged ||\r
-                               lastPosition.distanceToSquared( scope.object.position ) > EPS ||\r
-                               8 * ( 1 - lastQuaternion.dot( scope.object.quaternion ) ) > EPS ) {\r
-\r
-                               scope.dispatchEvent( changeEvent );\r
-\r
-                               lastPosition.copy( scope.object.position );\r
-                               lastQuaternion.copy( scope.object.quaternion );\r
-                               zoomChanged = false;\r
-\r
-                               return true;\r
-\r
-                       }\r
-\r
-                       return false;\r
-\r
-               };\r
-\r
-       }();\r
-\r
-       this.dispose = function () {\r
-\r
-               scope.domElement.removeEventListener( 'contextmenu', onContextMenu );\r
-\r
-               scope.domElement.removeEventListener( 'pointerdown', onPointerDown );\r
-               scope.domElement.removeEventListener( 'wheel', onMouseWheel );\r
-\r
-               scope.domElement.removeEventListener( 'touchstart', onTouchStart );\r
-               scope.domElement.removeEventListener( 'touchend', onTouchEnd );\r
-               scope.domElement.removeEventListener( 'touchmove', onTouchMove );\r
-\r
-               scope.domElement.ownerDocument.removeEventListener( 'pointermove', onPointerMove );\r
-               scope.domElement.ownerDocument.removeEventListener( 'pointerup', onPointerUp );\r
-\r
-\r
-               if ( scope._domElementKeyEvents !== null ) {\r
-\r
-                       scope._domElementKeyEvents.removeEventListener( 'keydown', onKeyDown );\r
-\r
-               }\r
-\r
-               //scope.dispatchEvent( { type: 'dispose' } ); // should this be added here?\r
-\r
-       };\r
-\r
-       //\r
-       // internals\r
-       //\r
-\r
-       var scope = this;\r
-\r
-       var changeEvent = { type: 'change' };\r
-       var startEvent = { type: 'start' };\r
-       var endEvent = { type: 'end' };\r
-\r
-       var STATE = {\r
-               NONE: - 1,\r
-               ROTATE: 0,\r
-               DOLLY: 1,\r
-               PAN: 2,\r
-               TOUCH_ROTATE: 3,\r
-               TOUCH_PAN: 4,\r
-               TOUCH_DOLLY_PAN: 5,\r
-               TOUCH_DOLLY_ROTATE: 6\r
-       };\r
-\r
-       var state = STATE.NONE;\r
-\r
-       var EPS = 0.000001;\r
-\r
-       // current position in spherical coordinates\r
-       var spherical = new Spherical();\r
-       var sphericalDelta = new Spherical();\r
-\r
-       var scale = 1;\r
-       var panOffset = new Vector3();\r
-       var zoomChanged = false;\r
-\r
-       var rotateStart = new Vector2();\r
-       var rotateEnd = new Vector2();\r
-       var rotateDelta = new Vector2();\r
-\r
-       var panStart = new Vector2();\r
-       var panEnd = new Vector2();\r
-       var panDelta = new Vector2();\r
-\r
-       var dollyStart = new Vector2();\r
-       var dollyEnd = new Vector2();\r
-       var dollyDelta = new Vector2();\r
-\r
-       function getAutoRotationAngle() {\r
-\r
-               return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed;\r
-\r
-       }\r
-\r
-       function getZoomScale() {\r
-\r
-               return Math.pow( 0.95, scope.zoomSpeed );\r
-\r
-       }\r
-\r
-       function rotateLeft( angle ) {\r
-\r
-               sphericalDelta.theta -= angle;\r
-\r
-       }\r
-\r
-       function rotateUp( angle ) {\r
-\r
-               sphericalDelta.phi -= angle;\r
-\r
-       }\r
-\r
-       var panLeft = function () {\r
-\r
-               var v = new Vector3();\r
-\r
-               return function panLeft( distance, objectMatrix ) {\r
-\r
-                       v.setFromMatrixColumn( objectMatrix, 0 ); // get X column of objectMatrix\r
-                       v.multiplyScalar( - distance );\r
-\r
-                       panOffset.add( v );\r
-\r
-               };\r
-\r
-       }();\r
-\r
-       var panUp = function () {\r
-\r
-               var v = new Vector3();\r
-\r
-               return function panUp( distance, objectMatrix ) {\r
-\r
-                       if ( scope.screenSpacePanning === true ) {\r
-\r
-                               v.setFromMatrixColumn( objectMatrix, 1 );\r
-\r
-                       } else {\r
-\r
-                               v.setFromMatrixColumn( objectMatrix, 0 );\r
-                               v.crossVectors( scope.object.up, v );\r
-\r
-                       }\r
-\r
-                       v.multiplyScalar( distance );\r
-\r
-                       panOffset.add( v );\r
-\r
-               };\r
-\r
-       }();\r
-\r
-       // deltaX and deltaY are in pixels; right and down are positive\r
-       var pan = function () {\r
-\r
-               var offset = new Vector3();\r
-\r
-               return function pan( deltaX, deltaY ) {\r
-\r
-                       var element = scope.domElement;\r
-\r
-                       if ( scope.object.isPerspectiveCamera ) {\r
-\r
-                               // perspective\r
-                               var position = scope.object.position;\r
-                               offset.copy( position ).sub( scope.target );\r
-                               var targetDistance = offset.length();\r
-\r
-                               // half of the fov is center to top of screen\r
-                               targetDistance *= Math.tan( ( scope.object.fov / 2 ) * Math.PI / 180.0 );\r
-\r
-                               // we use only clientHeight here so aspect ratio does not distort speed\r
-                               panLeft( 2 * deltaX * targetDistance / element.clientHeight, scope.object.matrix );\r
-                               panUp( 2 * deltaY * targetDistance / element.clientHeight, scope.object.matrix );\r
-\r
-                       } else if ( scope.object.isOrthographicCamera ) {\r
-\r
-                               // orthographic\r
-                               panLeft( deltaX * ( scope.object.right - scope.object.left ) / scope.object.zoom / element.clientWidth, scope.object.matrix );\r
-                               panUp( deltaY * ( scope.object.top - scope.object.bottom ) / scope.object.zoom / element.clientHeight, scope.object.matrix );\r
-\r
-                       } else {\r
-\r
-                               // camera neither orthographic nor perspective\r
-                               console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.' );\r
-                               scope.enablePan = false;\r
-\r
-                       }\r
-\r
-               };\r
-\r
-       }();\r
-\r
-       function dollyOut( dollyScale ) {\r
-\r
-               if ( scope.object.isPerspectiveCamera ) {\r
-\r
-                       scale /= dollyScale;\r
-\r
-               } else if ( scope.object.isOrthographicCamera ) {\r
-\r
-                       scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom * dollyScale ) );\r
-                       scope.object.updateProjectionMatrix();\r
-                       zoomChanged = true;\r
-\r
-               } else {\r
-\r
-                       console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' );\r
-                       scope.enableZoom = false;\r
-\r
-               }\r
-\r
-       }\r
-\r
-       function dollyIn( dollyScale ) {\r
-\r
-               if ( scope.object.isPerspectiveCamera ) {\r
-\r
-                       scale *= dollyScale;\r
-\r
-               } else if ( scope.object.isOrthographicCamera ) {\r
-\r
-                       scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom / dollyScale ) );\r
-                       scope.object.updateProjectionMatrix();\r
-                       zoomChanged = true;\r
-\r
-               } else {\r
-\r
-                       console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' );\r
-                       scope.enableZoom = false;\r
-\r
-               }\r
-\r
-       }\r
-\r
-       //\r
-       // event callbacks - update the object state\r
-       //\r
-\r
-       function handleMouseDownRotate( event ) {\r
-\r
-               rotateStart.set( event.clientX, event.clientY );\r
-\r
-       }\r
-\r
-       function handleMouseDownDolly( event ) {\r
-\r
-               dollyStart.set( event.clientX, event.clientY );\r
-\r
-       }\r
-\r
-       function handleMouseDownPan( event ) {\r
-\r
-               panStart.set( event.clientX, event.clientY );\r
-\r
-       }\r
-\r
-       function handleMouseMoveRotate( event ) {\r
-\r
-               rotateEnd.set( event.clientX, event.clientY );\r
-\r
-               rotateDelta.subVectors( rotateEnd, rotateStart ).multiplyScalar( scope.rotateSpeed );\r
-\r
-               var element = scope.domElement;\r
-\r
-               rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientHeight ); // yes, height\r
-\r
-               rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight );\r
-\r
-               rotateStart.copy( rotateEnd );\r
-\r
-               scope.update();\r
-\r
-       }\r
-\r
-       function handleMouseMoveDolly( event ) {\r
-\r
-               dollyEnd.set( event.clientX, event.clientY );\r
-\r
-               dollyDelta.subVectors( dollyEnd, dollyStart );\r
-\r
-               if ( dollyDelta.y > 0 ) {\r
-\r
-                       dollyOut( getZoomScale() );\r
-\r
-               } else if ( dollyDelta.y < 0 ) {\r
-\r
-                       dollyIn( getZoomScale() );\r
-\r
-               }\r
-\r
-               dollyStart.copy( dollyEnd );\r
-\r
-               scope.update();\r
-\r
-       }\r
-\r
-       function handleMouseMovePan( event ) {\r
-\r
-               panEnd.set( event.clientX, event.clientY );\r
-\r
-               panDelta.subVectors( panEnd, panStart ).multiplyScalar( scope.panSpeed );\r
-\r
-               pan( panDelta.x, panDelta.y );\r
-\r
-               panStart.copy( panEnd );\r
-\r
-               scope.update();\r
-\r
-       }\r
-\r
-       function handleMouseUp( /*event*/ ) {\r
-\r
-               // no-op\r
-\r
-       }\r
-\r
-       function handleMouseWheel( event ) {\r
-\r
-               if ( event.deltaY < 0 ) {\r
-\r
-                       dollyIn( getZoomScale() );\r
-\r
-               } else if ( event.deltaY > 0 ) {\r
-\r
-                       dollyOut( getZoomScale() );\r
-\r
-               }\r
-\r
-               scope.update();\r
-\r
-       }\r
-\r
-       function handleKeyDown( event ) {\r
-\r
-               var needsUpdate = false;\r
-\r
-               switch ( event.keyCode ) {\r
-\r
-                       case scope.keys.UP:\r
-                               pan( 0, scope.keyPanSpeed );\r
-                               needsUpdate = true;\r
-                               break;\r
-\r
-                       case scope.keys.BOTTOM:\r
-                               pan( 0, - scope.keyPanSpeed );\r
-                               needsUpdate = true;\r
-                               break;\r
-\r
-                       case scope.keys.LEFT:\r
-                               pan( scope.keyPanSpeed, 0 );\r
-                               needsUpdate = true;\r
-                               break;\r
-\r
-                       case scope.keys.RIGHT:\r
-                               pan( - scope.keyPanSpeed, 0 );\r
-                               needsUpdate = true;\r
-                               break;\r
-\r
-               }\r
-\r
-               if ( needsUpdate ) {\r
-\r
-                       // prevent the browser from scrolling on cursor keys\r
-                       event.preventDefault();\r
-\r
-                       scope.update();\r
-\r
-               }\r
-\r
-\r
-       }\r
-\r
-       function handleTouchStartRotate( event ) {\r
-\r
-               if ( event.touches.length == 1 ) {\r
-\r
-                       rotateStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );\r
-\r
-               } else {\r
-\r
-                       var x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX );\r
-                       var y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY );\r
-\r
-                       rotateStart.set( x, y );\r
-\r
-               }\r
-\r
-       }\r
-\r
-       function handleTouchStartPan( event ) {\r
-\r
-               if ( event.touches.length == 1 ) {\r
-\r
-                       panStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );\r
-\r
-               } else {\r
-\r
-                       var x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX );\r
-                       var y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY );\r
-\r
-                       panStart.set( x, y );\r
-\r
-               }\r
-\r
-       }\r
-\r
-       function handleTouchStartDolly( event ) {\r
-\r
-               var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;\r
-               var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;\r
-\r
-               var distance = Math.sqrt( dx * dx + dy * dy );\r
-\r
-               dollyStart.set( 0, distance );\r
-\r
-       }\r
-\r
-       function handleTouchStartDollyPan( event ) {\r
-\r
-               if ( scope.enableZoom ) handleTouchStartDolly( event );\r
-\r
-               if ( scope.enablePan ) handleTouchStartPan( event );\r
-\r
-       }\r
-\r
-       function handleTouchStartDollyRotate( event ) {\r
-\r
-               if ( scope.enableZoom ) handleTouchStartDolly( event );\r
-\r
-               if ( scope.enableRotate ) handleTouchStartRotate( event );\r
-\r
-       }\r
-\r
-       function handleTouchMoveRotate( event ) {\r
-\r
-               if ( event.touches.length == 1 ) {\r
-\r
-                       rotateEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );\r
-\r
-               } else {\r
-\r
-                       var x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX );\r
-                       var y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY );\r
-\r
-                       rotateEnd.set( x, y );\r
-\r
-               }\r
-\r
-               rotateDelta.subVectors( rotateEnd, rotateStart ).multiplyScalar( scope.rotateSpeed );\r
-\r
-               var element = scope.domElement;\r
-\r
-               rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientHeight ); // yes, height\r
-\r
-               rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight );\r
-\r
-               rotateStart.copy( rotateEnd );\r
-\r
-       }\r
-\r
-       function handleTouchMovePan( event ) {\r
-\r
-               if ( event.touches.length == 1 ) {\r
-\r
-                       panEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );\r
-\r
-               } else {\r
-\r
-                       var x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX );\r
-                       var y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY );\r
-\r
-                       panEnd.set( x, y );\r
-\r
-               }\r
-\r
-               panDelta.subVectors( panEnd, panStart ).multiplyScalar( scope.panSpeed );\r
-\r
-               pan( panDelta.x, panDelta.y );\r
-\r
-               panStart.copy( panEnd );\r
-\r
-       }\r
-\r
-       function handleTouchMoveDolly( event ) {\r
-\r
-               var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;\r
-               var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;\r
-\r
-               var distance = Math.sqrt( dx * dx + dy * dy );\r
-\r
-               dollyEnd.set( 0, distance );\r
-\r
-               dollyDelta.set( 0, Math.pow( dollyEnd.y / dollyStart.y, scope.zoomSpeed ) );\r
-\r
-               dollyOut( dollyDelta.y );\r
-\r
-               dollyStart.copy( dollyEnd );\r
-\r
-       }\r
-\r
-       function handleTouchMoveDollyPan( event ) {\r
-\r
-               if ( scope.enableZoom ) handleTouchMoveDolly( event );\r
-\r
-               if ( scope.enablePan ) handleTouchMovePan( event );\r
-\r
-       }\r
-\r
-       function handleTouchMoveDollyRotate( event ) {\r
-\r
-               if ( scope.enableZoom ) handleTouchMoveDolly( event );\r
-\r
-               if ( scope.enableRotate ) handleTouchMoveRotate( event );\r
-\r
-       }\r
-\r
-       function handleTouchEnd( /*event*/ ) {\r
-\r
-               // no-op\r
-\r
-       }\r
-\r
-       //\r
-       // event handlers - FSM: listen for events and reset state\r
-       //\r
-\r
-       function onPointerDown( event ) {\r
-\r
-               if ( scope.enabled === false ) return;\r
-\r
-               switch ( event.pointerType ) {\r
-\r
-                       case 'mouse':\r
-                       case 'pen':\r
-                               onMouseDown( event );\r
-                               break;\r
-\r
-                       // TODO touch\r
-\r
-               }\r
-\r
-       }\r
-\r
-       function onPointerMove( event ) {\r
-\r
-               if ( scope.enabled === false ) return;\r
-\r
-               switch ( event.pointerType ) {\r
-\r
-                       case 'mouse':\r
-                       case 'pen':\r
-                               onMouseMove( event );\r
-                               break;\r
-\r
-                       // TODO touch\r
-\r
-               }\r
-\r
-       }\r
-\r
-       function onPointerUp( event ) {\r
-\r
-               switch ( event.pointerType ) {\r
-\r
-                       case 'mouse':\r
-                       case 'pen':\r
-                               onMouseUp( event );\r
-                               break;\r
-\r
-                       // TODO touch\r
-\r
-               }\r
-\r
-       }\r
-\r
-       function onMouseDown( event ) {\r
-\r
-               // Prevent the browser from scrolling.\r
-               event.preventDefault();\r
-\r
-               // Manually set the focus since calling preventDefault above\r
-               // prevents the browser from setting it automatically.\r
-\r
-               scope.domElement.focus ? scope.domElement.focus() : window.focus();\r
-\r
-               var mouseAction;\r
-\r
-               switch ( event.button ) {\r
-\r
-                       case 0:\r
-\r
-                               mouseAction = scope.mouseButtons.LEFT;\r
-                               break;\r
-\r
-                       case 1:\r
-\r
-                               mouseAction = scope.mouseButtons.MIDDLE;\r
-                               break;\r
-\r
-                       case 2:\r
-\r
-                               mouseAction = scope.mouseButtons.RIGHT;\r
-                               break;\r
-\r
-                       default:\r
-\r
-                               mouseAction = - 1;\r
-\r
-               }\r
-\r
-               switch ( mouseAction ) {\r
-\r
-                       case MOUSE.DOLLY:\r
-\r
-                               if ( scope.enableZoom === false ) return;\r
-\r
-                               handleMouseDownDolly( event );\r
-\r
-                               state = STATE.DOLLY;\r
-\r
-                               break;\r
-\r
-                       case MOUSE.ROTATE:\r
-\r
-                               if ( event.ctrlKey || event.metaKey || event.shiftKey ) {\r
-\r
-                                       if ( scope.enablePan === false ) return;\r
-\r
-                                       handleMouseDownPan( event );\r
-\r
-                                       state = STATE.PAN;\r
-\r
-                               } else {\r
-\r
-                                       if ( scope.enableRotate === false ) return;\r
-\r
-                                       handleMouseDownRotate( event );\r
-\r
-                                       state = STATE.ROTATE;\r
-\r
-                               }\r
-\r
-                               break;\r
-\r
-                       case MOUSE.PAN:\r
-\r
-                               if ( event.ctrlKey || event.metaKey || event.shiftKey ) {\r
-\r
-                                       if ( scope.enableRotate === false ) return;\r
-\r
-                                       handleMouseDownRotate( event );\r
-\r
-                                       state = STATE.ROTATE;\r
-\r
-                               } else {\r
-\r
-                                       if ( scope.enablePan === false ) return;\r
-\r
-                                       handleMouseDownPan( event );\r
-\r
-                                       state = STATE.PAN;\r
-\r
-                               }\r
-\r
-                               break;\r
-\r
-                       default:\r
-\r
-                               state = STATE.NONE;\r
-\r
-               }\r
-\r
-               if ( state !== STATE.NONE ) {\r
-\r
-                       scope.domElement.ownerDocument.addEventListener( 'pointermove', onPointerMove );\r
-                       scope.domElement.ownerDocument.addEventListener( 'pointerup', onPointerUp );\r
-\r
-                       scope.dispatchEvent( startEvent );\r
-\r
-               }\r
-\r
-       }\r
-\r
-       function onMouseMove( event ) {\r
-\r
-               if ( scope.enabled === false ) return;\r
-\r
-               event.preventDefault();\r
-\r
-               switch ( state ) {\r
-\r
-                       case STATE.ROTATE:\r
-\r
-                               if ( scope.enableRotate === false ) return;\r
-\r
-                               handleMouseMoveRotate( event );\r
-\r
-                               break;\r
-\r
-                       case STATE.DOLLY:\r
-\r
-                               if ( scope.enableZoom === false ) return;\r
-\r
-                               handleMouseMoveDolly( event );\r
-\r
-                               break;\r
-\r
-                       case STATE.PAN:\r
-\r
-                               if ( scope.enablePan === false ) return;\r
-\r
-                               handleMouseMovePan( event );\r
-\r
-                               break;\r
-\r
-               }\r
-\r
-       }\r
-\r
-       function onMouseUp( event ) {\r
-\r
-               scope.domElement.ownerDocument.removeEventListener( 'pointermove', onPointerMove );\r
-               scope.domElement.ownerDocument.removeEventListener( 'pointerup', onPointerUp );\r
-\r
-               if ( scope.enabled === false ) return;\r
-\r
-               handleMouseUp( event );\r
-\r
-               scope.dispatchEvent( endEvent );\r
-\r
-               state = STATE.NONE;\r
-\r
-       }\r
-\r
-       function onMouseWheel( event ) {\r
-\r
-               if ( scope.enabled === false || scope.enableZoom === false || ( state !== STATE.NONE && state !== STATE.ROTATE ) ) return;\r
-\r
-               event.preventDefault();\r
-               event.stopPropagation();\r
-\r
-               scope.dispatchEvent( startEvent );\r
-\r
-               handleMouseWheel( event );\r
-\r
-               scope.dispatchEvent( endEvent );\r
-\r
-       }\r
-\r
-       function onKeyDown( event ) {\r
-\r
-               if ( scope.enabled === false || scope.enablePan === false ) return;\r
-\r
-               handleKeyDown( event );\r
-\r
-       }\r
-\r
-       function onTouchStart( event ) {\r
-\r
-               if ( scope.enabled === false ) return;\r
-\r
-               event.preventDefault(); // prevent scrolling\r
-\r
-               switch ( event.touches.length ) {\r
-\r
-                       case 1:\r
-\r
-                               switch ( scope.touches.ONE ) {\r
-\r
-                                       case TOUCH.ROTATE:\r
-\r
-                                               if ( scope.enableRotate === false ) return;\r
-\r
-                                               handleTouchStartRotate( event );\r
-\r
-                                               state = STATE.TOUCH_ROTATE;\r
-\r
-                                               break;\r
-\r
-                                       case TOUCH.PAN:\r
-\r
-                                               if ( scope.enablePan === false ) return;\r
-\r
-                                               handleTouchStartPan( event );\r
-\r
-                                               state = STATE.TOUCH_PAN;\r
-\r
-                                               break;\r
-\r
-                                       default:\r
-\r
-                                               state = STATE.NONE;\r
-\r
-                               }\r
-\r
-                               break;\r
-\r
-                       case 2:\r
-\r
-                               switch ( scope.touches.TWO ) {\r
-\r
-                                       case TOUCH.DOLLY_PAN:\r
-\r
-                                               if ( scope.enableZoom === false && scope.enablePan === false ) return;\r
-\r
-                                               handleTouchStartDollyPan( event );\r
-\r
-                                               state = STATE.TOUCH_DOLLY_PAN;\r
-\r
-                                               break;\r
-\r
-                                       case TOUCH.DOLLY_ROTATE:\r
-\r
-                                               if ( scope.enableZoom === false && scope.enableRotate === false ) return;\r
-\r
-                                               handleTouchStartDollyRotate( event );\r
-\r
-                                               state = STATE.TOUCH_DOLLY_ROTATE;\r
-\r
-                                               break;\r
-\r
-                                       default:\r
-\r
-                                               state = STATE.NONE;\r
-\r
-                               }\r
-\r
-                               break;\r
-\r
-                       default:\r
-\r
-                               state = STATE.NONE;\r
-\r
-               }\r
-\r
-               if ( state !== STATE.NONE ) {\r
-\r
-                       scope.dispatchEvent( startEvent );\r
-\r
-               }\r
-\r
-       }\r
-\r
-       function onTouchMove( event ) {\r
-\r
-               if ( scope.enabled === false ) return;\r
-\r
-               event.preventDefault(); // prevent scrolling\r
-               event.stopPropagation();\r
-\r
-               switch ( state ) {\r
-\r
-                       case STATE.TOUCH_ROTATE:\r
-\r
-                               if ( scope.enableRotate === false ) return;\r
-\r
-                               handleTouchMoveRotate( event );\r
-\r
-                               scope.update();\r
-\r
-                               break;\r
-\r
-                       case STATE.TOUCH_PAN:\r
-\r
-                               if ( scope.enablePan === false ) return;\r
-\r
-                               handleTouchMovePan( event );\r
-\r
-                               scope.update();\r
-\r
-                               break;\r
-\r
-                       case STATE.TOUCH_DOLLY_PAN:\r
-\r
-                               if ( scope.enableZoom === false && scope.enablePan === false ) return;\r
-\r
-                               handleTouchMoveDollyPan( event );\r
-\r
-                               scope.update();\r
-\r
-                               break;\r
-\r
-                       case STATE.TOUCH_DOLLY_ROTATE:\r
-\r
-                               if ( scope.enableZoom === false && scope.enableRotate === false ) return;\r
-\r
-                               handleTouchMoveDollyRotate( event );\r
-\r
-                               scope.update();\r
-\r
-                               break;\r
-\r
-                       default:\r
-\r
-                               state = STATE.NONE;\r
-\r
-               }\r
-\r
-       }\r
-\r
-       function onTouchEnd( event ) {\r
-\r
-               if ( scope.enabled === false ) return;\r
-\r
-               handleTouchEnd( event );\r
-\r
-               scope.dispatchEvent( endEvent );\r
-\r
-               state = STATE.NONE;\r
-\r
-       }\r
-\r
-       function onContextMenu( event ) {\r
-\r
-               if ( scope.enabled === false ) return;\r
-\r
-               event.preventDefault();\r
-\r
-       }\r
-\r
-       //\r
-\r
-       scope.domElement.addEventListener( 'contextmenu', onContextMenu );\r
-\r
-       scope.domElement.addEventListener( 'pointerdown', onPointerDown );\r
-       scope.domElement.addEventListener( 'wheel', onMouseWheel );\r
-\r
-       scope.domElement.addEventListener( 'touchstart', onTouchStart );\r
-       scope.domElement.addEventListener( 'touchend', onTouchEnd );\r
-       scope.domElement.addEventListener( 'touchmove', onTouchMove );\r
-\r
-       // force an update at start\r
-\r
-       this.update();\r
-\r
-};\r
-\r
-OrbitControls.prototype = Object.create( EventDispatcher.prototype );\r
-OrbitControls.prototype.constructor = OrbitControls;\r
-\r
-\r
-// This set of controls performs orbiting, dollying (zooming), and panning.\r
-// Unlike TrackballControls, it maintains the "up" direction object.up (+Y by default).\r
-// This is very similar to OrbitControls, another set of touch behavior\r
-//\r
-//    Orbit - right mouse, or left mouse + ctrl/meta/shiftKey / touch: two-finger rotate\r
-//    Zoom - middle mouse, or mousewheel / touch: two-finger spread or squish\r
-//    Pan - left mouse, or arrow keys / touch: one-finger move\r
-\r
-var MapControls = function ( object, domElement ) {\r
-\r
-       OrbitControls.call( this, object, domElement );\r
-\r
-       this.screenSpacePanning = false; // pan orthogonal to world-space direction camera.up\r
-\r
-       this.mouseButtons.LEFT = MOUSE.PAN;\r
-       this.mouseButtons.RIGHT = MOUSE.ROTATE;\r
-\r
-       this.touches.ONE = TOUCH.PAN;\r
-       this.touches.TWO = TOUCH.DOLLY_ROTATE;\r
-\r
-};\r
-\r
-MapControls.prototype = Object.create( EventDispatcher.prototype );\r
-MapControls.prototype.constructor = MapControls;\r
-\r
-export { OrbitControls, MapControls };
\ No newline at end of file
+// This set of controls performs orbiting, dollying (zooming), and panning.
+// Unlike TrackballControls, it maintains the "up" direction object.up (+Y by default).
+//
+//    Orbit - left mouse / touch: one-finger move
+//    Zoom - middle mouse, or mousewheel / touch: two-finger spread or squish
+//    Pan - right mouse, or left mouse + ctrl/meta/shiftKey, or arrow keys / touch: two-finger move
+
+THREE.OrbitControls = function ( object, domElement ) {
+
+       if ( domElement === undefined ) console.warn( 'THREE.OrbitControls: The second parameter "domElement" is now mandatory.' );
+       if ( domElement === document ) console.error( 'THREE.OrbitControls: "document" should not be used as the target "domElement". Please use "renderer.domElement" instead.' );
+
+       this.object = object;
+       this.domElement = domElement;
+
+       // Set to false to disable this control
+       this.enabled = true;
+
+       // "target" sets the location of focus, where the object orbits around
+       this.target = new THREE.Vector3();
+
+       // How far you can dolly in and out ( PerspectiveCamera only )
+       this.minDistance = 0;
+       this.maxDistance = Infinity;
+
+       // How far you can zoom in and out ( OrthographicCamera only )
+       this.minZoom = 0;
+       this.maxZoom = Infinity;
+
+       // How far you can orbit vertically, upper and lower limits.
+       // Range is 0 to Math.PI radians.
+       this.minPolarAngle = 0; // radians
+       this.maxPolarAngle = Math.PI; // radians
+
+       // How far you can orbit horizontally, upper and lower limits.
+       // If set, the interval [ min, max ] must be a sub-interval of [ - 2 PI, 2 PI ], with ( max - min < 2 PI )
+       this.minAzimuthAngle = - Infinity; // radians
+       this.maxAzimuthAngle = Infinity; // radians
+
+       // Set to true to enable damping (inertia)
+       // If damping is enabled, you must call controls.update() in your animation loop
+       this.enableDamping = false;
+       this.dampingFactor = 0.05;
+
+       // This option actually enables dollying in and out; left as "zoom" for backwards compatibility.
+       // Set to false to disable zooming
+       this.enableZoom = true;
+       this.zoomSpeed = 1.0;
+
+       // Set to false to disable rotating
+       this.enableRotate = true;
+       this.rotateSpeed = 1.0;
+
+       // Set to false to disable panning
+       this.enablePan = true;
+       this.panSpeed = 1.0;
+       this.screenSpacePanning = true; // if false, pan orthogonal to world-space direction camera.up
+       this.keyPanSpeed = 7.0; // pixels moved per arrow key push
+
+       // Set to true to automatically rotate around the target
+       // If auto-rotate is enabled, you must call controls.update() in your animation loop
+       this.autoRotate = false;
+       this.autoRotateSpeed = 2.0; // 30 seconds per orbit when fps is 60
+
+       // The four arrow keys
+       this.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40 };
+
+       // Mouse buttons
+       this.mouseButtons = { LEFT: THREE.MOUSE.ROTATE, MIDDLE: THREE.MOUSE.DOLLY, RIGHT: THREE.MOUSE.PAN };
+
+       // Touch fingers
+       this.touches = { ONE: THREE.TOUCH.ROTATE, TWO: THREE.TOUCH.DOLLY_PAN };
+
+       // for reset
+       this.target0 = this.target.clone();
+       this.position0 = this.object.position.clone();
+       this.zoom0 = this.object.zoom;
+
+       // the target DOM element for key events
+       this._domElementKeyEvents = null;
+
+       //
+       // public methods
+       //
+
+       this.getPolarAngle = function () {
+
+               return spherical.phi;
+
+       };
+
+       this.getAzimuthalAngle = function () {
+
+               return spherical.theta;
+
+       };
+
+       this.listenToKeyEvents = function ( domElement ) {
+
+               domElement.addEventListener( 'keydown', onKeyDown );
+               this._domElementKeyEvents = domElement;
+
+       };
+
+       this.saveState = function () {
+
+               scope.target0.copy( scope.target );
+               scope.position0.copy( scope.object.position );
+               scope.zoom0 = scope.object.zoom;
+
+       };
+
+       this.reset = function () {
+
+               scope.target.copy( scope.target0 );
+               scope.object.position.copy( scope.position0 );
+               scope.object.zoom = scope.zoom0;
+
+               scope.object.updateProjectionMatrix();
+               scope.dispatchEvent( changeEvent );
+
+               scope.update();
+
+               state = STATE.NONE;
+
+       };
+
+       // this method is exposed, but perhaps it would be better if we can make it private...
+       this.update = function () {
+
+               var offset = new THREE.Vector3();
+
+               // so camera.up is the orbit axis
+               var quat = new THREE.Quaternion().setFromUnitVectors( object.up, new THREE.Vector3( 0, 1, 0 ) );
+               var quatInverse = quat.clone().invert();
+
+               var lastPosition = new THREE.Vector3();
+               var lastQuaternion = new THREE.Quaternion();
+
+               var twoPI = 2 * Math.PI;
+
+               return function update() {
+
+                       var position = scope.object.position;
+
+                       offset.copy( position ).sub( scope.target );
+
+                       // rotate offset to "y-axis-is-up" space
+                       offset.applyQuaternion( quat );
+
+                       // angle from z-axis around y-axis
+                       spherical.setFromVector3( offset );
+
+                       if ( scope.autoRotate && state === STATE.NONE ) {
+
+                               rotateLeft( getAutoRotationAngle() );
+
+                       }
+
+                       if ( scope.enableDamping ) {
+
+                               spherical.theta += sphericalDelta.theta * scope.dampingFactor;
+                               spherical.phi += sphericalDelta.phi * scope.dampingFactor;
+
+                       } else {
+
+                               spherical.theta += sphericalDelta.theta;
+                               spherical.phi += sphericalDelta.phi;
+
+                       }
+
+                       // restrict theta to be between desired limits
+
+                       var min = scope.minAzimuthAngle;
+                       var max = scope.maxAzimuthAngle;
+
+                       if ( isFinite( min ) && isFinite( max ) ) {
+
+                               if ( min < - Math.PI ) min += twoPI; else if ( min > Math.PI ) min -= twoPI;
+
+                               if ( max < - Math.PI ) max += twoPI; else if ( max > Math.PI ) max -= twoPI;
+
+                               if ( min <= max ) {
+
+                                       spherical.theta = Math.max( min, Math.min( max, spherical.theta ) );
+
+                               } else {
+
+                                       spherical.theta = ( spherical.theta > ( min + max ) / 2 ) ?
+                                               Math.max( min, spherical.theta ) :
+                                               Math.min( max, spherical.theta );
+
+                               }
+
+                       }
+
+                       // restrict phi to be between desired limits
+                       spherical.phi = Math.max( scope.minPolarAngle, Math.min( scope.maxPolarAngle, spherical.phi ) );
+
+                       spherical.makeSafe();
+
+
+                       spherical.radius *= scale;
+
+                       // restrict radius to be between desired limits
+                       spherical.radius = Math.max( scope.minDistance, Math.min( scope.maxDistance, spherical.radius ) );
+
+                       // move target to panned location
+
+                       if ( scope.enableDamping === true ) {
+
+                               scope.target.addScaledVector( panOffset, scope.dampingFactor );
+
+                       } else {
+
+                               scope.target.add( panOffset );
+
+                       }
+
+                       offset.setFromSpherical( spherical );
+
+                       // rotate offset back to "camera-up-vector-is-up" space
+                       offset.applyQuaternion( quatInverse );
+
+                       position.copy( scope.target ).add( offset );
+
+                       scope.object.lookAt( scope.target );
+
+                       if ( scope.enableDamping === true ) {
+
+                               sphericalDelta.theta *= ( 1 - scope.dampingFactor );
+                               sphericalDelta.phi *= ( 1 - scope.dampingFactor );
+
+                               panOffset.multiplyScalar( 1 - scope.dampingFactor );
+
+                       } else {
+
+                               sphericalDelta.set( 0, 0, 0 );
+
+                               panOffset.set( 0, 0, 0 );
+
+                       }
+
+                       scale = 1;
+
+                       // update condition is:
+                       // min(camera displacement, camera rotation in radians)^2 > EPS
+                       // using small-angle approximation cos(x/2) = 1 - x^2 / 8
+
+                       if ( zoomChanged ||
+                               lastPosition.distanceToSquared( scope.object.position ) > EPS ||
+                               8 * ( 1 - lastQuaternion.dot( scope.object.quaternion ) ) > EPS ) {
+
+                               scope.dispatchEvent( changeEvent );
+
+                               lastPosition.copy( scope.object.position );
+                               lastQuaternion.copy( scope.object.quaternion );
+                               zoomChanged = false;
+
+                               return true;
+
+                       }
+
+                       return false;
+
+               };
+
+       }();
+
+       this.dispose = function () {
+
+               scope.domElement.removeEventListener( 'contextmenu', onContextMenu );
+
+               scope.domElement.removeEventListener( 'pointerdown', onPointerDown );
+               scope.domElement.removeEventListener( 'wheel', onMouseWheel );
+
+               scope.domElement.removeEventListener( 'touchstart', onTouchStart );
+               scope.domElement.removeEventListener( 'touchend', onTouchEnd );
+               scope.domElement.removeEventListener( 'touchmove', onTouchMove );
+
+               scope.domElement.ownerDocument.removeEventListener( 'pointermove', onPointerMove );
+               scope.domElement.ownerDocument.removeEventListener( 'pointerup', onPointerUp );
+
+
+               if ( scope._domElementKeyEvents !== null ) {
+
+                       scope._domElementKeyEvents.removeEventListener( 'keydown', onKeyDown );
+
+               }
+
+               //scope.dispatchEvent( { type: 'dispose' } ); // should this be added here?
+
+       };
+
+       //
+       // internals
+       //
+
+       var scope = this;
+
+       var changeEvent = { type: 'change' };
+       var startEvent = { type: 'start' };
+       var endEvent = { type: 'end' };
+
+       var STATE = {
+               NONE: - 1,
+               ROTATE: 0,
+               DOLLY: 1,
+               PAN: 2,
+               TOUCH_ROTATE: 3,
+               TOUCH_PAN: 4,
+               TOUCH_DOLLY_PAN: 5,
+               TOUCH_DOLLY_ROTATE: 6
+       };
+
+       var state = STATE.NONE;
+
+       var EPS = 0.000001;
+
+       // current position in spherical coordinates
+       var spherical = new THREE.Spherical();
+       var sphericalDelta = new THREE.Spherical();
+
+       var scale = 1;
+       var panOffset = new THREE.Vector3();
+       var zoomChanged = false;
+
+       var rotateStart = new THREE.Vector2();
+       var rotateEnd = new THREE.Vector2();
+       var rotateDelta = new THREE.Vector2();
+
+       var panStart = new THREE.Vector2();
+       var panEnd = new THREE.Vector2();
+       var panDelta = new THREE.Vector2();
+
+       var dollyStart = new THREE.Vector2();
+       var dollyEnd = new THREE.Vector2();
+       var dollyDelta = new THREE.Vector2();
+
+       function getAutoRotationAngle() {
+
+               return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed;
+
+       }
+
+       function getZoomScale() {
+
+               return Math.pow( 0.95, scope.zoomSpeed );
+
+       }
+
+       function rotateLeft( angle ) {
+
+               sphericalDelta.theta -= angle;
+
+       }
+
+       function rotateUp( angle ) {
+
+               sphericalDelta.phi -= angle;
+
+       }
+
+       var panLeft = function () {
+
+               var v = new THREE.Vector3();
+
+               return function panLeft( distance, objectMatrix ) {
+
+                       v.setFromMatrixColumn( objectMatrix, 0 ); // get X column of objectMatrix
+                       v.multiplyScalar( - distance );
+
+                       panOffset.add( v );
+
+               };
+
+       }();
+
+       var panUp = function () {
+
+               var v = new THREE.Vector3();
+
+               return function panUp( distance, objectMatrix ) {
+
+                       if ( scope.screenSpacePanning === true ) {
+
+                               v.setFromMatrixColumn( objectMatrix, 1 );
+
+                       } else {
+
+                               v.setFromMatrixColumn( objectMatrix, 0 );
+                               v.crossVectors( scope.object.up, v );
+
+                       }
+
+                       v.multiplyScalar( distance );
+
+                       panOffset.add( v );
+
+               };
+
+       }();
+
+       // deltaX and deltaY are in pixels; right and down are positive
+       var pan = function () {
+
+               var offset = new THREE.Vector3();
+
+               return function pan( deltaX, deltaY ) {
+
+                       var element = scope.domElement;
+
+                       if ( scope.object.isPerspectiveCamera ) {
+
+                               // perspective
+                               var position = scope.object.position;
+                               offset.copy( position ).sub( scope.target );
+                               var targetDistance = offset.length();
+
+                               // half of the fov is center to top of screen
+                               targetDistance *= Math.tan( ( scope.object.fov / 2 ) * Math.PI / 180.0 );
+
+                               // we use only clientHeight here so aspect ratio does not distort speed
+                               panLeft( 2 * deltaX * targetDistance / element.clientHeight, scope.object.matrix );
+                               panUp( 2 * deltaY * targetDistance / element.clientHeight, scope.object.matrix );
+
+                       } else if ( scope.object.isOrthographicCamera ) {
+
+                               // orthographic
+                               panLeft( deltaX * ( scope.object.right - scope.object.left ) / scope.object.zoom / element.clientWidth, scope.object.matrix );
+                               panUp( deltaY * ( scope.object.top - scope.object.bottom ) / scope.object.zoom / element.clientHeight, scope.object.matrix );
+
+                       } else {
+
+                               // camera neither orthographic nor perspective
+                               console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.' );
+                               scope.enablePan = false;
+
+                       }
+
+               };
+
+       }();
+
+       function dollyOut( dollyScale ) {
+
+               if ( scope.object.isPerspectiveCamera ) {
+
+                       scale /= dollyScale;
+
+               } else if ( scope.object.isOrthographicCamera ) {
+
+                       scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom * dollyScale ) );
+                       scope.object.updateProjectionMatrix();
+                       zoomChanged = true;
+
+               } else {
+
+                       console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' );
+                       scope.enableZoom = false;
+
+               }
+
+       }
+
+       function dollyIn( dollyScale ) {
+
+               if ( scope.object.isPerspectiveCamera ) {
+
+                       scale *= dollyScale;
+
+               } else if ( scope.object.isOrthographicCamera ) {
+
+                       scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom / dollyScale ) );
+                       scope.object.updateProjectionMatrix();
+                       zoomChanged = true;
+
+               } else {
+
+                       console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' );
+                       scope.enableZoom = false;
+
+               }
+
+       }
+
+       //
+       // event callbacks - update the object state
+       //
+
+       function handleMouseDownRotate( event ) {
+
+               rotateStart.set( event.clientX, event.clientY );
+
+       }
+
+       function handleMouseDownDolly( event ) {
+
+               dollyStart.set( event.clientX, event.clientY );
+
+       }
+
+       function handleMouseDownPan( event ) {
+
+               panStart.set( event.clientX, event.clientY );
+
+       }
+
+       function handleMouseMoveRotate( event ) {
+
+               rotateEnd.set( event.clientX, event.clientY );
+
+               rotateDelta.subVectors( rotateEnd, rotateStart ).multiplyScalar( scope.rotateSpeed );
+
+               var element = scope.domElement;
+
+               rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientHeight ); // yes, height
+
+               rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight );
+
+               rotateStart.copy( rotateEnd );
+
+               scope.update();
+
+       }
+
+       function handleMouseMoveDolly( event ) {
+
+               dollyEnd.set( event.clientX, event.clientY );
+
+               dollyDelta.subVectors( dollyEnd, dollyStart );
+
+               if ( dollyDelta.y > 0 ) {
+
+                       dollyOut( getZoomScale() );
+
+               } else if ( dollyDelta.y < 0 ) {
+
+                       dollyIn( getZoomScale() );
+
+               }
+
+               dollyStart.copy( dollyEnd );
+
+               scope.update();
+
+       }
+
+       function handleMouseMovePan( event ) {
+
+               panEnd.set( event.clientX, event.clientY );
+
+               panDelta.subVectors( panEnd, panStart ).multiplyScalar( scope.panSpeed );
+
+               pan( panDelta.x, panDelta.y );
+
+               panStart.copy( panEnd );
+
+               scope.update();
+
+       }
+
+       function handleMouseUp( /*event*/ ) {
+
+               // no-op
+
+       }
+
+       function handleMouseWheel( event ) {
+
+               if ( event.deltaY < 0 ) {
+
+                       dollyIn( getZoomScale() );
+
+               } else if ( event.deltaY > 0 ) {
+
+                       dollyOut( getZoomScale() );
+
+               }
+
+               scope.update();
+
+       }
+
+       function handleKeyDown( event ) {
+
+               var needsUpdate = false;
+
+               switch ( event.keyCode ) {
+
+                       case scope.keys.UP:
+                               pan( 0, scope.keyPanSpeed );
+                               needsUpdate = true;
+                               break;
+
+                       case scope.keys.BOTTOM:
+                               pan( 0, - scope.keyPanSpeed );
+                               needsUpdate = true;
+                               break;
+
+                       case scope.keys.LEFT:
+                               pan( scope.keyPanSpeed, 0 );
+                               needsUpdate = true;
+                               break;
+
+                       case scope.keys.RIGHT:
+                               pan( - scope.keyPanSpeed, 0 );
+                               needsUpdate = true;
+                               break;
+
+               }
+
+               if ( needsUpdate ) {
+
+                       // prevent the browser from scrolling on cursor keys
+                       event.preventDefault();
+
+                       scope.update();
+
+               }
+
+
+       }
+
+       function handleTouchStartRotate( event ) {
+
+               if ( event.touches.length == 1 ) {
+
+                       rotateStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
+
+               } else {
+
+                       var x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX );
+                       var y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY );
+
+                       rotateStart.set( x, y );
+
+               }
+
+       }
+
+       function handleTouchStartPan( event ) {
+
+               if ( event.touches.length == 1 ) {
+
+                       panStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
+
+               } else {
+
+                       var x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX );
+                       var y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY );
+
+                       panStart.set( x, y );
+
+               }
+
+       }
+
+       function handleTouchStartDolly( event ) {
+
+               var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
+               var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
+
+               var distance = Math.sqrt( dx * dx + dy * dy );
+
+               dollyStart.set( 0, distance );
+
+       }
+
+       function handleTouchStartDollyPan( event ) {
+
+               if ( scope.enableZoom ) handleTouchStartDolly( event );
+
+               if ( scope.enablePan ) handleTouchStartPan( event );
+
+       }
+
+       function handleTouchStartDollyRotate( event ) {
+
+               if ( scope.enableZoom ) handleTouchStartDolly( event );
+
+               if ( scope.enableRotate ) handleTouchStartRotate( event );
+
+       }
+
+       function handleTouchMoveRotate( event ) {
+
+               if ( event.touches.length == 1 ) {
+
+                       rotateEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
+
+               } else {
+
+                       var x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX );
+                       var y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY );
+
+                       rotateEnd.set( x, y );
+
+               }
+
+               rotateDelta.subVectors( rotateEnd, rotateStart ).multiplyScalar( scope.rotateSpeed );
+
+               var element = scope.domElement;
+
+               rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientHeight ); // yes, height
+
+               rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight );
+
+               rotateStart.copy( rotateEnd );
+
+       }
+
+       function handleTouchMovePan( event ) {
+
+               if ( event.touches.length == 1 ) {
+
+                       panEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
+
+               } else {
+
+                       var x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX );
+                       var y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY );
+
+                       panEnd.set( x, y );
+
+               }
+
+               panDelta.subVectors( panEnd, panStart ).multiplyScalar( scope.panSpeed );
+
+               pan( panDelta.x, panDelta.y );
+
+               panStart.copy( panEnd );
+
+       }
+
+       function handleTouchMoveDolly( event ) {
+
+               var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
+               var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
+
+               var distance = Math.sqrt( dx * dx + dy * dy );
+
+               dollyEnd.set( 0, distance );
+
+               dollyDelta.set( 0, Math.pow( dollyEnd.y / dollyStart.y, scope.zoomSpeed ) );
+
+               dollyOut( dollyDelta.y );
+
+               dollyStart.copy( dollyEnd );
+
+       }
+
+       function handleTouchMoveDollyPan( event ) {
+
+               if ( scope.enableZoom ) handleTouchMoveDolly( event );
+
+               if ( scope.enablePan ) handleTouchMovePan( event );
+
+       }
+
+       function handleTouchMoveDollyRotate( event ) {
+
+               if ( scope.enableZoom ) handleTouchMoveDolly( event );
+
+               if ( scope.enableRotate ) handleTouchMoveRotate( event );
+
+       }
+
+       function handleTouchEnd( /*event*/ ) {
+
+               // no-op
+
+       }
+
+       //
+       // event handlers - FSM: listen for events and reset state
+       //
+
+       function onPointerDown( event ) {
+
+               if ( scope.enabled === false ) return;
+
+               switch ( event.pointerType ) {
+
+                       case 'mouse':
+                       case 'pen':
+                               onMouseDown( event );
+                               break;
+
+                       // TODO touch
+
+               }
+
+       }
+
+       function onPointerMove( event ) {
+
+               if ( scope.enabled === false ) return;
+
+               switch ( event.pointerType ) {
+
+                       case 'mouse':
+                       case 'pen':
+                               onMouseMove( event );
+                               break;
+
+                       // TODO touch
+
+               }
+
+       }
+
+       function onPointerUp( event ) {
+
+               switch ( event.pointerType ) {
+
+                       case 'mouse':
+                       case 'pen':
+                               onMouseUp( event );
+                               break;
+
+                       // TODO touch
+
+               }
+
+       }
+
+       function onMouseDown( event ) {
+
+               // Prevent the browser from scrolling.
+               event.preventDefault();
+
+               // Manually set the focus since calling preventDefault above
+               // prevents the browser from setting it automatically.
+
+               scope.domElement.focus ? scope.domElement.focus() : window.focus();
+
+               var mouseAction;
+
+               switch ( event.button ) {
+
+                       case 0:
+
+                               mouseAction = scope.mouseButtons.LEFT;
+                               break;
+
+                       case 1:
+
+                               mouseAction = scope.mouseButtons.MIDDLE;
+                               break;
+
+                       case 2:
+
+                               mouseAction = scope.mouseButtons.RIGHT;
+                               break;
+
+                       default:
+
+                               mouseAction = - 1;
+
+               }
+
+               switch ( mouseAction ) {
+
+                       case THREE.MOUSE.DOLLY:
+
+                               if ( scope.enableZoom === false ) return;
+
+                               handleMouseDownDolly( event );
+
+                               state = STATE.DOLLY;
+
+                               break;
+
+                       case THREE.MOUSE.ROTATE:
+
+                               if ( event.ctrlKey || event.metaKey || event.shiftKey ) {
+
+                                       if ( scope.enablePan === false ) return;
+
+                                       handleMouseDownPan( event );
+
+                                       state = STATE.PAN;
+
+                               } else {
+
+                                       if ( scope.enableRotate === false ) return;
+
+                                       handleMouseDownRotate( event );
+
+                                       state = STATE.ROTATE;
+
+                               }
+
+                               break;
+
+                       case THREE.MOUSE.PAN:
+
+                               if ( event.ctrlKey || event.metaKey || event.shiftKey ) {
+
+                                       if ( scope.enableRotate === false ) return;
+
+                                       handleMouseDownRotate( event );
+
+                                       state = STATE.ROTATE;
+
+                               } else {
+
+                                       if ( scope.enablePan === false ) return;
+
+                                       handleMouseDownPan( event );
+
+                                       state = STATE.PAN;
+
+                               }
+
+                               break;
+
+                       default:
+
+                               state = STATE.NONE;
+
+               }
+
+               if ( state !== STATE.NONE ) {
+
+                       scope.domElement.ownerDocument.addEventListener( 'pointermove', onPointerMove );
+                       scope.domElement.ownerDocument.addEventListener( 'pointerup', onPointerUp );
+
+                       scope.dispatchEvent( startEvent );
+
+               }
+
+       }
+
+       function onMouseMove( event ) {
+
+               if ( scope.enabled === false ) return;
+
+               event.preventDefault();
+
+               switch ( state ) {
+
+                       case STATE.ROTATE:
+
+                               if ( scope.enableRotate === false ) return;
+
+                               handleMouseMoveRotate( event );
+
+                               break;
+
+                       case STATE.DOLLY:
+
+                               if ( scope.enableZoom === false ) return;
+
+                               handleMouseMoveDolly( event );
+
+                               break;
+
+                       case STATE.PAN:
+
+                               if ( scope.enablePan === false ) return;
+
+                               handleMouseMovePan( event );
+
+                               break;
+
+               }
+
+       }
+
+       function onMouseUp( event ) {
+
+               scope.domElement.ownerDocument.removeEventListener( 'pointermove', onPointerMove );
+               scope.domElement.ownerDocument.removeEventListener( 'pointerup', onPointerUp );
+
+               if ( scope.enabled === false ) return;
+
+               handleMouseUp( event );
+
+               scope.dispatchEvent( endEvent );
+
+               state = STATE.NONE;
+
+       }
+
+       function onMouseWheel( event ) {
+
+               if ( scope.enabled === false || scope.enableZoom === false || ( state !== STATE.NONE && state !== STATE.ROTATE ) ) return;
+
+               event.preventDefault();
+               event.stopPropagation();
+
+               scope.dispatchEvent( startEvent );
+
+               handleMouseWheel( event );
+
+               scope.dispatchEvent( endEvent );
+
+       }
+
+       function onKeyDown( event ) {
+
+               if ( scope.enabled === false || scope.enablePan === false ) return;
+
+               handleKeyDown( event );
+
+       }
+
+       function onTouchStart( event ) {
+
+               if ( scope.enabled === false ) return;
+
+               event.preventDefault(); // prevent scrolling
+
+               switch ( event.touches.length ) {
+
+                       case 1:
+
+                               switch ( scope.touches.ONE ) {
+
+                                       case THREE.TOUCH.ROTATE:
+
+                                               if ( scope.enableRotate === false ) return;
+
+                                               handleTouchStartRotate( event );
+
+                                               state = STATE.TOUCH_ROTATE;
+
+                                               break;
+
+                                       case THREE.TOUCH.PAN:
+
+                                               if ( scope.enablePan === false ) return;
+
+                                               handleTouchStartPan( event );
+
+                                               state = STATE.TOUCH_PAN;
+
+                                               break;
+
+                                       default:
+
+                                               state = STATE.NONE;
+
+                               }
+
+                               break;
+
+                       case 2:
+
+                               switch ( scope.touches.TWO ) {
+
+                                       case THREE.TOUCH.DOLLY_PAN:
+
+                                               if ( scope.enableZoom === false && scope.enablePan === false ) return;
+
+                                               handleTouchStartDollyPan( event );
+
+                                               state = STATE.TOUCH_DOLLY_PAN;
+
+                                               break;
+
+                                       case THREE.TOUCH.DOLLY_ROTATE:
+
+                                               if ( scope.enableZoom === false && scope.enableRotate === false ) return;
+
+                                               handleTouchStartDollyRotate( event );
+
+                                               state = STATE.TOUCH_DOLLY_ROTATE;
+
+                                               break;
+
+                                       default:
+
+                                               state = STATE.NONE;
+
+                               }
+
+                               break;
+
+                       default:
+
+                               state = STATE.NONE;
+
+               }
+
+               if ( state !== STATE.NONE ) {
+
+                       scope.dispatchEvent( startEvent );
+
+               }
+
+       }
+
+       function onTouchMove( event ) {
+
+               if ( scope.enabled === false ) return;
+
+               event.preventDefault(); // prevent scrolling
+               event.stopPropagation();
+
+               switch ( state ) {
+
+                       case STATE.TOUCH_ROTATE:
+
+                               if ( scope.enableRotate === false ) return;
+
+                               handleTouchMoveRotate( event );
+
+                               scope.update();
+
+                               break;
+
+                       case STATE.TOUCH_PAN:
+
+                               if ( scope.enablePan === false ) return;
+
+                               handleTouchMovePan( event );
+
+                               scope.update();
+
+                               break;
+
+                       case STATE.TOUCH_DOLLY_PAN:
+
+                               if ( scope.enableZoom === false && scope.enablePan === false ) return;
+
+                               handleTouchMoveDollyPan( event );
+
+                               scope.update();
+
+                               break;
+
+                       case STATE.TOUCH_DOLLY_ROTATE:
+
+                               if ( scope.enableZoom === false && scope.enableRotate === false ) return;
+
+                               handleTouchMoveDollyRotate( event );
+
+                               scope.update();
+
+                               break;
+
+                       default:
+
+                               state = STATE.NONE;
+
+               }
+
+       }
+
+       function onTouchEnd( event ) {
+
+               if ( scope.enabled === false ) return;
+
+               handleTouchEnd( event );
+
+               scope.dispatchEvent( endEvent );
+
+               state = STATE.NONE;
+
+       }
+
+       function onContextMenu( event ) {
+
+               if ( scope.enabled === false ) return;
+
+               event.preventDefault();
+
+       }
+
+       //
+
+       scope.domElement.addEventListener( 'contextmenu', onContextMenu );
+
+       scope.domElement.addEventListener( 'pointerdown', onPointerDown );
+       scope.domElement.addEventListener( 'wheel', onMouseWheel );
+
+       scope.domElement.addEventListener( 'touchstart', onTouchStart );
+       scope.domElement.addEventListener( 'touchend', onTouchEnd );
+       scope.domElement.addEventListener( 'touchmove', onTouchMove );
+
+       // force an update at start
+
+       this.update();
+
+};
+
+THREE.OrbitControls.prototype = Object.create( THREE.EventDispatcher.prototype );
+THREE.OrbitControls.prototype.constructor = THREE.OrbitControls;
+
+
+// This set of controls performs orbiting, dollying (zooming), and panning.
+// Unlike TrackballControls, it maintains the "up" direction object.up (+Y by default).
+// This is very similar to OrbitControls, another set of touch behavior
+//
+//    Orbit - right mouse, or left mouse + ctrl/meta/shiftKey / touch: two-finger rotate
+//    Zoom - middle mouse, or mousewheel / touch: two-finger spread or squish
+//    Pan - left mouse, or arrow keys / touch: one-finger move
+
+THREE.MapControls = function ( object, domElement ) {
+
+       THREE.OrbitControls.call( this, object, domElement );
+
+       this.screenSpacePanning = false; // pan orthogonal to world-space direction camera.up
+
+       this.mouseButtons.LEFT = THREE.MOUSE.PAN;
+       this.mouseButtons.RIGHT = THREE.MOUSE.ROTATE;
+
+       this.touches.ONE = THREE.TOUCH.PAN;
+       this.touches.TWO = THREE.TOUCH.DOLLY_ROTATE;
+
+};
+
+THREE.MapControls.prototype = Object.create( THREE.EventDispatcher.prototype );
+THREE.MapControls.prototype.constructor = THREE.MapControls;
diff --git a/Scripts/_cloth.js b/Scripts/_cloth.js
new file mode 100644 (file)
index 0000000..546f7d3
--- /dev/null
@@ -0,0 +1,621 @@
+/**\r
+ *  Convenience Function for calculating the distance between two vectors\r
+ *  because THREE JS Vector functions mutate variables\r
+ * @param {Vector3} a - Vector A\r
+ * @param {Vector3} b - Vector B\r
+ */\r
+function vectorLength(a, b) {\r
+  let v1 = new THREE.Vector3();\r
+  v1.copy(a);\r
+  let v2 = new THREE.Vector3();\r
+  v2.copy(b);\r
+\r
+  return v1.sub(v2).length();\r
+}\r
+\r
+/**\r
+ * Class representing a quad face\r
+ * Each face consists of two triangular mesh faces\r
+ * containts four indices for determining vertices\r
+ * and six springs, one between each of the vertices\r
+ */\r
+export class Face {\r
+  a;\r
+  b;\r
+  c;\r
+  d;\r
+\r
+  springs = [];\r
+\r
+  constructor(a, b, c, d) {\r
+    this.a = a;\r
+    this.b = b;\r
+    this.c = c;\r
+    this.d = d;\r
+  }\r
+}\r
+\r
+/**\r
+ * Class representing a single spring\r
+ * has a current and resting length\r
+ * and indices to the two connected vertices\r
+ */\r
+export class Spring {\r
+  restLength;\r
+  currentLength;\r
+  index1;\r
+  index2;\r
+\r
+\r
+  /**\r
+   * set vertex indices\r
+   * and calculate inital length based on the\r
+   * vertex positions\r
+   * @param {Array<Vector3>} vertices \r
+   * @param {number} index1 \r
+   * @param {number} index2 \r
+   */\r
+  constructor(vertices, index1, index2) {\r
+    this.index1 = index1;\r
+    this.index2 = index2;\r
+\r
+    let length = vectorLength(vertices[index1], vertices[index2]);\r
+    this.restLength = length;\r
+    this.currentLength = length;\r
+  }\r
+\r
+  getDirection(vertices) {\r
+    let direction = new THREE.Vector3();\r
+    direction.copy(vertices[this.index1]);\r
+\r
+    direction.sub(vertices[this.index2]);\r
+    direction.divideScalar(vectorLength(vertices[this.index1], vertices[this.index2]));\r
+\r
+    return direction;\r
+  }\r
+\r
+  update(vertices) {\r
+    let length = vectorLength(vertices[this.index1], vertices[this.index2]);\r
+    this.currentLength = length;\r
+  }\r
+}\r
+\r
+/**\r
+ * Class representing a single piece of cloth\r
+ * contains THREE JS geometry,\r
+ * logically represented by an array of adjacent faces\r
+ * and vertex weights which are accessed by the same\r
+ * indices as the vertices in the Mesh\r
+ */\r
+export class Cloth {\r
+  VertexWeight = 1;\r
+\r
+  geometry = new THREE.Geometry();\r
+\r
+  faces = [];\r
+\r
+  vertexWeights = [];\r
+\r
+  vertexRigidness = [];\r
+\r
+  fixedPoints = [];\r
+\r
+  externalForces = [];\r
+  windForce = 50;\r
+\r
+  windFactor = new THREE.Vector3(0, 0, 0);\r
+\r
+  /**\r
+   * creates a rectangular piece of cloth\r
+   * takes the size of the cloth\r
+   * and the number of vertices it should be composed of\r
+   * @param {number} width - width of the cloth\r
+   * @param {number} height - height of the cloth\r
+   * @param {number} numPointsWidth - number of vertices in horizontal direction\r
+   * @param {number} numPointsHeight  - number of vertices in vertical direction\r
+   */\r
+  createBasic(width, height, numPointsWidth, numPointsHeight) {\r
+    /** resulting vertices and faces */\r
+    let vertices = [];\r
+    let faces = [];\r
+\r
+    this.width = width;\r
+    this.height = height;\r
+    this.numPointsWidth = numPointsWidth;\r
+    this.numPointsHeight = numPointsHeight;\r
+\r
+    /**\r
+     * distance between two vertices horizontally/vertically\r
+     * divide by the number of points minus one\r
+     * because there are (n - 1) lines between n vertices\r
+     */\r
+    let stepWidth = width / (numPointsWidth - 1);\r
+    let stepHeight = height / (numPointsHeight - 1);\r
+\r
+    /**\r
+     * iterate over the number of vertices in x/y axis\r
+     * and add a new Vector3 to "vertices"\r
+     */\r
+    for (let y = 0; y < numPointsHeight; y++) {\r
+      for (let x = 0; x < numPointsWidth; x++) {\r
+        vertices.push(\r
+          new THREE.Vector3((x - ((numPointsWidth-1)/2)) * stepWidth, height - (y + ((numPointsHeight-1)/2)) * stepHeight, 0)\r
+        );\r
+      }\r
+    }\r
+\r
+    /**\r
+     * helper function to calculate index of vertex\r
+     * in "vertices" array based on its x and y positions\r
+     * in the mesh\r
+     * @param {number} x - x index of vertex\r
+     * @param {number} y - y index of vertex\r
+     */\r
+    function getVertexIndex(x, y) {\r
+      return y * numPointsWidth + x;\r
+    }\r
+\r
+    /**\r
+     * generate faces based on 4 vertices\r
+     * and 6 springs each\r
+     */\r
+    for (let y = 0; y < numPointsHeight - 1; y++) {\r
+      for (let x = 0; x < numPointsWidth - 1; x++) {\r
+        let newFace = new Face(\r
+          getVertexIndex(x, y),\r
+          getVertexIndex(x, y + 1),\r
+          getVertexIndex(x + 1, y),\r
+          getVertexIndex(x + 1, y + 1),\r
+        );\r
+\r
+        newFace.springs.push(new Spring(vertices, getVertexIndex(x, y), getVertexIndex(x + 1, y)));         // oben\r
+        newFace.springs.push(new Spring(vertices, getVertexIndex(x, y), getVertexIndex(x, y + 1)));         // links\r
+        newFace.springs.push(new Spring(vertices, getVertexIndex(x, y), getVertexIndex(x + 1, y + 1)));     // oben links  -> unten rechts diagonal\r
+        newFace.springs.push(new Spring(vertices, getVertexIndex(x + 1, y), getVertexIndex(x, y + 1)));     // oben rechts -> unten links diagonal\r
+        newFace.springs.push(new Spring(vertices, getVertexIndex(x + 1, y), getVertexIndex(x + 1, y + 1))); // rechts\r
+        newFace.springs.push(new Spring(vertices, getVertexIndex(x, y + 1), getVertexIndex(x + 1, y + 1))); // unten\r
+\r
+        faces.push(newFace);\r
+      }\r
+    }\r
+\r
+    /**\r
+     * call createExplicit\r
+     * with generated vertices and faces\r
+     */\r
+    this.createExplicit(vertices, faces);\r
+\r
+    /**\r
+     * hand cloth from left and right upper corners\r
+     */\r
+    this.fixedPoints.push(getVertexIndex(0, 0));\r
+    this.fixedPoints.push(getVertexIndex(0, 19));\r
+  }\r
+\r
+  /**\r
+   * Generate THREE JS Geometry\r
+   * (list of vertices and list of indices representing triangles)\r
+   * and calculate the weight of each face and split it between\r
+   * surrounding vertices\r
+   * @param {Array<Vector3>} vertices \r
+   * @param {Array<Face>} faces \r
+   */\r
+  createExplicit(vertices, faces) {\r
+\r
+    /**\r
+     * Copy vertices and initialize vertex weights to 0\r
+     */\r
+    for (let i in vertices) {\r
+      this.geometry.vertices.push(vertices[i].clone());\r
+      this.previousPositions.push(vertices[i].clone());\r
+      // this.geometry.vertices.push(vertices[i]);\r
+      // this.previousPositions.push(vertices[i]);\r
+      this.vertexWeights.push(0);\r
+      this.vertexRigidness.push(false);\r
+      this.externalForces.push(new THREE.Vector3(0,0,0));\r
+    }\r
+    /**\r
+     * copy faces,\r
+     * generate two triangles per face,\r
+     * calculate weight of face as its area\r
+     * and split between the 4 vertices\r
+     */\r
+    for (let i in faces) {\r
+      let face = faces[i];\r
+\r
+      /** copy faces to class member */\r
+      this.faces.push(face);\r
+\r
+      /** generate triangles */\r
+      this.geometry.faces.push(new THREE.Face3(\r
+        face.a, face.b, face.c\r
+      ));\r
+      this.geometry.faces.push(new THREE.Face3(\r
+        face.c, face.b, face.d\r
+      ));\r
+\r
+      /**\r
+       * calculate area of face as combined area of\r
+       * its two composing triangles\r
+       */\r
+      let xLength = vectorLength(this.geometry.vertices[face.b], this.geometry.vertices[face.a]);\r
+      let yLength = vectorLength(this.geometry.vertices[face.c], this.geometry.vertices[face.a]);\r
+      let weight = xLength * yLength / 2;\r
+\r
+      xLength = vectorLength(this.geometry.vertices[face.b], this.geometry.vertices[face.d]);\r
+      yLength = vectorLength(this.geometry.vertices[face.c], this.geometry.vertices[face.d]);\r
+      weight += xLength * yLength / 2;\r
+\r
+      weight *= 10;\r
+\r
+      /**\r
+       * split weight equally between four surrounding vertices\r
+       */\r
+      this.vertexWeights[face.a] += weight / 4;\r
+      this.vertexWeights[face.b] += weight / 4;\r
+      this.vertexWeights[face.c] += weight / 4;\r
+      this.vertexWeights[face.d] += weight / 4;\r
+    }\r
+\r
+    /**\r
+     * let THREE JS compute bounding sphere around generated mesh\r
+     * needed for View Frustum Culling internally\r
+     */\r
+    this.geometry.computeBoundingSphere();\r
+    this.geometry.computeFaceNormals();\r
+    this.geometry.computeVertexNormals();\r
+  }\r
+\r
+  /**\r
+   * generate a debug mesh for visualizing\r
+   * vertices and springs of the cloth\r
+   * and add it to scene for rendering\r
+   * @param {Scene} scene - Scene to add Debug Mesh to\r
+   */\r
+  createDebugMesh(scene) {\r
+    /**\r
+     * helper function to generate a single line\r
+     * between two Vertices with a given color\r
+     * @param {Vector3} from \r
+     * @param {Vector3} to \r
+     * @param {number} color \r
+     */\r
+    function addLine(from, to, color) {\r
+      let geometry = new THREE.Geometry();\r
+      geometry.vertices.push(from);\r
+      geometry.vertices.push(to);\r
+      let material = new THREE.LineBasicMaterial({ color: color, linewidth: 10 });\r
+      let line = new THREE.Line(geometry, material);\r
+      line.renderOrder = 1;\r
+      scene.add(line);\r
+    }\r
+    /**\r
+     * helper function to generate a small sphere\r
+     * at a given Vertex Position with color\r
+     * @param {Vector3} point \r
+     * @param {number} color \r
+     */\r
+    function addPoint(point, color) {\r
+      const geometry = new THREE.SphereGeometry(0.05, 32, 32);\r
+      const material = new THREE.MeshBasicMaterial({ color: color });\r
+      const sphere = new THREE.Mesh(geometry, material);\r
+      sphere.position.set(point.x, point.y, point.z);\r
+      scene.add(sphere);\r
+    }\r
+\r
+    let lineColor = 0x000000;\r
+    let pointColor = 0xff00000;\r
+\r
+    /**\r
+     * generate one line for each of the 6 springs\r
+     * and one point for each of the 4 vertices\r
+     * for all of the faces\r
+     */\r
+    for (let i in this.faces) {\r
+      let face = this.faces[i];\r
+      addLine(this.geometry.vertices[face.a], this.geometry.vertices[face.b], lineColor);\r
+      addLine(this.geometry.vertices[face.a], this.geometry.vertices[face.c], lineColor);\r
+      addLine(this.geometry.vertices[face.a], this.geometry.vertices[face.d], lineColor);\r
+      addLine(this.geometry.vertices[face.b], this.geometry.vertices[face.c], lineColor);\r
+      addLine(this.geometry.vertices[face.b], this.geometry.vertices[face.d], lineColor);\r
+      addLine(this.geometry.vertices[face.c], this.geometry.vertices[face.d], lineColor);\r
+\r
+      addPoint(this.geometry.vertices[face.a], pointColor);\r
+      addPoint(this.geometry.vertices[face.b], pointColor);\r
+      addPoint(this.geometry.vertices[face.c], pointColor);\r
+      addPoint(this.geometry.vertices[face.d], pointColor);\r
+    }\r
+  }\r
+\r
+  previousPositions = [];\r
+  time = 0;\r
+  /**\r
+   * \r
+   * @param {number} dt time in seconds since last frame\r
+   */\r
+  simulate(dt) {\r
+    for (let i in this.geometry.vertices) {\r
+      let acceleration = this.getAcceleration(i, dt);\r
+\r
+      //acceleration.clampLength(0, 10);\r
+\r
+      if (Math.abs(acceleration.length()) <= 10e-4) {\r
+        acceleration.set(0, 0, 0);\r
+      }\r
\r
+      let currentPosition = this.verlet(this.geometry.vertices[i].clone(), this.previousPositions[i].clone(), acceleration, dt);\r
+      //let currentPosition = this.euler(this.geometry.vertices[i], acceleration, dt);\r
+     \r
+      this.previousPositions[i].copy(this.geometry.vertices[i]);\r
+      this.geometry.vertices[i].copy(currentPosition);\r
+    }\r
+    \r
+    this.checkIntersect();\r
+    \r
+    this.time += dt;\r
+\r
+    for (let face of this.faces) {\r
+      for (let spring of face.springs) {\r
+        spring.update(this.geometry.vertices);\r
+      }\r
+    }\r
+\r
+    /**\r
+     * let THREE JS compute bounding sphere around generated mesh\r
+     * needed for View Frustum Culling internally\r
+     */\r
+\r
+    this.geometry.verticesNeedUpdate = true;\r
+    this.geometry.elementsNeedUpdate = true;\r
+    this.geometry.computeBoundingSphere();\r
+    this.geometry.computeFaceNormals();\r
+    this.geometry.computeVertexNormals();\r
+\r
+  }\r
+\r
+checkIntersect() {\r
+  let npw = this.numPointsWidth;\r
+  function getX(i, ) { return i % npw; }\r
+  function getY(i) { return Math.floor(i / npw); }\r
+  for (let i in this.geometry.vertices) {\r
+    for (let j in this.geometry.vertices) {\r
+      this.vertexRigidness[i] = false;\r
+      this.vertexRigidness[j] = false;\r
+      if (i == j || (Math.abs(getX(i) - getX(j)) == 1 && Math.abs(getY(i) - getY(j)) == 1))\r
+        continue;\r
+      let posI = this.geometry.vertices[i];\r
+      let posJ = this.geometry.vertices[j];\r
+      let dist = posI.distanceTo(posJ);\r
+      const collisionDistance = Math.min(this.width / this.numPointsWidth, this.height / this.numPointsHeight);\r
+      if (dist < collisionDistance) {\r
+        this.vertexRigidness[i] = true;\r
+        this.vertexRigidness[j] = true;\r
+        let diff = this.geometry.vertices[i].clone().sub(this.geometry.vertices[j]).normalize().multiplyScalar((collisionDistance - dist) * 1.001 / 2);\r
+        if (!(this.fixedPoints.includes(i) || this.fixedPoints.includes(j))) {\r
+          this.geometry.vertices[i].add(diff);\r
+          this.geometry.vertices[j].sub(diff);\r
+        }\r
+      }\r
+    }\r
+  }\r
+}\r
+\r
+/**\r
+ * Equation of motion for each vertex which represents the acceleration \r
+ * @param {number} vertexIndex The index of the current vertex whose acceleration should be calculated\r
+ *  @param {number} dt The time passed since last frame\r
+ */\r
+getAcceleration(vertexIndex, dt) {\r
+  if (this.fixedPoints.includes(parseInt(vertexIndex)) ||\r
+      this.vertexRigidness[vertexIndex]) {\r
+    return new THREE.Vector3(0, 0, 0);\r
+  }\r
+\r
+  let externalForce = this.externalForces[vertexIndex];\r
+  let vertex = this.geometry.vertices[vertexIndex];//.add(externalForce);\r
+\r
+  // Mass of vertex\r
+  let M = this.vertexWeights[vertexIndex];\r
+  // constant gravity\r
+  let g = new THREE.Vector3(0, -9.8, 0);\r
+  // stiffness\r
+  let k = 1000;\r
+\r
+  // Wind vector\r
+  let fWind = new THREE.Vector3(\r
+    this.windFactor.x * (Math.sin(vertex.x * vertex.y * this.time)+1),\r
+    this.windFactor.y * Math.cos(vertex.z * this.time),\r
+    this.windFactor.z * Math.sin(Math.cos(5 * vertex.x * vertex.y * vertex.z))\r
+  );\r
+  //console.log(fWind);\r
+\r
+  /**\r
+   * constant determined by the properties of the surrounding fluids (air)\r
+   * achievement of cloth effects through try out\r
+   * */\r
+  let a = 0.1;\r
+  \r
+  let velocity = new THREE.Vector3(\r
+    (this.previousPositions[vertexIndex].x - vertex.x) / dt,\r
+    (this.previousPositions[vertexIndex].y - vertex.y) / dt,\r
+    (this.previousPositions[vertexIndex].z - vertex.z) / dt\r
+  );\r
+\r
+  //console.log(velocity, vertex, this.previousPositions[vertexIndex]);\r
+\r
+  let fAirResistance = velocity.multiply(velocity).multiplyScalar(-a);\r
+  \r
+  let springSum = new THREE.Vector3(0, 0, 0);\r
+\r
+  // Get the bounding springs and add them to the needed springs\r
+  // TODO: optimize\r
+\r
+  const numPointsX = this.numPointsWidth;\r
+  const numPointsY = this.numPointsHeight;\r
+  const numFacesX = numPointsX - 1;\r
+  const numFacesY = numPointsY - 1;\r
+\r
+  function getFaceIndex(x, y) {\r
+    return y * numFacesX + x;\r
+  }\r
+\r
+  let indexX = vertexIndex % numPointsX;\r
+  let indexY = Math.floor(vertexIndex / numPointsX);\r
+\r
+  let springs = [];\r
+\r
+  // 0  oben\r
+  // 1  links\r
+  // 2  oben links  -> unten rechts diagonal\r
+  // 3  oben rechts -> unten links diagonal\r
+  // 4  rechts\r
+  // 5  unten\r
+\r
+  let ul = indexX > 0 && indexY < numPointsY - 1;\r
+  let ur = indexX < numPointsX - 1 && indexY < numPointsY - 1;\r
+  let ol = indexX > 0 && indexY > 0;\r
+  let or = indexX < numPointsX - 1 && indexY > 0;\r
+\r
+  if (ul) {\r
+    let faceUL = this.faces[getFaceIndex(indexX - 1, indexY)];\r
+    springs.push(faceUL.springs[3]);\r
+    if (!ol)\r
+      springs.push(faceUL.springs[0]);\r
+    springs.push(faceUL.springs[4]);\r
+  }\r
+  if (ur) {\r
+    let faceUR = this.faces[getFaceIndex(indexX, indexY)];\r
+    springs.push(faceUR.springs[2]);\r
+    if (!or)\r
+      springs.push(faceUR.springs[0]);\r
+    if (!ul)\r
+      springs.push(faceUR.springs[1]);\r
+  }\r
+  if (ol) {\r
+    let faceOL = this.faces[getFaceIndex(indexX - 1, indexY - 1)];\r
+    springs.push(faceOL.springs[2]);\r
+    springs.push(faceOL.springs[4]);\r
+    springs.push(faceOL.springs[5]);\r
+  }\r
+  if (or) {\r
+    let faceOR = this.faces[getFaceIndex(indexX , indexY - 1)];\r
+    springs.push(faceOR.springs[3]);\r
+    if (!ol)\r
+      springs.push(faceOR.springs[1]);\r
+    springs.push(faceOR.springs[5]);\r
+  }\r
+\r
+  for (let spring of springs) {\r
+    let springDirection = spring.getDirection(this.geometry.vertices);\r
+\r
+    if (spring.index1 == vertexIndex)\r
+      springDirection.multiplyScalar(-1);\r
+\r
+    springSum.add(springDirection.multiplyScalar(k * (spring.restLength - spring.currentLength)));\r
+  }\r
+  \r
+  let result = new THREE.Vector3(1, 1, 1);\r
+  result.multiplyScalar(M).multiply(g).add(fWind).add(externalForce).add(fAirResistance).sub(springSum);\r
+\r
+  document.getElementById("Output").innerText = "SpringSum: " + Math.floor(springSum.y);\r
+\r
+  let threshold = 1;\r
+  let forceReduktion = 0.8;\r
+  if(Math.abs(externalForce.z) > threshold){\r
+    externalForce.z *= forceReduktion;\r
+  } else {\r
+    externalForce.z = 0;\r
+  }\r
+\r
+  if(Math.abs(externalForce.y) > threshold){\r
+    externalForce.y *= forceReduktion;\r
+  } else {\r
+    externalForce.y = 0;\r
+  }\r
+\r
+  if(Math.abs(externalForce.x) > threshold){\r
+    externalForce.x *= forceReduktion;\r
+  } else {\r
+    externalForce.x = 0;\r
+  }\r
+    \r
+  \r
+\r
+  return result;\r
+}\r
+\r
+/**\r
+ * The Verlet algorithm as an integrator \r
+ * to get the next position of a vertex  \r
+ * @param {Vector3} currentPosition \r
+ * @param {Vector3} previousPosition \r
+ * @param {Vector3} acceleration \r
+ * @param {number} passedTime The delta time since last frame\r
+ */\r
+verlet(currentPosition, previousPosition, acceleration, passedTime) {\r
+  // verlet algorithm\r
+  // next position = 2 * current Position - previous position + acceleration * (passed time)^2\r
+  // acceleration (dv/dt) = F(net)\r
+  // Dependency for one vertex: gravity, fluids/air, springs\r
+  const DRAG = 0.97;\r
+  let nextPosition = new THREE.Vector3(\r
+    (currentPosition.x - previousPosition.x) * DRAG + currentPosition.x + acceleration.x * (passedTime * passedTime),\r
+    (currentPosition.y - previousPosition.y) * DRAG + currentPosition.y + acceleration.y * (passedTime * passedTime),\r
+    (currentPosition.z - previousPosition.z) * DRAG + currentPosition.z + acceleration.z * (passedTime * passedTime),\r
+  );\r
+\r
+  // let nextPosition = new THREE.Vector3(\r
+  //   (2 * currentPosition.x) - previousPosition.x + acceleration.x * (passedTime * passedTime),\r
+  //   (2 * currentPosition.y) - previousPosition.y + acceleration.y * (passedTime * passedTime),\r
+  //   (2 * currentPosition.z) - previousPosition.z + acceleration.z * (passedTime * passedTime),\r
+  // );\r
+\r
+  return nextPosition;\r
+}\r
+\r
+euler(currentPosition, acceleration, passedTime) {\r
+  let nextPosition = new THREE.Vector3(\r
+    currentPosition.x + acceleration.x * passedTime,\r
+    currentPosition.y + acceleration.y * passedTime,\r
+    currentPosition.z + acceleration.z * passedTime,\r
+  );\r
+\r
+  return nextPosition;\r
+}\r
+\r
+wind(intersects) {\r
+  let intersect = intersects[0];\r
+  this.externalForces[intersect.face.a].z -= this.windForce;\r
+  this.externalForces[intersect.face.b].z -= this.windForce;\r
+  this.externalForces[intersect.face.c].z -= this.windForce;\r
+}\r
+\r
+mousePressed = false;\r
+mouseMoved = false;\r
+intersects;\r
+\r
+mousePress(intersects){\r
+  this.mousePressed = true;\r
+  this.intersects = intersects;\r
+\r
+}\r
+\r
+mouseMove(mousePos){\r
+  this.mouseMoved = true;\r
+  if(this.mousePressed){\r
+    let intersect = this.intersects[0];\r
+    this.externalForces[intersect.face.a].add(mousePos.clone().sub(this.geometry.vertices[intersect.face.a]).multiplyScalar(90));\r
+    /*\r
+    this.geometry.vertices[intersect.face.a].x = mousePos.x;\r
+    this.geometry.vertices[intersect.face.a].y = mousePos.y;\r
+    this.geometry.vertices[intersect.face.a].z = mousePos.z;\r
+  */  \r
+  }\r
+}\r
+\r
+mouseRelease(){\r
+  this.mousePressed = false;\r
+}\r
+\r
+}\r
+\r
diff --git a/Scripts/_main.js b/Scripts/_main.js
new file mode 100644 (file)
index 0000000..fc797c8
--- /dev/null
@@ -0,0 +1,201 @@
+import { Face, Spring, Cloth } from './cloth.js';\r
+import { OrbitControls } from './OrbitControls.js';\r
+\r
+function addLights(scene){\r
+  \r
+  scene.add( new THREE.AmbientLight( 0x222222 ) );\r
+\r
+  const light1 = new THREE.PointLight( 0xffffff, 1, 50 );\r
+  light1.position.set( 15, 1, 40 );\r
+  scene.add( light1 );\r
+\r
+  const light2 = new THREE.PointLight( 0xffffff, 1, 50 );\r
+  light2.position.set( -15, 0, 40 );\r
+  scene.add( light2 );\r
+\r
+  const light3 = new THREE.PointLight( 0xffffff, 1, 50 );\r
+  light3.position.set( 0, -1, 40 );\r
+  scene.add( light3 );\r
+  \r
+}\r
+\r
+/**\r
+ * setup THREE JS Scene, Camera and Renderer\r
+ */\r
+function setup_scene(canvasSpace) {\r
+  const scene = new THREE.Scene();\r
+  const camera = new THREE.PerspectiveCamera(75, window.innerWidth / (window.innerHeight - canvasSpace), 0.1, 1000);\r
+  const renderer = new THREE.WebGLRenderer();\r
+  /** size canvas to leave some space for UI */\r
+  renderer.setSize(window.innerWidth, window.innerHeight - canvasSpace);\r
+  renderer.antialias = true;\r
+  /** embed canvas in HTML */\r
+  document.getElementById("threejscontainer").appendChild(renderer.domElement);\r
+\r
+  /** add orbit controls */\r
+  const controls = new OrbitControls(camera, renderer.domElement);\r
+  controls.target.set(0, 0, 0);\r
+  controls.update();\r
+\r
+  /** add scene background */\r
+  const loader = new THREE.TextureLoader();\r
+  const texture = loader.load(\r
+    'Textures/tears_of_steel_bridge_2k.jpg',\r
+    () => {\r
+      const rt = new THREE.WebGLCubeRenderTarget(texture.image.height);\r
+      rt.fromEquirectangularTexture(renderer, texture);\r
+      scene.background = rt;\r
+    });\r
+\r
+  /** add flag pole */\r
+  const geometry = new THREE.CylinderGeometry( 0.02, 0.02, 5, 32 );\r
+  const material = new THREE.MeshStandardMaterial( {color: 0xffffff} );\r
+  const cylinder = new THREE.Mesh( geometry, material );\r
+  cylinder.position.set(-0.5, -2.25, 0);\r
+  scene.add( cylinder );\r
+\r
+  /** add global light */\r
+  const directionalLight = new THREE.DirectionalLight(0xffffff, 1);\r
+  scene.add(directionalLight);\r
+\r
+  /** position camera */\r
+  camera.position.z = 2;\r
+  addLights(scene);\r
+  return [scene, camera, renderer];\r
+}\r
+\r
+/** call "init" when document is fully loaded */\r
+document.body.onload = init;\r
+\r
+function init() {\r
+  let mousePos = new THREE.Vector2();\r
+  let previousClothSimulation;\r
+  \r
+  /**\r
+   * Space left empty under canvas\r
+   * for UI elements\r
+   */\r
+  const canvasSpace = 200;\r
+\r
+  /** Constant Frame Time */\r
+  const frameTime = 1000.0 / 60.0;\r
+\r
+  /** Setup scene */\r
+  let [scene, camera, renderer] = setup_scene(canvasSpace);\r
+  \r
+  /** setup cloth and generate debug mesh */\r
+  let cloth = new Cloth();\r
+  cloth.createBasic(1, 0.5, 20, 20);\r
+  document.getElementById("windToggle").onchange = (e) => {\r
+    if (e.target.checked)\r
+      cloth.windFactor.set(0.5, 0.2, 0.2);\r
+    else\r
+      cloth.windFactor.set(0, 0, 0);\r
+  };\r
+  //cloth.createDebugMesh(scene);\r
+\r
+\r
+  const material = new THREE.MeshStandardMaterial({ color: 0xC70039, side: THREE.DoubleSide, flatShading: false });\r
+  const mesh = new THREE.Mesh(cloth.geometry, material);\r
+\r
+  scene.add(mesh);\r
+\r
+\r
+  \r
+  let raycaster = new THREE.Raycaster();\r
+  let intersects;\r
+  let rightMousePressed;\r
+  /**\r
+   * function called every frame\r
+   * @param {number} dt - time passed since last frame in ms\r
+   */\r
+  function animate(dt) {\r
+    cloth.simulate(dt/1000);\r
+\r
+    raycaster.setFromCamera( new THREE.Vector2((mousePos.x / w) * 2 - 1, ((h - mousePos.y) / h) * 2 - 1), camera );\r
+\r
+    intersects = raycaster.intersectObject( mesh );\r
+\r
+    if ( intersects.length > 0 && rightMousePressed) {\r
+      cloth.wind(intersects);\r
+    }\r
+    setTimeout(() => {\r
+      animate(frameTime);\r
+    }, frameTime);\r
+    renderer.render(scene, camera);\r
+  }\r
+\r
+\r
+  /** add callback for window resize */\r
+  let canvas = document.getElementsByTagName("canvas")[0];\r
+  let w = window.innerWidth;\r
+  let h = window.innerHeight - canvasSpace;\r
+  let resize = function () {\r
+    w = window.innerWidth;\r
+    h = window.innerHeight - canvasSpace;\r
+    canvas.width = w;\r
+    canvas.height = h;\r
+  }\r
+  window.onresize = resize;\r
+  resize();\r
+\r
+  /**\r
+   * if canvas has been successfully initialized\r
+   * start rendering\r
+   */\r
+  if (canvas.getContext) {\r
+    animate(performance.now());\r
+  }\r
+\r
+  \r
+\r
+  /** add mouse move callback */\r
+  canvas.onmousemove = (evt) => {\r
+    mousePos.x = evt.clientX;\r
+    mousePos.y = evt.clientY;\r
+\r
+    cloth.mouseMove(calculateMousePosToWorld(evt));\r
+  };\r
+\r
+  /**\r
+   * Prevent context menu while blowing wind\r
+   */\r
+  canvas.addEventListener('contextmenu', function(evt) { \r
+    evt.preventDefault();\r
+  }, false);\r
+\r
+\r
+  canvas.onmousedown = (evt) => {\r
+\r
+    // Check mouse click\r
+    rightMousePressed = evt.button == 2;\r
+    \r
+    if(intersects.length > 0 && evt.button == 0){\r
+      cloth.mousePress(intersects);\r
+    } \r
+  }\r
+  \r
+  canvas.onmouseup = (evt) => {\r
+    cloth.mouseRelease();\r
+    rightMousePressed = false;\r
+  }\r
+\r
+  function calculateMousePosToWorld(evt){\r
+    var vec = new THREE.Vector3(); // create once and reuse\r
+    var pos = new THREE.Vector3(); // create once and reuse\r
+\r
+    vec.set(\r
+      ( evt.clientX / window.innerWidth ) * 2 - 1,\r
+    - ( evt.clientY / window.innerHeight ) * 2 + 1,\r
+      0.5 );\r
+\r
+    vec.unproject( camera );\r
+\r
+    vec.sub( camera.position ).normalize();\r
+\r
+    var distance = - camera.position.z / vec.z;\r
+\r
+    pos.copy( camera.position ).add( vec.multiplyScalar( distance ) );\r
+    return pos;\r
+  }\r
+}
\ No newline at end of file
index 546f7d34ff05b7a561cee2a6fda279087ae63240..f1068d4b6fc056e421b60f4e604c17c1b9c3d8b9 100644 (file)
@@ -1,621 +1,4 @@
-/**\r
- *  Convenience Function for calculating the distance between two vectors\r
- *  because THREE JS Vector functions mutate variables\r
- * @param {Vector3} a - Vector A\r
- * @param {Vector3} b - Vector B\r
- */\r
-function vectorLength(a, b) {\r
-  let v1 = new THREE.Vector3();\r
-  v1.copy(a);\r
-  let v2 = new THREE.Vector3();\r
-  v2.copy(b);\r
-\r
-  return v1.sub(v2).length();\r
-}\r
-\r
-/**\r
- * Class representing a quad face\r
- * Each face consists of two triangular mesh faces\r
- * containts four indices for determining vertices\r
- * and six springs, one between each of the vertices\r
- */\r
-export class Face {\r
-  a;\r
-  b;\r
-  c;\r
-  d;\r
-\r
-  springs = [];\r
-\r
-  constructor(a, b, c, d) {\r
-    this.a = a;\r
-    this.b = b;\r
-    this.c = c;\r
-    this.d = d;\r
-  }\r
-}\r
-\r
-/**\r
- * Class representing a single spring\r
- * has a current and resting length\r
- * and indices to the two connected vertices\r
- */\r
-export class Spring {\r
-  restLength;\r
-  currentLength;\r
-  index1;\r
-  index2;\r
-\r
-\r
-  /**\r
-   * set vertex indices\r
-   * and calculate inital length based on the\r
-   * vertex positions\r
-   * @param {Array<Vector3>} vertices \r
-   * @param {number} index1 \r
-   * @param {number} index2 \r
-   */\r
-  constructor(vertices, index1, index2) {\r
-    this.index1 = index1;\r
-    this.index2 = index2;\r
-\r
-    let length = vectorLength(vertices[index1], vertices[index2]);\r
-    this.restLength = length;\r
-    this.currentLength = length;\r
-  }\r
-\r
-  getDirection(vertices) {\r
-    let direction = new THREE.Vector3();\r
-    direction.copy(vertices[this.index1]);\r
-\r
-    direction.sub(vertices[this.index2]);\r
-    direction.divideScalar(vectorLength(vertices[this.index1], vertices[this.index2]));\r
-\r
-    return direction;\r
-  }\r
-\r
-  update(vertices) {\r
-    let length = vectorLength(vertices[this.index1], vertices[this.index2]);\r
-    this.currentLength = length;\r
-  }\r
-}\r
-\r
-/**\r
- * Class representing a single piece of cloth\r
- * contains THREE JS geometry,\r
- * logically represented by an array of adjacent faces\r
- * and vertex weights which are accessed by the same\r
- * indices as the vertices in the Mesh\r
- */\r
-export class Cloth {\r
-  VertexWeight = 1;\r
-\r
-  geometry = new THREE.Geometry();\r
-\r
-  faces = [];\r
-\r
-  vertexWeights = [];\r
-\r
-  vertexRigidness = [];\r
-\r
-  fixedPoints = [];\r
-\r
-  externalForces = [];\r
-  windForce = 50;\r
-\r
-  windFactor = new THREE.Vector3(0, 0, 0);\r
-\r
-  /**\r
-   * creates a rectangular piece of cloth\r
-   * takes the size of the cloth\r
-   * and the number of vertices it should be composed of\r
-   * @param {number} width - width of the cloth\r
-   * @param {number} height - height of the cloth\r
-   * @param {number} numPointsWidth - number of vertices in horizontal direction\r
-   * @param {number} numPointsHeight  - number of vertices in vertical direction\r
-   */\r
-  createBasic(width, height, numPointsWidth, numPointsHeight) {\r
-    /** resulting vertices and faces */\r
-    let vertices = [];\r
-    let faces = [];\r
-\r
-    this.width = width;\r
-    this.height = height;\r
-    this.numPointsWidth = numPointsWidth;\r
-    this.numPointsHeight = numPointsHeight;\r
-\r
-    /**\r
-     * distance between two vertices horizontally/vertically\r
-     * divide by the number of points minus one\r
-     * because there are (n - 1) lines between n vertices\r
-     */\r
-    let stepWidth = width / (numPointsWidth - 1);\r
-    let stepHeight = height / (numPointsHeight - 1);\r
-\r
-    /**\r
-     * iterate over the number of vertices in x/y axis\r
-     * and add a new Vector3 to "vertices"\r
-     */\r
-    for (let y = 0; y < numPointsHeight; y++) {\r
-      for (let x = 0; x < numPointsWidth; x++) {\r
-        vertices.push(\r
-          new THREE.Vector3((x - ((numPointsWidth-1)/2)) * stepWidth, height - (y + ((numPointsHeight-1)/2)) * stepHeight, 0)\r
-        );\r
-      }\r
-    }\r
-\r
-    /**\r
-     * helper function to calculate index of vertex\r
-     * in "vertices" array based on its x and y positions\r
-     * in the mesh\r
-     * @param {number} x - x index of vertex\r
-     * @param {number} y - y index of vertex\r
-     */\r
-    function getVertexIndex(x, y) {\r
-      return y * numPointsWidth + x;\r
-    }\r
-\r
-    /**\r
-     * generate faces based on 4 vertices\r
-     * and 6 springs each\r
-     */\r
-    for (let y = 0; y < numPointsHeight - 1; y++) {\r
-      for (let x = 0; x < numPointsWidth - 1; x++) {\r
-        let newFace = new Face(\r
-          getVertexIndex(x, y),\r
-          getVertexIndex(x, y + 1),\r
-          getVertexIndex(x + 1, y),\r
-          getVertexIndex(x + 1, y + 1),\r
-        );\r
-\r
-        newFace.springs.push(new Spring(vertices, getVertexIndex(x, y), getVertexIndex(x + 1, y)));         // oben\r
-        newFace.springs.push(new Spring(vertices, getVertexIndex(x, y), getVertexIndex(x, y + 1)));         // links\r
-        newFace.springs.push(new Spring(vertices, getVertexIndex(x, y), getVertexIndex(x + 1, y + 1)));     // oben links  -> unten rechts diagonal\r
-        newFace.springs.push(new Spring(vertices, getVertexIndex(x + 1, y), getVertexIndex(x, y + 1)));     // oben rechts -> unten links diagonal\r
-        newFace.springs.push(new Spring(vertices, getVertexIndex(x + 1, y), getVertexIndex(x + 1, y + 1))); // rechts\r
-        newFace.springs.push(new Spring(vertices, getVertexIndex(x, y + 1), getVertexIndex(x + 1, y + 1))); // unten\r
-\r
-        faces.push(newFace);\r
-      }\r
-    }\r
-\r
-    /**\r
-     * call createExplicit\r
-     * with generated vertices and faces\r
-     */\r
-    this.createExplicit(vertices, faces);\r
-\r
-    /**\r
-     * hand cloth from left and right upper corners\r
-     */\r
-    this.fixedPoints.push(getVertexIndex(0, 0));\r
-    this.fixedPoints.push(getVertexIndex(0, 19));\r
-  }\r
-\r
-  /**\r
-   * Generate THREE JS Geometry\r
-   * (list of vertices and list of indices representing triangles)\r
-   * and calculate the weight of each face and split it between\r
-   * surrounding vertices\r
-   * @param {Array<Vector3>} vertices \r
-   * @param {Array<Face>} faces \r
-   */\r
-  createExplicit(vertices, faces) {\r
-\r
-    /**\r
-     * Copy vertices and initialize vertex weights to 0\r
-     */\r
-    for (let i in vertices) {\r
-      this.geometry.vertices.push(vertices[i].clone());\r
-      this.previousPositions.push(vertices[i].clone());\r
-      // this.geometry.vertices.push(vertices[i]);\r
-      // this.previousPositions.push(vertices[i]);\r
-      this.vertexWeights.push(0);\r
-      this.vertexRigidness.push(false);\r
-      this.externalForces.push(new THREE.Vector3(0,0,0));\r
-    }\r
-    /**\r
-     * copy faces,\r
-     * generate two triangles per face,\r
-     * calculate weight of face as its area\r
-     * and split between the 4 vertices\r
-     */\r
-    for (let i in faces) {\r
-      let face = faces[i];\r
-\r
-      /** copy faces to class member */\r
-      this.faces.push(face);\r
-\r
-      /** generate triangles */\r
-      this.geometry.faces.push(new THREE.Face3(\r
-        face.a, face.b, face.c\r
-      ));\r
-      this.geometry.faces.push(new THREE.Face3(\r
-        face.c, face.b, face.d\r
-      ));\r
-\r
-      /**\r
-       * calculate area of face as combined area of\r
-       * its two composing triangles\r
-       */\r
-      let xLength = vectorLength(this.geometry.vertices[face.b], this.geometry.vertices[face.a]);\r
-      let yLength = vectorLength(this.geometry.vertices[face.c], this.geometry.vertices[face.a]);\r
-      let weight = xLength * yLength / 2;\r
-\r
-      xLength = vectorLength(this.geometry.vertices[face.b], this.geometry.vertices[face.d]);\r
-      yLength = vectorLength(this.geometry.vertices[face.c], this.geometry.vertices[face.d]);\r
-      weight += xLength * yLength / 2;\r
-\r
-      weight *= 10;\r
-\r
-      /**\r
-       * split weight equally between four surrounding vertices\r
-       */\r
-      this.vertexWeights[face.a] += weight / 4;\r
-      this.vertexWeights[face.b] += weight / 4;\r
-      this.vertexWeights[face.c] += weight / 4;\r
-      this.vertexWeights[face.d] += weight / 4;\r
-    }\r
-\r
-    /**\r
-     * let THREE JS compute bounding sphere around generated mesh\r
-     * needed for View Frustum Culling internally\r
-     */\r
-    this.geometry.computeBoundingSphere();\r
-    this.geometry.computeFaceNormals();\r
-    this.geometry.computeVertexNormals();\r
-  }\r
-\r
-  /**\r
-   * generate a debug mesh for visualizing\r
-   * vertices and springs of the cloth\r
-   * and add it to scene for rendering\r
-   * @param {Scene} scene - Scene to add Debug Mesh to\r
-   */\r
-  createDebugMesh(scene) {\r
-    /**\r
-     * helper function to generate a single line\r
-     * between two Vertices with a given color\r
-     * @param {Vector3} from \r
-     * @param {Vector3} to \r
-     * @param {number} color \r
-     */\r
-    function addLine(from, to, color) {\r
-      let geometry = new THREE.Geometry();\r
-      geometry.vertices.push(from);\r
-      geometry.vertices.push(to);\r
-      let material = new THREE.LineBasicMaterial({ color: color, linewidth: 10 });\r
-      let line = new THREE.Line(geometry, material);\r
-      line.renderOrder = 1;\r
-      scene.add(line);\r
-    }\r
-    /**\r
-     * helper function to generate a small sphere\r
-     * at a given Vertex Position with color\r
-     * @param {Vector3} point \r
-     * @param {number} color \r
-     */\r
-    function addPoint(point, color) {\r
-      const geometry = new THREE.SphereGeometry(0.05, 32, 32);\r
-      const material = new THREE.MeshBasicMaterial({ color: color });\r
-      const sphere = new THREE.Mesh(geometry, material);\r
-      sphere.position.set(point.x, point.y, point.z);\r
-      scene.add(sphere);\r
-    }\r
-\r
-    let lineColor = 0x000000;\r
-    let pointColor = 0xff00000;\r
-\r
-    /**\r
-     * generate one line for each of the 6 springs\r
-     * and one point for each of the 4 vertices\r
-     * for all of the faces\r
-     */\r
-    for (let i in this.faces) {\r
-      let face = this.faces[i];\r
-      addLine(this.geometry.vertices[face.a], this.geometry.vertices[face.b], lineColor);\r
-      addLine(this.geometry.vertices[face.a], this.geometry.vertices[face.c], lineColor);\r
-      addLine(this.geometry.vertices[face.a], this.geometry.vertices[face.d], lineColor);\r
-      addLine(this.geometry.vertices[face.b], this.geometry.vertices[face.c], lineColor);\r
-      addLine(this.geometry.vertices[face.b], this.geometry.vertices[face.d], lineColor);\r
-      addLine(this.geometry.vertices[face.c], this.geometry.vertices[face.d], lineColor);\r
-\r
-      addPoint(this.geometry.vertices[face.a], pointColor);\r
-      addPoint(this.geometry.vertices[face.b], pointColor);\r
-      addPoint(this.geometry.vertices[face.c], pointColor);\r
-      addPoint(this.geometry.vertices[face.d], pointColor);\r
-    }\r
-  }\r
-\r
-  previousPositions = [];\r
-  time = 0;\r
-  /**\r
-   * \r
-   * @param {number} dt time in seconds since last frame\r
-   */\r
-  simulate(dt) {\r
-    for (let i in this.geometry.vertices) {\r
-      let acceleration = this.getAcceleration(i, dt);\r
-\r
-      //acceleration.clampLength(0, 10);\r
-\r
-      if (Math.abs(acceleration.length()) <= 10e-4) {\r
-        acceleration.set(0, 0, 0);\r
-      }\r
\r
-      let currentPosition = this.verlet(this.geometry.vertices[i].clone(), this.previousPositions[i].clone(), acceleration, dt);\r
-      //let currentPosition = this.euler(this.geometry.vertices[i], acceleration, dt);\r
-     \r
-      this.previousPositions[i].copy(this.geometry.vertices[i]);\r
-      this.geometry.vertices[i].copy(currentPosition);\r
-    }\r
-    \r
-    this.checkIntersect();\r
-    \r
-    this.time += dt;\r
-\r
-    for (let face of this.faces) {\r
-      for (let spring of face.springs) {\r
-        spring.update(this.geometry.vertices);\r
-      }\r
-    }\r
-\r
-    /**\r
-     * let THREE JS compute bounding sphere around generated mesh\r
-     * needed for View Frustum Culling internally\r
-     */\r
-\r
-    this.geometry.verticesNeedUpdate = true;\r
-    this.geometry.elementsNeedUpdate = true;\r
-    this.geometry.computeBoundingSphere();\r
-    this.geometry.computeFaceNormals();\r
-    this.geometry.computeVertexNormals();\r
-\r
-  }\r
-\r
-checkIntersect() {\r
-  let npw = this.numPointsWidth;\r
-  function getX(i, ) { return i % npw; }\r
-  function getY(i) { return Math.floor(i / npw); }\r
-  for (let i in this.geometry.vertices) {\r
-    for (let j in this.geometry.vertices) {\r
-      this.vertexRigidness[i] = false;\r
-      this.vertexRigidness[j] = false;\r
-      if (i == j || (Math.abs(getX(i) - getX(j)) == 1 && Math.abs(getY(i) - getY(j)) == 1))\r
-        continue;\r
-      let posI = this.geometry.vertices[i];\r
-      let posJ = this.geometry.vertices[j];\r
-      let dist = posI.distanceTo(posJ);\r
-      const collisionDistance = Math.min(this.width / this.numPointsWidth, this.height / this.numPointsHeight);\r
-      if (dist < collisionDistance) {\r
-        this.vertexRigidness[i] = true;\r
-        this.vertexRigidness[j] = true;\r
-        let diff = this.geometry.vertices[i].clone().sub(this.geometry.vertices[j]).normalize().multiplyScalar((collisionDistance - dist) * 1.001 / 2);\r
-        if (!(this.fixedPoints.includes(i) || this.fixedPoints.includes(j))) {\r
-          this.geometry.vertices[i].add(diff);\r
-          this.geometry.vertices[j].sub(diff);\r
-        }\r
-      }\r
-    }\r
-  }\r
-}\r
-\r
-/**\r
- * Equation of motion for each vertex which represents the acceleration \r
- * @param {number} vertexIndex The index of the current vertex whose acceleration should be calculated\r
- *  @param {number} dt The time passed since last frame\r
- */\r
-getAcceleration(vertexIndex, dt) {\r
-  if (this.fixedPoints.includes(parseInt(vertexIndex)) ||\r
-      this.vertexRigidness[vertexIndex]) {\r
-    return new THREE.Vector3(0, 0, 0);\r
-  }\r
-\r
-  let externalForce = this.externalForces[vertexIndex];\r
-  let vertex = this.geometry.vertices[vertexIndex];//.add(externalForce);\r
-\r
-  // Mass of vertex\r
-  let M = this.vertexWeights[vertexIndex];\r
-  // constant gravity\r
-  let g = new THREE.Vector3(0, -9.8, 0);\r
-  // stiffness\r
-  let k = 1000;\r
-\r
-  // Wind vector\r
-  let fWind = new THREE.Vector3(\r
-    this.windFactor.x * (Math.sin(vertex.x * vertex.y * this.time)+1),\r
-    this.windFactor.y * Math.cos(vertex.z * this.time),\r
-    this.windFactor.z * Math.sin(Math.cos(5 * vertex.x * vertex.y * vertex.z))\r
-  );\r
-  //console.log(fWind);\r
-\r
-  /**\r
-   * constant determined by the properties of the surrounding fluids (air)\r
-   * achievement of cloth effects through try out\r
-   * */\r
-  let a = 0.1;\r
-  \r
-  let velocity = new THREE.Vector3(\r
-    (this.previousPositions[vertexIndex].x - vertex.x) / dt,\r
-    (this.previousPositions[vertexIndex].y - vertex.y) / dt,\r
-    (this.previousPositions[vertexIndex].z - vertex.z) / dt\r
-  );\r
-\r
-  //console.log(velocity, vertex, this.previousPositions[vertexIndex]);\r
-\r
-  let fAirResistance = velocity.multiply(velocity).multiplyScalar(-a);\r
-  \r
-  let springSum = new THREE.Vector3(0, 0, 0);\r
-\r
-  // Get the bounding springs and add them to the needed springs\r
-  // TODO: optimize\r
-\r
-  const numPointsX = this.numPointsWidth;\r
-  const numPointsY = this.numPointsHeight;\r
-  const numFacesX = numPointsX - 1;\r
-  const numFacesY = numPointsY - 1;\r
-\r
-  function getFaceIndex(x, y) {\r
-    return y * numFacesX + x;\r
-  }\r
-\r
-  let indexX = vertexIndex % numPointsX;\r
-  let indexY = Math.floor(vertexIndex / numPointsX);\r
-\r
-  let springs = [];\r
-\r
-  // 0  oben\r
-  // 1  links\r
-  // 2  oben links  -> unten rechts diagonal\r
-  // 3  oben rechts -> unten links diagonal\r
-  // 4  rechts\r
-  // 5  unten\r
-\r
-  let ul = indexX > 0 && indexY < numPointsY - 1;\r
-  let ur = indexX < numPointsX - 1 && indexY < numPointsY - 1;\r
-  let ol = indexX > 0 && indexY > 0;\r
-  let or = indexX < numPointsX - 1 && indexY > 0;\r
-\r
-  if (ul) {\r
-    let faceUL = this.faces[getFaceIndex(indexX - 1, indexY)];\r
-    springs.push(faceUL.springs[3]);\r
-    if (!ol)\r
-      springs.push(faceUL.springs[0]);\r
-    springs.push(faceUL.springs[4]);\r
-  }\r
-  if (ur) {\r
-    let faceUR = this.faces[getFaceIndex(indexX, indexY)];\r
-    springs.push(faceUR.springs[2]);\r
-    if (!or)\r
-      springs.push(faceUR.springs[0]);\r
-    if (!ul)\r
-      springs.push(faceUR.springs[1]);\r
-  }\r
-  if (ol) {\r
-    let faceOL = this.faces[getFaceIndex(indexX - 1, indexY - 1)];\r
-    springs.push(faceOL.springs[2]);\r
-    springs.push(faceOL.springs[4]);\r
-    springs.push(faceOL.springs[5]);\r
-  }\r
-  if (or) {\r
-    let faceOR = this.faces[getFaceIndex(indexX , indexY - 1)];\r
-    springs.push(faceOR.springs[3]);\r
-    if (!ol)\r
-      springs.push(faceOR.springs[1]);\r
-    springs.push(faceOR.springs[5]);\r
-  }\r
-\r
-  for (let spring of springs) {\r
-    let springDirection = spring.getDirection(this.geometry.vertices);\r
-\r
-    if (spring.index1 == vertexIndex)\r
-      springDirection.multiplyScalar(-1);\r
-\r
-    springSum.add(springDirection.multiplyScalar(k * (spring.restLength - spring.currentLength)));\r
-  }\r
-  \r
-  let result = new THREE.Vector3(1, 1, 1);\r
-  result.multiplyScalar(M).multiply(g).add(fWind).add(externalForce).add(fAirResistance).sub(springSum);\r
-\r
-  document.getElementById("Output").innerText = "SpringSum: " + Math.floor(springSum.y);\r
-\r
-  let threshold = 1;\r
-  let forceReduktion = 0.8;\r
-  if(Math.abs(externalForce.z) > threshold){\r
-    externalForce.z *= forceReduktion;\r
-  } else {\r
-    externalForce.z = 0;\r
-  }\r
-\r
-  if(Math.abs(externalForce.y) > threshold){\r
-    externalForce.y *= forceReduktion;\r
-  } else {\r
-    externalForce.y = 0;\r
-  }\r
-\r
-  if(Math.abs(externalForce.x) > threshold){\r
-    externalForce.x *= forceReduktion;\r
-  } else {\r
-    externalForce.x = 0;\r
-  }\r
-    \r
-  \r
-\r
-  return result;\r
-}\r
-\r
-/**\r
- * The Verlet algorithm as an integrator \r
- * to get the next position of a vertex  \r
- * @param {Vector3} currentPosition \r
- * @param {Vector3} previousPosition \r
- * @param {Vector3} acceleration \r
- * @param {number} passedTime The delta time since last frame\r
- */\r
-verlet(currentPosition, previousPosition, acceleration, passedTime) {\r
-  // verlet algorithm\r
-  // next position = 2 * current Position - previous position + acceleration * (passed time)^2\r
-  // acceleration (dv/dt) = F(net)\r
-  // Dependency for one vertex: gravity, fluids/air, springs\r
-  const DRAG = 0.97;\r
-  let nextPosition = new THREE.Vector3(\r
-    (currentPosition.x - previousPosition.x) * DRAG + currentPosition.x + acceleration.x * (passedTime * passedTime),\r
-    (currentPosition.y - previousPosition.y) * DRAG + currentPosition.y + acceleration.y * (passedTime * passedTime),\r
-    (currentPosition.z - previousPosition.z) * DRAG + currentPosition.z + acceleration.z * (passedTime * passedTime),\r
-  );\r
-\r
-  // let nextPosition = new THREE.Vector3(\r
-  //   (2 * currentPosition.x) - previousPosition.x + acceleration.x * (passedTime * passedTime),\r
-  //   (2 * currentPosition.y) - previousPosition.y + acceleration.y * (passedTime * passedTime),\r
-  //   (2 * currentPosition.z) - previousPosition.z + acceleration.z * (passedTime * passedTime),\r
-  // );\r
-\r
-  return nextPosition;\r
-}\r
-\r
-euler(currentPosition, acceleration, passedTime) {\r
-  let nextPosition = new THREE.Vector3(\r
-    currentPosition.x + acceleration.x * passedTime,\r
-    currentPosition.y + acceleration.y * passedTime,\r
-    currentPosition.z + acceleration.z * passedTime,\r
-  );\r
-\r
-  return nextPosition;\r
-}\r
-\r
-wind(intersects) {\r
-  let intersect = intersects[0];\r
-  this.externalForces[intersect.face.a].z -= this.windForce;\r
-  this.externalForces[intersect.face.b].z -= this.windForce;\r
-  this.externalForces[intersect.face.c].z -= this.windForce;\r
-}\r
-\r
-mousePressed = false;\r
-mouseMoved = false;\r
-intersects;\r
-\r
-mousePress(intersects){\r
-  this.mousePressed = true;\r
-  this.intersects = intersects;\r
-\r
-}\r
-\r
-mouseMove(mousePos){\r
-  this.mouseMoved = true;\r
-  if(this.mousePressed){\r
-    let intersect = this.intersects[0];\r
-    this.externalForces[intersect.face.a].add(mousePos.clone().sub(this.geometry.vertices[intersect.face.a]).multiplyScalar(90));\r
-    /*\r
-    this.geometry.vertices[intersect.face.a].x = mousePos.x;\r
-    this.geometry.vertices[intersect.face.a].y = mousePos.y;\r
-    this.geometry.vertices[intersect.face.a].z = mousePos.z;\r
-  */  \r
-  }\r
-}\r
-\r
-mouseRelease(){\r
-  this.mousePressed = false;\r
-}\r
-\r
-}\r
-\r
+// cloth rendering\r
+// simulate\r
+// setup scene\r
+// orbit controls/skybox/flagge
\ No newline at end of file
index fc797c872ed2503a9808e8a86df0bfa5411e5dab..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1,201 +0,0 @@
-import { Face, Spring, Cloth } from './cloth.js';\r
-import { OrbitControls } from './OrbitControls.js';\r
-\r
-function addLights(scene){\r
-  \r
-  scene.add( new THREE.AmbientLight( 0x222222 ) );\r
-\r
-  const light1 = new THREE.PointLight( 0xffffff, 1, 50 );\r
-  light1.position.set( 15, 1, 40 );\r
-  scene.add( light1 );\r
-\r
-  const light2 = new THREE.PointLight( 0xffffff, 1, 50 );\r
-  light2.position.set( -15, 0, 40 );\r
-  scene.add( light2 );\r
-\r
-  const light3 = new THREE.PointLight( 0xffffff, 1, 50 );\r
-  light3.position.set( 0, -1, 40 );\r
-  scene.add( light3 );\r
-  \r
-}\r
-\r
-/**\r
- * setup THREE JS Scene, Camera and Renderer\r
- */\r
-function setup_scene(canvasSpace) {\r
-  const scene = new THREE.Scene();\r
-  const camera = new THREE.PerspectiveCamera(75, window.innerWidth / (window.innerHeight - canvasSpace), 0.1, 1000);\r
-  const renderer = new THREE.WebGLRenderer();\r
-  /** size canvas to leave some space for UI */\r
-  renderer.setSize(window.innerWidth, window.innerHeight - canvasSpace);\r
-  renderer.antialias = true;\r
-  /** embed canvas in HTML */\r
-  document.getElementById("threejscontainer").appendChild(renderer.domElement);\r
-\r
-  /** add orbit controls */\r
-  const controls = new OrbitControls(camera, renderer.domElement);\r
-  controls.target.set(0, 0, 0);\r
-  controls.update();\r
-\r
-  /** add scene background */\r
-  const loader = new THREE.TextureLoader();\r
-  const texture = loader.load(\r
-    'Textures/tears_of_steel_bridge_2k.jpg',\r
-    () => {\r
-      const rt = new THREE.WebGLCubeRenderTarget(texture.image.height);\r
-      rt.fromEquirectangularTexture(renderer, texture);\r
-      scene.background = rt;\r
-    });\r
-\r
-  /** add flag pole */\r
-  const geometry = new THREE.CylinderGeometry( 0.02, 0.02, 5, 32 );\r
-  const material = new THREE.MeshStandardMaterial( {color: 0xffffff} );\r
-  const cylinder = new THREE.Mesh( geometry, material );\r
-  cylinder.position.set(-0.5, -2.25, 0);\r
-  scene.add( cylinder );\r
-\r
-  /** add global light */\r
-  const directionalLight = new THREE.DirectionalLight(0xffffff, 1);\r
-  scene.add(directionalLight);\r
-\r
-  /** position camera */\r
-  camera.position.z = 2;\r
-  addLights(scene);\r
-  return [scene, camera, renderer];\r
-}\r
-\r
-/** call "init" when document is fully loaded */\r
-document.body.onload = init;\r
-\r
-function init() {\r
-  let mousePos = new THREE.Vector2();\r
-  let previousClothSimulation;\r
-  \r
-  /**\r
-   * Space left empty under canvas\r
-   * for UI elements\r
-   */\r
-  const canvasSpace = 200;\r
-\r
-  /** Constant Frame Time */\r
-  const frameTime = 1000.0 / 60.0;\r
-\r
-  /** Setup scene */\r
-  let [scene, camera, renderer] = setup_scene(canvasSpace);\r
-  \r
-  /** setup cloth and generate debug mesh */\r
-  let cloth = new Cloth();\r
-  cloth.createBasic(1, 0.5, 20, 20);\r
-  document.getElementById("windToggle").onchange = (e) => {\r
-    if (e.target.checked)\r
-      cloth.windFactor.set(0.5, 0.2, 0.2);\r
-    else\r
-      cloth.windFactor.set(0, 0, 0);\r
-  };\r
-  //cloth.createDebugMesh(scene);\r
-\r
-\r
-  const material = new THREE.MeshStandardMaterial({ color: 0xC70039, side: THREE.DoubleSide, flatShading: false });\r
-  const mesh = new THREE.Mesh(cloth.geometry, material);\r
-\r
-  scene.add(mesh);\r
-\r
-\r
-  \r
-  let raycaster = new THREE.Raycaster();\r
-  let intersects;\r
-  let rightMousePressed;\r
-  /**\r
-   * function called every frame\r
-   * @param {number} dt - time passed since last frame in ms\r
-   */\r
-  function animate(dt) {\r
-    cloth.simulate(dt/1000);\r
-\r
-    raycaster.setFromCamera( new THREE.Vector2((mousePos.x / w) * 2 - 1, ((h - mousePos.y) / h) * 2 - 1), camera );\r
-\r
-    intersects = raycaster.intersectObject( mesh );\r
-\r
-    if ( intersects.length > 0 && rightMousePressed) {\r
-      cloth.wind(intersects);\r
-    }\r
-    setTimeout(() => {\r
-      animate(frameTime);\r
-    }, frameTime);\r
-    renderer.render(scene, camera);\r
-  }\r
-\r
-\r
-  /** add callback for window resize */\r
-  let canvas = document.getElementsByTagName("canvas")[0];\r
-  let w = window.innerWidth;\r
-  let h = window.innerHeight - canvasSpace;\r
-  let resize = function () {\r
-    w = window.innerWidth;\r
-    h = window.innerHeight - canvasSpace;\r
-    canvas.width = w;\r
-    canvas.height = h;\r
-  }\r
-  window.onresize = resize;\r
-  resize();\r
-\r
-  /**\r
-   * if canvas has been successfully initialized\r
-   * start rendering\r
-   */\r
-  if (canvas.getContext) {\r
-    animate(performance.now());\r
-  }\r
-\r
-  \r
-\r
-  /** add mouse move callback */\r
-  canvas.onmousemove = (evt) => {\r
-    mousePos.x = evt.clientX;\r
-    mousePos.y = evt.clientY;\r
-\r
-    cloth.mouseMove(calculateMousePosToWorld(evt));\r
-  };\r
-\r
-  /**\r
-   * Prevent context menu while blowing wind\r
-   */\r
-  canvas.addEventListener('contextmenu', function(evt) { \r
-    evt.preventDefault();\r
-  }, false);\r
-\r
-\r
-  canvas.onmousedown = (evt) => {\r
-\r
-    // Check mouse click\r
-    rightMousePressed = evt.button == 2;\r
-    \r
-    if(intersects.length > 0 && evt.button == 0){\r
-      cloth.mousePress(intersects);\r
-    } \r
-  }\r
-  \r
-  canvas.onmouseup = (evt) => {\r
-    cloth.mouseRelease();\r
-    rightMousePressed = false;\r
-  }\r
-\r
-  function calculateMousePosToWorld(evt){\r
-    var vec = new THREE.Vector3(); // create once and reuse\r
-    var pos = new THREE.Vector3(); // create once and reuse\r
-\r
-    vec.set(\r
-      ( evt.clientX / window.innerWidth ) * 2 - 1,\r
-    - ( evt.clientY / window.innerHeight ) * 2 + 1,\r
-      0.5 );\r
-\r
-    vec.unproject( camera );\r
-\r
-    vec.sub( camera.position ).normalize();\r
-\r
-    var distance = - camera.position.z / vec.z;\r
-\r
-    pos.copy( camera.position ).add( vec.multiplyScalar( distance ) );\r
-    return pos;\r
-  }\r
-}
\ No newline at end of file
index 1cf26b32e07893d0370e012310f8aaac7419ac38..7b0e89292ad2423e057dc8eaeb6073aec59e9149 100644 (file)
                };
        }
 
-       var REVISION = '123';
+       /**
+        * Copyright (c) 2014-present, Facebook, Inc.
+        *
+        * This source code is licensed under the MIT license found in the
+        * LICENSE file in the root directory of this source tree.
+        */
+       var runtime = function (exports) {
+
+               var Op = Object.prototype;
+               var hasOwn = Op.hasOwnProperty;
+               var undefined$1; // More compressible than void 0.
+
+               var $Symbol = typeof Symbol === "function" ? Symbol : {};
+               var iteratorSymbol = $Symbol.iterator || "@@iterator";
+               var asyncIteratorSymbol = $Symbol.asyncIterator || "@@asyncIterator";
+               var toStringTagSymbol = $Symbol.toStringTag || "@@toStringTag";
+
+               function define(obj, key, value) {
+                       Object.defineProperty(obj, key, {
+                               value: value,
+                               enumerable: true,
+                               configurable: true,
+                               writable: true
+                       });
+                       return obj[key];
+               }
+
+               try {
+                       // IE 8 has a broken Object.defineProperty that only works on DOM objects.
+                       define({}, "");
+               } catch (err) {
+                       define = function define(obj, key, value) {
+                               return obj[key] = value;
+                       };
+               }
+
+               function wrap(innerFn, outerFn, self, tryLocsList) {
+                       // If outerFn provided and outerFn.prototype is a Generator, then outerFn.prototype instanceof Generator.
+                       var protoGenerator = outerFn && outerFn.prototype instanceof Generator ? outerFn : Generator;
+                       var generator = Object.create(protoGenerator.prototype);
+                       var context = new Context(tryLocsList || []); // The ._invoke method unifies the implementations of the .next,
+                       // .throw, and .return methods.
+
+                       generator._invoke = makeInvokeMethod(innerFn, self, context);
+                       return generator;
+               }
+
+               exports.wrap = wrap; // Try/catch helper to minimize deoptimizations. Returns a completion
+               // record like context.tryEntries[i].completion. This interface could
+               // have been (and was previously) designed to take a closure to be
+               // invoked without arguments, but in all the cases we care about we
+               // already have an existing method we want to call, so there's no need
+               // to create a new function object. We can even get away with assuming
+               // the method takes exactly one argument, since that happens to be true
+               // in every case, so we don't have to touch the arguments object. The
+               // only additional allocation required is the completion record, which
+               // has a stable shape and so hopefully should be cheap to allocate.
+
+               function tryCatch(fn, obj, arg) {
+                       try {
+                               return {
+                                       type: "normal",
+                                       arg: fn.call(obj, arg)
+                               };
+                       } catch (err) {
+                               return {
+                                       type: "throw",
+                                       arg: err
+                               };
+                       }
+               }
+
+               var GenStateSuspendedStart = "suspendedStart";
+               var GenStateSuspendedYield = "suspendedYield";
+               var GenStateExecuting = "executing";
+               var GenStateCompleted = "completed"; // Returning this object from the innerFn has the same effect as
+               // breaking out of the dispatch switch statement.
+
+               var ContinueSentinel = {}; // Dummy constructor functions that we use as the .constructor and
+               // .constructor.prototype properties for functions that return Generator
+               // objects. For full spec compliance, you may wish to configure your
+               // minifier not to mangle the names of these two functions.
+
+               function Generator() {}
+
+               function GeneratorFunction() {}
+
+               function GeneratorFunctionPrototype() {} // This is a polyfill for %IteratorPrototype% for environments that
+               // don't natively support it.
+
+
+               var IteratorPrototype = {};
+
+               IteratorPrototype[iteratorSymbol] = function () {
+                       return this;
+               };
+
+               var getProto = Object.getPrototypeOf;
+               var NativeIteratorPrototype = getProto && getProto(getProto(values([])));
+
+               if (NativeIteratorPrototype && NativeIteratorPrototype !== Op && hasOwn.call(NativeIteratorPrototype, iteratorSymbol)) {
+                       // This environment has a native %IteratorPrototype%; use it instead
+                       // of the polyfill.
+                       IteratorPrototype = NativeIteratorPrototype;
+               }
+
+               var Gp = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(IteratorPrototype);
+               GeneratorFunction.prototype = Gp.constructor = GeneratorFunctionPrototype;
+               GeneratorFunctionPrototype.constructor = GeneratorFunction;
+               GeneratorFunction.displayName = define(GeneratorFunctionPrototype, toStringTagSymbol, "GeneratorFunction"); // Helper for defining the .next, .throw, and .return methods of the
+               // Iterator interface in terms of a single ._invoke method.
+
+               function defineIteratorMethods(prototype) {
+                       ["next", "throw", "return"].forEach(function (method) {
+                               define(prototype, method, function (arg) {
+                                       return this._invoke(method, arg);
+                               });
+                       });
+               }
+
+               exports.isGeneratorFunction = function (genFun) {
+                       var ctor = typeof genFun === "function" && genFun.constructor;
+                       return ctor ? ctor === GeneratorFunction || // For the native GeneratorFunction constructor, the best we can
+                       // do is to check its .name property.
+                       (ctor.displayName || ctor.name) === "GeneratorFunction" : false;
+               };
+
+               exports.mark = function (genFun) {
+                       if (Object.setPrototypeOf) {
+                               Object.setPrototypeOf(genFun, GeneratorFunctionPrototype);
+                       } else {
+                               genFun.__proto__ = GeneratorFunctionPrototype;
+                               define(genFun, toStringTagSymbol, "GeneratorFunction");
+                       }
+
+                       genFun.prototype = Object.create(Gp);
+                       return genFun;
+               }; // Within the body of any async function, `await x` is transformed to
+               // `yield regeneratorRuntime.awrap(x)`, so that the runtime can test
+               // `hasOwn.call(value, "__await")` to determine if the yielded value is
+               // meant to be awaited.
+
+
+               exports.awrap = function (arg) {
+                       return {
+                               __await: arg
+                       };
+               };
+
+               function AsyncIterator(generator, PromiseImpl) {
+                       function invoke(method, arg, resolve, reject) {
+                               var record = tryCatch(generator[method], generator, arg);
+
+                               if (record.type === "throw") {
+                                       reject(record.arg);
+                               } else {
+                                       var result = record.arg;
+                                       var value = result.value;
+
+                                       if (value && typeof value === "object" && hasOwn.call(value, "__await")) {
+                                               return PromiseImpl.resolve(value.__await).then(function (value) {
+                                                       invoke("next", value, resolve, reject);
+                                               }, function (err) {
+                                                       invoke("throw", err, resolve, reject);
+                                               });
+                                       }
+
+                                       return PromiseImpl.resolve(value).then(function (unwrapped) {
+                                               // When a yielded Promise is resolved, its final value becomes
+                                               // the .value of the Promise<{value,done}> result for the
+                                               // current iteration.
+                                               result.value = unwrapped;
+                                               resolve(result);
+                                       }, function (error) {
+                                               // If a rejected Promise was yielded, throw the rejection back
+                                               // into the async generator function so it can be handled there.
+                                               return invoke("throw", error, resolve, reject);
+                                       });
+                               }
+                       }
+
+                       var previousPromise;
+
+                       function enqueue(method, arg) {
+                               function callInvokeWithMethodAndArg() {
+                                       return new PromiseImpl(function (resolve, reject) {
+                                               invoke(method, arg, resolve, reject);
+                                       });
+                               }
+
+                               return previousPromise = // If enqueue has been called before, then we want to wait until
+                               // all previous Promises have been resolved before calling invoke,
+                               // so that results are always delivered in the correct order. If
+                               // enqueue has not been called before, then it is important to
+                               // call invoke immediately, without waiting on a callback to fire,
+                               // so that the async generator function has the opportunity to do
+                               // any necessary setup in a predictable way. This predictability
+                               // is why the Promise constructor synchronously invokes its
+                               // executor callback, and why async functions synchronously
+                               // execute code before the first await. Since we implement simple
+                               // async functions in terms of async generators, it is especially
+                               // important to get this right, even though it requires care.
+                               previousPromise ? previousPromise.then(callInvokeWithMethodAndArg, // Avoid propagating failures to Promises returned by later
+                               // invocations of the iterator.
+                               callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg();
+                       } // Define the unified helper method that is used to implement .next,
+                       // .throw, and .return (see defineIteratorMethods).
+
+
+                       this._invoke = enqueue;
+               }
+
+               defineIteratorMethods(AsyncIterator.prototype);
+
+               AsyncIterator.prototype[asyncIteratorSymbol] = function () {
+                       return this;
+               };
+
+               exports.AsyncIterator = AsyncIterator; // Note that simple async functions are implemented on top of
+               // AsyncIterator objects; they just return a Promise for the value of
+               // the final result produced by the iterator.
+
+               exports.async = function (innerFn, outerFn, self, tryLocsList, PromiseImpl) {
+                       if (PromiseImpl === void 0) PromiseImpl = Promise;
+                       var iter = new AsyncIterator(wrap(innerFn, outerFn, self, tryLocsList), PromiseImpl);
+                       return exports.isGeneratorFunction(outerFn) ? iter // If outerFn is a generator, return the full iterator.
+                       : iter.next().then(function (result) {
+                               return result.done ? result.value : iter.next();
+                       });
+               };
+
+               function makeInvokeMethod(innerFn, self, context) {
+                       var state = GenStateSuspendedStart;
+                       return function invoke(method, arg) {
+                               if (state === GenStateExecuting) {
+                                       throw new Error("Generator is already running");
+                               }
+
+                               if (state === GenStateCompleted) {
+                                       if (method === "throw") {
+                                               throw arg;
+                                       } // Be forgiving, per 25.3.3.3.3 of the spec:
+                                       // https://people.mozilla.org/~jorendorff/es6-draft.html#sec-generatorresume
+
+
+                                       return doneResult();
+                               }
+
+                               context.method = method;
+                               context.arg = arg;
+
+                               while (true) {
+                                       var delegate = context.delegate;
+
+                                       if (delegate) {
+                                               var delegateResult = maybeInvokeDelegate(delegate, context);
+
+                                               if (delegateResult) {
+                                                       if (delegateResult === ContinueSentinel) continue;
+                                                       return delegateResult;
+                                               }
+                                       }
+
+                                       if (context.method === "next") {
+                                               // Setting context._sent for legacy support of Babel's
+                                               // function.sent implementation.
+                                               context.sent = context._sent = context.arg;
+                                       } else if (context.method === "throw") {
+                                               if (state === GenStateSuspendedStart) {
+                                                       state = GenStateCompleted;
+                                                       throw context.arg;
+                                               }
+
+                                               context.dispatchException(context.arg);
+                                       } else if (context.method === "return") {
+                                               context.abrupt("return", context.arg);
+                                       }
+
+                                       state = GenStateExecuting;
+                                       var record = tryCatch(innerFn, self, context);
+
+                                       if (record.type === "normal") {
+                                               // If an exception is thrown from innerFn, we leave state ===
+                                               // GenStateExecuting and loop back for another invocation.
+                                               state = context.done ? GenStateCompleted : GenStateSuspendedYield;
+
+                                               if (record.arg === ContinueSentinel) {
+                                                       continue;
+                                               }
+
+                                               return {
+                                                       value: record.arg,
+                                                       done: context.done
+                                               };
+                                       } else if (record.type === "throw") {
+                                               state = GenStateCompleted; // Dispatch the exception by looping back around to the
+                                               // context.dispatchException(context.arg) call above.
+
+                                               context.method = "throw";
+                                               context.arg = record.arg;
+                                       }
+                               }
+                       };
+               } // Call delegate.iterator[context.method](context.arg) and handle the
+               // result, either by returning a { value, done } result from the
+               // delegate iterator, or by modifying context.method and context.arg,
+               // setting context.delegate to null, and returning the ContinueSentinel.
+
+
+               function maybeInvokeDelegate(delegate, context) {
+                       var method = delegate.iterator[context.method];
+
+                       if (method === undefined$1) {
+                               // A .throw or .return when the delegate iterator has no .throw
+                               // method always terminates the yield* loop.
+                               context.delegate = null;
+
+                               if (context.method === "throw") {
+                                       // Note: ["return"] must be used for ES3 parsing compatibility.
+                                       if (delegate.iterator["return"]) {
+                                               // If the delegate iterator has a return method, give it a
+                                               // chance to clean up.
+                                               context.method = "return";
+                                               context.arg = undefined$1;
+                                               maybeInvokeDelegate(delegate, context);
+
+                                               if (context.method === "throw") {
+                                                       // If maybeInvokeDelegate(context) changed context.method from
+                                                       // "return" to "throw", let that override the TypeError below.
+                                                       return ContinueSentinel;
+                                               }
+                                       }
+
+                                       context.method = "throw";
+                                       context.arg = new TypeError("The iterator does not provide a 'throw' method");
+                               }
+
+                               return ContinueSentinel;
+                       }
+
+                       var record = tryCatch(method, delegate.iterator, context.arg);
+
+                       if (record.type === "throw") {
+                               context.method = "throw";
+                               context.arg = record.arg;
+                               context.delegate = null;
+                               return ContinueSentinel;
+                       }
+
+                       var info = record.arg;
+
+                       if (!info) {
+                               context.method = "throw";
+                               context.arg = new TypeError("iterator result is not an object");
+                               context.delegate = null;
+                               return ContinueSentinel;
+                       }
+
+                       if (info.done) {
+                               // Assign the result of the finished delegate to the temporary
+                               // variable specified by delegate.resultName (see delegateYield).
+                               context[delegate.resultName] = info.value; // Resume execution at the desired location (see delegateYield).
+
+                               context.next = delegate.nextLoc; // If context.method was "throw" but the delegate handled the
+                               // exception, let the outer generator proceed normally. If
+                               // context.method was "next", forget context.arg since it has been
+                               // "consumed" by the delegate iterator. If context.method was
+                               // "return", allow the original .return call to continue in the
+                               // outer generator.
+
+                               if (context.method !== "return") {
+                                       context.method = "next";
+                                       context.arg = undefined$1;
+                               }
+                       } else {
+                               // Re-yield the result returned by the delegate method.
+                               return info;
+                       } // The delegate iterator is finished, so forget it and continue with
+                       // the outer generator.
+
+
+                       context.delegate = null;
+                       return ContinueSentinel;
+               } // Define Generator.prototype.{next,throw,return} in terms of the
+               // unified ._invoke helper method.
+
+
+               defineIteratorMethods(Gp);
+               define(Gp, toStringTagSymbol, "Generator"); // A Generator should always return itself as the iterator object when the
+               // @@iterator function is called on it. Some browsers' implementations of the
+               // iterator prototype chain incorrectly implement this, causing the Generator
+               // object to not be returned from this call. This ensures that doesn't happen.
+               // See https://github.com/facebook/regenerator/issues/274 for more details.
+
+               Gp[iteratorSymbol] = function () {
+                       return this;
+               };
+
+               Gp.toString = function () {
+                       return "[object Generator]";
+               };
+
+               function pushTryEntry(locs) {
+                       var entry = {
+                               tryLoc: locs[0]
+                       };
+
+                       if (1 in locs) {
+                               entry.catchLoc = locs[1];
+                       }
+
+                       if (2 in locs) {
+                               entry.finallyLoc = locs[2];
+                               entry.afterLoc = locs[3];
+                       }
+
+                       this.tryEntries.push(entry);
+               }
+
+               function resetTryEntry(entry) {
+                       var record = entry.completion || {};
+                       record.type = "normal";
+                       delete record.arg;
+                       entry.completion = record;
+               }
+
+               function Context(tryLocsList) {
+                       // The root entry object (effectively a try statement without a catch
+                       // or a finally block) gives us a place to store values thrown from
+                       // locations where there is no enclosing try statement.
+                       this.tryEntries = [{
+                               tryLoc: "root"
+                       }];
+                       tryLocsList.forEach(pushTryEntry, this);
+                       this.reset(true);
+               }
+
+               exports.keys = function (object) {
+                       var keys = [];
+
+                       for (var key in object) {
+                               keys.push(key);
+                       }
+
+                       keys.reverse(); // Rather than returning an object with a next method, we keep
+                       // things simple and return the next function itself.
+
+                       return function next() {
+                               while (keys.length) {
+                                       var key = keys.pop();
+
+                                       if (key in object) {
+                                               next.value = key;
+                                               next.done = false;
+                                               return next;
+                                       }
+                               } // To avoid creating an additional object, we just hang the .value
+                               // and .done properties off the next function object itself. This
+                               // also ensures that the minifier will not anonymize the function.
+
+
+                               next.done = true;
+                               return next;
+                       };
+               };
+
+               function values(iterable) {
+                       if (iterable) {
+                               var iteratorMethod = iterable[iteratorSymbol];
+
+                               if (iteratorMethod) {
+                                       return iteratorMethod.call(iterable);
+                               }
+
+                               if (typeof iterable.next === "function") {
+                                       return iterable;
+                               }
+
+                               if (!isNaN(iterable.length)) {
+                                       var i = -1,
+                                                       next = function next() {
+                                               while (++i < iterable.length) {
+                                                       if (hasOwn.call(iterable, i)) {
+                                                               next.value = iterable[i];
+                                                               next.done = false;
+                                                               return next;
+                                                       }
+                                               }
+
+                                               next.value = undefined$1;
+                                               next.done = true;
+                                               return next;
+                                       };
+
+                                       return next.next = next;
+                               }
+                       } // Return an iterator with no values.
+
+
+                       return {
+                               next: doneResult
+                       };
+               }
+
+               exports.values = values;
+
+               function doneResult() {
+                       return {
+                               value: undefined$1,
+                               done: true
+                       };
+               }
+
+               Context.prototype = {
+                       constructor: Context,
+                       reset: function reset(skipTempReset) {
+                               this.prev = 0;
+                               this.next = 0; // Resetting context._sent for legacy support of Babel's
+                               // function.sent implementation.
+
+                               this.sent = this._sent = undefined$1;
+                               this.done = false;
+                               this.delegate = null;
+                               this.method = "next";
+                               this.arg = undefined$1;
+                               this.tryEntries.forEach(resetTryEntry);
+
+                               if (!skipTempReset) {
+                                       for (var name in this) {
+                                               // Not sure about the optimal order of these conditions:
+                                               if (name.charAt(0) === "t" && hasOwn.call(this, name) && !isNaN(+name.slice(1))) {
+                                                       this[name] = undefined$1;
+                                               }
+                                       }
+                               }
+                       },
+                       stop: function stop() {
+                               this.done = true;
+                               var rootEntry = this.tryEntries[0];
+                               var rootRecord = rootEntry.completion;
+
+                               if (rootRecord.type === "throw") {
+                                       throw rootRecord.arg;
+                               }
+
+                               return this.rval;
+                       },
+                       dispatchException: function dispatchException(exception) {
+                               if (this.done) {
+                                       throw exception;
+                               }
+
+                               var context = this;
+
+                               function handle(loc, caught) {
+                                       record.type = "throw";
+                                       record.arg = exception;
+                                       context.next = loc;
+
+                                       if (caught) {
+                                               // If the dispatched exception was caught by a catch block,
+                                               // then let that catch block handle the exception normally.
+                                               context.method = "next";
+                                               context.arg = undefined$1;
+                                       }
+
+                                       return !!caught;
+                               }
+
+                               for (var i = this.tryEntries.length - 1; i >= 0; --i) {
+                                       var entry = this.tryEntries[i];
+                                       var record = entry.completion;
+
+                                       if (entry.tryLoc === "root") {
+                                               // Exception thrown outside of any try block that could handle
+                                               // it, so set the completion value of the entire function to
+                                               // throw the exception.
+                                               return handle("end");
+                                       }
+
+                                       if (entry.tryLoc <= this.prev) {
+                                               var hasCatch = hasOwn.call(entry, "catchLoc");
+                                               var hasFinally = hasOwn.call(entry, "finallyLoc");
+
+                                               if (hasCatch && hasFinally) {
+                                                       if (this.prev < entry.catchLoc) {
+                                                               return handle(entry.catchLoc, true);
+                                                       } else if (this.prev < entry.finallyLoc) {
+                                                               return handle(entry.finallyLoc);
+                                                       }
+                                               } else if (hasCatch) {
+                                                       if (this.prev < entry.catchLoc) {
+                                                               return handle(entry.catchLoc, true);
+                                                       }
+                                               } else if (hasFinally) {
+                                                       if (this.prev < entry.finallyLoc) {
+                                                               return handle(entry.finallyLoc);
+                                                       }
+                                               } else {
+                                                       throw new Error("try statement without catch or finally");
+                                               }
+                                       }
+                               }
+                       },
+                       abrupt: function abrupt(type, arg) {
+                               for (var i = this.tryEntries.length - 1; i >= 0; --i) {
+                                       var entry = this.tryEntries[i];
+
+                                       if (entry.tryLoc <= this.prev && hasOwn.call(entry, "finallyLoc") && this.prev < entry.finallyLoc) {
+                                               var finallyEntry = entry;
+                                               break;
+                                       }
+                               }
+
+                               if (finallyEntry && (type === "break" || type === "continue") && finallyEntry.tryLoc <= arg && arg <= finallyEntry.finallyLoc) {
+                                       // Ignore the finally entry if control is not jumping to a
+                                       // location outside the try/catch block.
+                                       finallyEntry = null;
+                               }
+
+                               var record = finallyEntry ? finallyEntry.completion : {};
+                               record.type = type;
+                               record.arg = arg;
+
+                               if (finallyEntry) {
+                                       this.method = "next";
+                                       this.next = finallyEntry.finallyLoc;
+                                       return ContinueSentinel;
+                               }
+
+                               return this.complete(record);
+                       },
+                       complete: function complete(record, afterLoc) {
+                               if (record.type === "throw") {
+                                       throw record.arg;
+                               }
+
+                               if (record.type === "break" || record.type === "continue") {
+                                       this.next = record.arg;
+                               } else if (record.type === "return") {
+                                       this.rval = this.arg = record.arg;
+                                       this.method = "return";
+                                       this.next = "end";
+                               } else if (record.type === "normal" && afterLoc) {
+                                       this.next = afterLoc;
+                               }
+
+                               return ContinueSentinel;
+                       },
+                       finish: function finish(finallyLoc) {
+                               for (var i = this.tryEntries.length - 1; i >= 0; --i) {
+                                       var entry = this.tryEntries[i];
+
+                                       if (entry.finallyLoc === finallyLoc) {
+                                               this.complete(entry.completion, entry.afterLoc);
+                                               resetTryEntry(entry);
+                                               return ContinueSentinel;
+                                       }
+                               }
+                       },
+                       "catch": function _catch(tryLoc) {
+                               for (var i = this.tryEntries.length - 1; i >= 0; --i) {
+                                       var entry = this.tryEntries[i];
+
+                                       if (entry.tryLoc === tryLoc) {
+                                               var record = entry.completion;
+
+                                               if (record.type === "throw") {
+                                                       var thrown = record.arg;
+                                                       resetTryEntry(entry);
+                                               }
+
+                                               return thrown;
+                                       }
+                               } // The context.catch method must only be called with a location
+                               // argument that corresponds to a known catch block.
+
+
+                               throw new Error("illegal catch attempt");
+                       },
+                       delegateYield: function delegateYield(iterable, resultName, nextLoc) {
+                               this.delegate = {
+                                       iterator: values(iterable),
+                                       resultName: resultName,
+                                       nextLoc: nextLoc
+                               };
+
+                               if (this.method === "next") {
+                                       // Deliberately forget the last sent value so that we don't
+                                       // accidentally pass it on to the delegate.
+                                       this.arg = undefined$1;
+                               }
+
+                               return ContinueSentinel;
+                       }
+               }; // Regardless of whether this script is executing as a CommonJS module
+               // or not, return the runtime object so that we can declare the variable
+               // regeneratorRuntime in the outer scope, which allows this module to be
+               // injected easily by `bin/regenerator --include-runtime script.js`.
+
+               return exports;
+       }( // If this script is executing as a CommonJS module, use module.exports
+       // as the regeneratorRuntime namespace. Otherwise create a new empty
+       // object. Either way, the resulting object will be used to initialize
+       // the regeneratorRuntime variable at the top of this file.
+       typeof module === "object" ? module.exports : {});
+
+       try {
+               regeneratorRuntime = runtime;
+       } catch (accidentalStrictMode) {
+               // This module should not be running in strict mode, so the above
+               // assignment should always work unless something is misconfigured. Just
+               // in case runtime.js accidentally runs in strict mode, we can escape
+               // strict mode using a global Function call. This could conceivably fail
+               // if a Content Security Policy forbids using Function, but in that case
+               // the proper solution is to fix the accidental strict mode problem. If
+               // you've misconfigured your bundler to force strict mode and applied a
+               // CSP to forbid Function, and you're not willing to fix either of those
+               // problems, please detail your unique predicament in a GitHub issue.
+               Function("r", "regeneratorRuntime = r")(runtime);
+       }
+
+       var REVISION = '125';
        var MOUSE = {
                LEFT: 0,
                MIDDLE: 1,
        var StaticCopyUsage = 35046;
        var DynamicCopyUsage = 35050;
        var StreamCopyUsage = 35042;
-       var GLSL1 = "100";
-       var GLSL3 = "300 es";
+       var GLSL1 = '100';
+       var GLSL3 = '300 es';
+
+       function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
+               try {
+                       var info = gen[key](arg);
+                       var value = info.value;
+               } catch (error) {
+                       reject(error);
+                       return;
+               }
+
+               if (info.done) {
+                       resolve(value);
+               } else {
+                       Promise.resolve(value).then(_next, _throw);
+               }
+       }
+
+       function _asyncToGenerator(fn) {
+               return function () {
+                       var self = this,
+                                       args = arguments;
+                       return new Promise(function (resolve, reject) {
+                               var gen = fn.apply(self, args);
+
+                               function _next(value) {
+                                       asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
+                               }
+
+                               function _throw(err) {
+                                       asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
+                               }
+
+                               _next(undefined);
+                       });
+               };
+       }
+
+       function _defineProperties(target, props) {
+               for (var i = 0; i < props.length; i++) {
+                       var descriptor = props[i];
+                       descriptor.enumerable = descriptor.enumerable || false;
+                       descriptor.configurable = true;
+                       if ("value" in descriptor) descriptor.writable = true;
+                       Object.defineProperty(target, descriptor.key, descriptor);
+               }
+       }
+
+       function _createClass(Constructor, protoProps, staticProps) {
+               if (protoProps) _defineProperties(Constructor.prototype, protoProps);
+               if (staticProps) _defineProperties(Constructor, staticProps);
+               return Constructor;
+       }
+
+       function _inheritsLoose(subClass, superClass) {
+               subClass.prototype = Object.create(superClass.prototype);
+               subClass.prototype.constructor = subClass;
+               subClass.__proto__ = superClass;
+       }
+
+       function _assertThisInitialized(self) {
+               if (self === void 0) {
+                       throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
+               }
+
+               return self;
+       }
+
+       function _unsupportedIterableToArray(o, minLen) {
+               if (!o) return;
+               if (typeof o === "string") return _arrayLikeToArray(o, minLen);
+               var n = Object.prototype.toString.call(o).slice(8, -1);
+               if (n === "Object" && o.constructor) n = o.constructor.name;
+               if (n === "Map" || n === "Set") return Array.from(o);
+               if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
+       }
+
+       function _arrayLikeToArray(arr, len) {
+               if (len == null || len > arr.length) len = arr.length;
+
+               for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
+
+               return arr2;
+       }
+
+       function _createForOfIteratorHelperLoose(o, allowArrayLike) {
+               var it;
+
+               if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) {
+                       if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") {
+                               if (it) o = it;
+                               var i = 0;
+                               return function () {
+                                       if (i >= o.length) return {
+                                               done: true
+                                       };
+                                       return {
+                                               done: false,
+                                               value: o[i++]
+                                       };
+                               };
+                       }
+
+                       throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
+               }
+
+               it = o[Symbol.iterator]();
+               return it.next.bind(it);
+       }
 
        /**
         * https://github.com/mrdoob/eventdispatcher.js/
                lerp: function lerp(x, y, t) {
                        return (1 - t) * x + t * y;
                },
+               // http://www.rorydriscoll.com/2016/03/07/frame-rate-independent-damping-using-lerp/
+               damp: function damp(x, y, lambda, dt) {
+                       return MathUtils.lerp(x, y, 1 - Math.exp(-lambda * dt));
+               },
+               // https://www.desmos.com/calculator/vcsjnyz7x4
+               pingpong: function pingpong(x, length) {
+                       if (length === void 0) {
+                               length = 1;
+                       }
+
+                       return length - Math.abs(MathUtils.euclideanModulo(x, length * 2) - length);
+               },
                // http://en.wikipedia.org/wiki/Smoothstep
                smoothstep: function smoothstep(x, min, max) {
                        if (x <= min) return 0;
                }
        };
 
-       function _defineProperties(target, props) {
-               for (var i = 0; i < props.length; i++) {
-                       var descriptor = props[i];
-                       descriptor.enumerable = descriptor.enumerable || false;
-                       descriptor.configurable = true;
-                       if ("value" in descriptor) descriptor.writable = true;
-                       Object.defineProperty(target, descriptor.key, descriptor);
-               }
-       }
-
-       function _createClass(Constructor, protoProps, staticProps) {
-               if (protoProps) _defineProperties(Constructor.prototype, protoProps);
-               if (staticProps) _defineProperties(Constructor, staticProps);
-               return Constructor;
-       }
-
-       function _inheritsLoose(subClass, superClass) {
-               subClass.prototype = Object.create(superClass.prototype);
-               subClass.prototype.constructor = subClass;
-               subClass.__proto__ = superClass;
-       }
-
-       function _assertThisInitialized(self) {
-               if (self === void 0) {
-                       throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
-               }
-
-               return self;
-       }
-
        var Vector2 = /*#__PURE__*/function () {
                function Vector2(x, y) {
                        if (x === void 0) {
                        var c = Math.cos(rotation);
                        var s = Math.sin(rotation);
                        this.set(sx * c, sx * s, -sx * (c * cx + s * cy) + cx + tx, -sy * s, sy * c, -sy * (-s * cx + c * cy) + cy + ty, 0, 0, 1);
+                       return this;
                };
 
                _proto.scale = function scale(sx, sy) {
                        return uv;
                }
        });
-       Object.defineProperty(Texture.prototype, "needsUpdate", {
+       Object.defineProperty(Texture.prototype, 'needsUpdate', {
                set: function set(value) {
                        if (value === true) this.version++;
                }
                        return this;
                };
 
+               _proto.multiply = function multiply(v) {
+                       this.x *= v.x;
+                       this.y *= v.y;
+                       this.z *= v.z;
+                       this.w *= v.w;
+                       return this;
+               };
+
                _proto.multiplyScalar = function multiplyScalar(scalar) {
                        this.x *= scalar;
                        this.y *= scalar;
         * depthBuffer/stencilBuffer: Booleans to indicate if we should generate these buffers
        */
 
-       function WebGLRenderTarget(width, height, options) {
-               this.width = width;
-               this.height = height;
-               this.scissor = new Vector4(0, 0, width, height);
-               this.scissorTest = false;
-               this.viewport = new Vector4(0, 0, width, height);
-               options = options || {};
-               this.texture = new Texture(undefined, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding);
-               this.texture.image = {};
-               this.texture.image.width = width;
-               this.texture.image.height = height;
-               this.texture.generateMipmaps = options.generateMipmaps !== undefined ? options.generateMipmaps : false;
-               this.texture.minFilter = options.minFilter !== undefined ? options.minFilter : LinearFilter;
-               this.depthBuffer = options.depthBuffer !== undefined ? options.depthBuffer : true;
-               this.stencilBuffer = options.stencilBuffer !== undefined ? options.stencilBuffer : false;
-               this.depthTexture = options.depthTexture !== undefined ? options.depthTexture : null;
-       }
-
-       WebGLRenderTarget.prototype = Object.assign(Object.create(EventDispatcher.prototype), {
-               constructor: WebGLRenderTarget,
-               isWebGLRenderTarget: true,
-               setSize: function setSize(width, height) {
+       var WebGLRenderTarget = /*#__PURE__*/function (_EventDispatcher) {
+               _inheritsLoose(WebGLRenderTarget, _EventDispatcher);
+
+               function WebGLRenderTarget(width, height, options) {
+                       var _this;
+
+                       _this = _EventDispatcher.call(this) || this;
+                       Object.defineProperty(_assertThisInitialized(_this), 'isWebGLRenderTarget', {
+                               value: true
+                       });
+                       _this.width = width;
+                       _this.height = height;
+                       _this.scissor = new Vector4(0, 0, width, height);
+                       _this.scissorTest = false;
+                       _this.viewport = new Vector4(0, 0, width, height);
+                       options = options || {};
+                       _this.texture = new Texture(undefined, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding);
+                       _this.texture.image = {};
+                       _this.texture.image.width = width;
+                       _this.texture.image.height = height;
+                       _this.texture.generateMipmaps = options.generateMipmaps !== undefined ? options.generateMipmaps : false;
+                       _this.texture.minFilter = options.minFilter !== undefined ? options.minFilter : LinearFilter;
+                       _this.depthBuffer = options.depthBuffer !== undefined ? options.depthBuffer : true;
+                       _this.stencilBuffer = options.stencilBuffer !== undefined ? options.stencilBuffer : false;
+                       _this.depthTexture = options.depthTexture !== undefined ? options.depthTexture : null;
+                       return _this;
+               }
+
+               var _proto = WebGLRenderTarget.prototype;
+
+               _proto.setSize = function setSize(width, height) {
                        if (this.width !== width || this.height !== height) {
                                this.width = width;
                                this.height = height;
 
                        this.viewport.set(0, 0, width, height);
                        this.scissor.set(0, 0, width, height);
-               },
-               clone: function clone() {
+               };
+
+               _proto.clone = function clone() {
                        return new this.constructor().copy(this);
-               },
-               copy: function copy(source) {
+               };
+
+               _proto.copy = function copy(source) {
                        this.width = source.width;
                        this.height = source.height;
                        this.viewport.copy(source.viewport);
                        this.stencilBuffer = source.stencilBuffer;
                        this.depthTexture = source.depthTexture;
                        return this;
-               },
-               dispose: function dispose() {
+               };
+
+               _proto.dispose = function dispose() {
                        this.dispatchEvent({
                                type: 'dispose'
                        });
+               };
+
+               return WebGLRenderTarget;
+       }(EventDispatcher);
+
+       var WebGLMultisampleRenderTarget = /*#__PURE__*/function (_WebGLRenderTarget) {
+               _inheritsLoose(WebGLMultisampleRenderTarget, _WebGLRenderTarget);
+
+               function WebGLMultisampleRenderTarget(width, height, options) {
+                       var _this;
+
+                       _this = _WebGLRenderTarget.call(this, width, height, options) || this;
+                       Object.defineProperty(_assertThisInitialized(_this), 'isWebGLMultisampleRenderTarget', {
+                               value: true
+                       });
+                       _this.samples = 4;
+                       return _this;
                }
-       });
 
-       function WebGLMultisampleRenderTarget(width, height, options) {
-               WebGLRenderTarget.call(this, width, height, options);
-               this.samples = 4;
-       }
+               var _proto = WebGLMultisampleRenderTarget.prototype;
+
+               _proto.copy = function copy(source) {
+                       _WebGLRenderTarget.prototype.copy.call(this, source);
 
-       WebGLMultisampleRenderTarget.prototype = Object.assign(Object.create(WebGLRenderTarget.prototype), {
-               constructor: WebGLMultisampleRenderTarget,
-               isWebGLMultisampleRenderTarget: true,
-               copy: function copy(source) {
-                       WebGLRenderTarget.prototype.copy.call(this, source);
                        this.samples = source.samples;
                        return this;
-               }
-       });
+               };
+
+               return WebGLMultisampleRenderTarget;
+       }(WebGLRenderTarget);
 
        var Quaternion = /*#__PURE__*/function () {
                function Quaternion(x, y, z, w) {
                        return this;
                };
 
+               _proto.setFromMatrix3 = function setFromMatrix3(m) {
+                       var me = m.elements;
+                       this.set(me[0], me[3], me[6], 0, me[1], me[4], me[7], 0, me[2], me[5], me[8], 0, 0, 0, 0, 1);
+                       return this;
+               };
+
                _proto.extractBasis = function extractBasis(xAxis, yAxis, zAxis) {
                        xAxis.setFromMatrixColumn(this, 0);
                        yAxis.setFromMatrixColumn(this, 1);
                        }
 
                        if (object === this) {
-                               console.error("THREE.Object3D.add: object can't be added as a child of itself.", object);
+                               console.error('THREE.Object3D.add: object can\'t be added as a child of itself.', object);
                                return this;
                        }
 
                                this.children.push(object);
                                object.dispatchEvent(_addedEvent);
                        } else {
-                               console.error("THREE.Object3D.add: object not an instance of THREE.Object3D.", object);
+                               console.error('THREE.Object3D.add: object not an instance of THREE.Object3D.', object);
                        }
 
                        return this;
 
                        var m;
 
-                       if (m = /^((?:rgb|hsl)a?)\(\s*([^\)]*)\)/.exec(style)) {
+                       if (m = /^((?:rgb|hsl)a?)\(([^\)]*)\)/.exec(style)) {
                                // rgb / hsl
                                var color;
                                var name = m[1];
                                switch (name) {
                                        case 'rgb':
                                        case 'rgba':
-                                               if (color = /^(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec(components)) {
+                                               if (color = /^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(components)) {
                                                        // rgb(255,0,0) rgba(255,0,0,0.5)
                                                        this.r = Math.min(255, parseInt(color[1], 10)) / 255;
                                                        this.g = Math.min(255, parseInt(color[2], 10)) / 255;
                                                        this.b = Math.min(255, parseInt(color[3], 10)) / 255;
-                                                       handleAlpha(color[5]);
+                                                       handleAlpha(color[4]);
                                                        return this;
                                                }
 
-                                               if (color = /^(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec(components)) {
+                                               if (color = /^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(components)) {
                                                        // rgb(100%,0%,0%) rgba(100%,0%,0%,0.5)
                                                        this.r = Math.min(100, parseInt(color[1], 10)) / 100;
                                                        this.g = Math.min(100, parseInt(color[2], 10)) / 100;
                                                        this.b = Math.min(100, parseInt(color[3], 10)) / 100;
-                                                       handleAlpha(color[5]);
+                                                       handleAlpha(color[4]);
                                                        return this;
                                                }
 
 
                                        case 'hsl':
                                        case 'hsla':
-                                               if (color = /^([0-9]*\.?[0-9]+)\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec(components)) {
+                                               if (color = /^\s*(\d*\.?\d+)\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(components)) {
                                                        // hsl(120,50%,50%) hsla(120,50%,50%,0.5)
                                                        var h = parseFloat(color[1]) / 360;
                                                        var s = parseInt(color[2], 10) / 100;
                                                        var l = parseInt(color[3], 10) / 100;
-                                                       handleAlpha(color[5]);
+                                                       handleAlpha(color[4]);
                                                        return this.setHSL(h, s, l);
                                                }
 
                                                break;
                                }
-                       } else if (m = /^\#([A-Fa-f0-9]+)$/.exec(style)) {
+                       } else if (m = /^\#([A-Fa-f\d]+)$/.exec(style)) {
                                // hex color
                                var hex = m[1];
                                var size = hex.length;
                        return this;
                };
 
+               _proto.lerpColors = function lerpColors(color1, color2, alpha) {
+                       this.r = color1.r + (color2.r - color1.r) * alpha;
+                       this.g = color1.g + (color2.g - color1.g) * alpha;
+                       this.b = color1.b + (color2.b - color1.b) * alpha;
+                       return this;
+               };
+
                _proto.lerpHSL = function lerpHSL(color, alpha) {
                        this.getHSL(_hslA);
                        color.getHSL(_hslB);
                                var newValue = values[key];
 
                                if (newValue === undefined) {
-                                       console.warn("THREE.Material: '" + key + "' parameter is undefined.");
+                                       console.warn('THREE.Material: \'' + key + '\' parameter is undefined.');
                                        continue;
                                } // for backward compatability if shading is set in the constructor
 
                                var currentValue = this[key];
 
                                if (currentValue === undefined) {
-                                       console.warn("THREE." + this.type + ": '" + key + "' is not a property of this material.");
+                                       console.warn('THREE.' + this.type + ': \'' + key + '\' is not a property of this material.');
                                        continue;
                                }
 
        Float64BufferAttribute.prototype = Object.create(BufferAttribute.prototype);
        Float64BufferAttribute.prototype.constructor = Float64BufferAttribute; //
 
-       var DirectGeometry = /*#__PURE__*/function () {
-               function DirectGeometry() {
-                       this.vertices = [];
-                       this.normals = [];
-                       this.colors = [];
-                       this.uvs = [];
-                       this.uvs2 = [];
-                       this.groups = [];
-                       this.morphTargets = {};
-                       this.skinWeights = [];
-                       this.skinIndices = []; // this.lineDistances = [];
-
-                       this.boundingBox = null;
-                       this.boundingSphere = null; // update flags
-
-                       this.verticesNeedUpdate = false;
-                       this.normalsNeedUpdate = false;
-                       this.colorsNeedUpdate = false;
-                       this.uvsNeedUpdate = false;
-                       this.groupsNeedUpdate = false;
-               }
-
-               var _proto = DirectGeometry.prototype;
-
-               _proto.computeGroups = function computeGroups(geometry) {
-                       var groups = [];
-                       var group, i;
-                       var materialIndex = undefined;
-                       var faces = geometry.faces;
-
-                       for (i = 0; i < faces.length; i++) {
-                               var face = faces[i]; // materials
-
-                               if (face.materialIndex !== materialIndex) {
-                                       materialIndex = face.materialIndex;
-
-                                       if (group !== undefined) {
-                                               group.count = i * 3 - group.start;
-                                               groups.push(group);
-                                       }
-
-                                       group = {
-                                               start: i * 3,
-                                               materialIndex: materialIndex
-                                       };
-                               }
-                       }
-
-                       if (group !== undefined) {
-                               group.count = i * 3 - group.start;
-                               groups.push(group);
-                       }
-
-                       this.groups = groups;
-               };
-
-               _proto.fromGeometry = function fromGeometry(geometry) {
-                       var faces = geometry.faces;
-                       var vertices = geometry.vertices;
-                       var faceVertexUvs = geometry.faceVertexUvs;
-                       var hasFaceVertexUv = faceVertexUvs[0] && faceVertexUvs[0].length > 0;
-                       var hasFaceVertexUv2 = faceVertexUvs[1] && faceVertexUvs[1].length > 0; // morphs
-
-                       var morphTargets = geometry.morphTargets;
-                       var morphTargetsLength = morphTargets.length;
-                       var morphTargetsPosition;
-
-                       if (morphTargetsLength > 0) {
-                               morphTargetsPosition = [];
-
-                               for (var i = 0; i < morphTargetsLength; i++) {
-                                       morphTargetsPosition[i] = {
-                                               name: morphTargets[i].name,
-                                               data: []
-                                       };
-                               }
-
-                               this.morphTargets.position = morphTargetsPosition;
-                       }
-
-                       var morphNormals = geometry.morphNormals;
-                       var morphNormalsLength = morphNormals.length;
-                       var morphTargetsNormal;
-
-                       if (morphNormalsLength > 0) {
-                               morphTargetsNormal = [];
-
-                               for (var _i = 0; _i < morphNormalsLength; _i++) {
-                                       morphTargetsNormal[_i] = {
-                                               name: morphNormals[_i].name,
-                                               data: []
-                                       };
-                               }
-
-                               this.morphTargets.normal = morphTargetsNormal;
-                       } // skins
-
-
-                       var skinIndices = geometry.skinIndices;
-                       var skinWeights = geometry.skinWeights;
-                       var hasSkinIndices = skinIndices.length === vertices.length;
-                       var hasSkinWeights = skinWeights.length === vertices.length; //
-
-                       if (vertices.length > 0 && faces.length === 0) {
-                               console.error('THREE.DirectGeometry: Faceless geometries are not supported.');
-                       }
-
-                       for (var _i2 = 0; _i2 < faces.length; _i2++) {
-                               var face = faces[_i2];
-                               this.vertices.push(vertices[face.a], vertices[face.b], vertices[face.c]);
-                               var vertexNormals = face.vertexNormals;
-
-                               if (vertexNormals.length === 3) {
-                                       this.normals.push(vertexNormals[0], vertexNormals[1], vertexNormals[2]);
-                               } else {
-                                       var normal = face.normal;
-                                       this.normals.push(normal, normal, normal);
-                               }
-
-                               var vertexColors = face.vertexColors;
-
-                               if (vertexColors.length === 3) {
-                                       this.colors.push(vertexColors[0], vertexColors[1], vertexColors[2]);
-                               } else {
-                                       var color = face.color;
-                                       this.colors.push(color, color, color);
-                               }
-
-                               if (hasFaceVertexUv === true) {
-                                       var vertexUvs = faceVertexUvs[0][_i2];
-
-                                       if (vertexUvs !== undefined) {
-                                               this.uvs.push(vertexUvs[0], vertexUvs[1], vertexUvs[2]);
-                                       } else {
-                                               console.warn('THREE.DirectGeometry.fromGeometry(): Undefined vertexUv ', _i2);
-                                               this.uvs.push(new Vector2(), new Vector2(), new Vector2());
-                                       }
-                               }
-
-                               if (hasFaceVertexUv2 === true) {
-                                       var _vertexUvs = faceVertexUvs[1][_i2];
-
-                                       if (_vertexUvs !== undefined) {
-                                               this.uvs2.push(_vertexUvs[0], _vertexUvs[1], _vertexUvs[2]);
-                                       } else {
-                                               console.warn('THREE.DirectGeometry.fromGeometry(): Undefined vertexUv2 ', _i2);
-                                               this.uvs2.push(new Vector2(), new Vector2(), new Vector2());
-                                       }
-                               } // morphs
-
-
-                               for (var j = 0; j < morphTargetsLength; j++) {
-                                       var morphTarget = morphTargets[j].vertices;
-                                       morphTargetsPosition[j].data.push(morphTarget[face.a], morphTarget[face.b], morphTarget[face.c]);
-                               }
-
-                               for (var _j = 0; _j < morphNormalsLength; _j++) {
-                                       var morphNormal = morphNormals[_j].vertexNormals[_i2];
-
-                                       morphTargetsNormal[_j].data.push(morphNormal.a, morphNormal.b, morphNormal.c);
-                               } // skins
-
-
-                               if (hasSkinIndices) {
-                                       this.skinIndices.push(skinIndices[face.a], skinIndices[face.b], skinIndices[face.c]);
-                               }
-
-                               if (hasSkinWeights) {
-                                       this.skinWeights.push(skinWeights[face.a], skinWeights[face.b], skinWeights[face.c]);
-                               }
-                       }
-
-                       this.computeGroups(geometry);
-                       this.verticesNeedUpdate = geometry.verticesNeedUpdate;
-                       this.normalsNeedUpdate = geometry.normalsNeedUpdate;
-                       this.colorsNeedUpdate = geometry.colorsNeedUpdate;
-                       this.uvsNeedUpdate = geometry.uvsNeedUpdate;
-                       this.groupsNeedUpdate = geometry.groupsNeedUpdate;
-
-                       if (geometry.boundingSphere !== null) {
-                               this.boundingSphere = geometry.boundingSphere.clone();
-                       }
-
-                       if (geometry.boundingBox !== null) {
-                               this.boundingBox = geometry.boundingBox.clone();
-                       }
-
-                       return this;
-               };
-
-               return DirectGeometry;
-       }();
-
        function arrayMax(array) {
                if (array.length === 0) return -Infinity;
                var max = array[0];
                return new TYPED_ARRAYS[type](buffer);
        }
 
-       var _bufferGeometryId = 1; // BufferGeometry uses odd numbers as Id
+       var _id = 0;
 
        var _m1$2 = new Matrix4();
 
 
        function BufferGeometry() {
                Object.defineProperty(this, 'id', {
-                       value: _bufferGeometryId += 2
+                       value: _id++
                });
                this.uuid = MathUtils.generateUUID();
                this.name = '';
                        this.translate(_offset.x, _offset.y, _offset.z);
                        return this;
                },
-               setFromObject: function setFromObject(object) {
-                       // console.log( 'THREE.BufferGeometry.setFromObject(). Converting', object, this );
-                       var geometry = object.geometry;
-
-                       if (object.isPoints || object.isLine) {
-                               var positions = new Float32BufferAttribute(geometry.vertices.length * 3, 3);
-                               var colors = new Float32BufferAttribute(geometry.colors.length * 3, 3);
-                               this.setAttribute('position', positions.copyVector3sArray(geometry.vertices));
-                               this.setAttribute('color', colors.copyColorsArray(geometry.colors));
-
-                               if (geometry.lineDistances && geometry.lineDistances.length === geometry.vertices.length) {
-                                       var lineDistances = new Float32BufferAttribute(geometry.lineDistances.length, 1);
-                                       this.setAttribute('lineDistance', lineDistances.copyArray(geometry.lineDistances));
-                               }
-
-                               if (geometry.boundingSphere !== null) {
-                                       this.boundingSphere = geometry.boundingSphere.clone();
-                               }
-
-                               if (geometry.boundingBox !== null) {
-                                       this.boundingBox = geometry.boundingBox.clone();
-                               }
-                       } else if (object.isMesh) {
-                               if (geometry && geometry.isGeometry) {
-                                       this.fromGeometry(geometry);
-                               }
-                       }
-
-                       return this;
-               },
                setFromPoints: function setFromPoints(points) {
                        var position = [];
 
                        this.setAttribute('position', new Float32BufferAttribute(position, 3));
                        return this;
                },
-               updateFromObject: function updateFromObject(object) {
-                       var geometry = object.geometry;
-
-                       if (object.isMesh) {
-                               var direct = geometry.__directGeometry;
-
-                               if (geometry.elementsNeedUpdate === true) {
-                                       direct = undefined;
-                                       geometry.elementsNeedUpdate = false;
-                               }
-
-                               if (direct === undefined) {
-                                       return this.fromGeometry(geometry);
-                               }
-
-                               direct.verticesNeedUpdate = geometry.verticesNeedUpdate;
-                               direct.normalsNeedUpdate = geometry.normalsNeedUpdate;
-                               direct.colorsNeedUpdate = geometry.colorsNeedUpdate;
-                               direct.uvsNeedUpdate = geometry.uvsNeedUpdate;
-                               direct.groupsNeedUpdate = geometry.groupsNeedUpdate;
-                               geometry.verticesNeedUpdate = false;
-                               geometry.normalsNeedUpdate = false;
-                               geometry.colorsNeedUpdate = false;
-                               geometry.uvsNeedUpdate = false;
-                               geometry.groupsNeedUpdate = false;
-                               geometry = direct;
-                       }
-
-                       if (geometry.verticesNeedUpdate === true) {
-                               var attribute = this.attributes.position;
-
-                               if (attribute !== undefined) {
-                                       attribute.copyVector3sArray(geometry.vertices);
-                                       attribute.needsUpdate = true;
-                               }
-
-                               geometry.verticesNeedUpdate = false;
-                       }
-
-                       if (geometry.normalsNeedUpdate === true) {
-                               var _attribute = this.attributes.normal;
-
-                               if (_attribute !== undefined) {
-                                       _attribute.copyVector3sArray(geometry.normals);
-
-                                       _attribute.needsUpdate = true;
-                               }
-
-                               geometry.normalsNeedUpdate = false;
-                       }
-
-                       if (geometry.colorsNeedUpdate === true) {
-                               var _attribute2 = this.attributes.color;
-
-                               if (_attribute2 !== undefined) {
-                                       _attribute2.copyColorsArray(geometry.colors);
-
-                                       _attribute2.needsUpdate = true;
-                               }
-
-                               geometry.colorsNeedUpdate = false;
-                       }
-
-                       if (geometry.uvsNeedUpdate) {
-                               var _attribute3 = this.attributes.uv;
-
-                               if (_attribute3 !== undefined) {
-                                       _attribute3.copyVector2sArray(geometry.uvs);
-
-                                       _attribute3.needsUpdate = true;
-                               }
-
-                               geometry.uvsNeedUpdate = false;
-                       }
-
-                       if (geometry.lineDistancesNeedUpdate) {
-                               var _attribute4 = this.attributes.lineDistance;
-
-                               if (_attribute4 !== undefined) {
-                                       _attribute4.copyArray(geometry.lineDistances);
-
-                                       _attribute4.needsUpdate = true;
-                               }
-
-                               geometry.lineDistancesNeedUpdate = false;
-                       }
-
-                       if (geometry.groupsNeedUpdate) {
-                               geometry.computeGroups(object.geometry);
-                               this.groups = geometry.groups;
-                               geometry.groupsNeedUpdate = false;
-                       }
-
-                       return this;
-               },
-               fromGeometry: function fromGeometry(geometry) {
-                       geometry.__directGeometry = new DirectGeometry().fromGeometry(geometry);
-                       return this.fromDirectGeometry(geometry.__directGeometry);
-               },
-               fromDirectGeometry: function fromDirectGeometry(geometry) {
-                       var positions = new Float32Array(geometry.vertices.length * 3);
-                       this.setAttribute('position', new BufferAttribute(positions, 3).copyVector3sArray(geometry.vertices));
-
-                       if (geometry.normals.length > 0) {
-                               var normals = new Float32Array(geometry.normals.length * 3);
-                               this.setAttribute('normal', new BufferAttribute(normals, 3).copyVector3sArray(geometry.normals));
-                       }
-
-                       if (geometry.colors.length > 0) {
-                               var colors = new Float32Array(geometry.colors.length * 3);
-                               this.setAttribute('color', new BufferAttribute(colors, 3).copyColorsArray(geometry.colors));
-                       }
-
-                       if (geometry.uvs.length > 0) {
-                               var uvs = new Float32Array(geometry.uvs.length * 2);
-                               this.setAttribute('uv', new BufferAttribute(uvs, 2).copyVector2sArray(geometry.uvs));
-                       }
-
-                       if (geometry.uvs2.length > 0) {
-                               var uvs2 = new Float32Array(geometry.uvs2.length * 2);
-                               this.setAttribute('uv2', new BufferAttribute(uvs2, 2).copyVector2sArray(geometry.uvs2));
-                       } // groups
-
-
-                       this.groups = geometry.groups; // morphs
-
-                       for (var name in geometry.morphTargets) {
-                               var array = [];
-                               var morphTargets = geometry.morphTargets[name];
-
-                               for (var i = 0, l = morphTargets.length; i < l; i++) {
-                                       var morphTarget = morphTargets[i];
-                                       var attribute = new Float32BufferAttribute(morphTarget.data.length * 3, 3);
-                                       attribute.name = morphTarget.name;
-                                       array.push(attribute.copyVector3sArray(morphTarget.data));
-                               }
-
-                               this.morphAttributes[name] = array;
-                       } // skinning
-
-
-                       if (geometry.skinIndices.length > 0) {
-                               var skinIndices = new Float32BufferAttribute(geometry.skinIndices.length * 4, 4);
-                               this.setAttribute('skinIndex', skinIndices.copyVector4sArray(geometry.skinIndices));
-                       }
-
-                       if (geometry.skinWeights.length > 0) {
-                               var skinWeights = new Float32BufferAttribute(geometry.skinWeights.length * 4, 4);
-                               this.setAttribute('skinWeight', skinWeights.copyVector4sArray(geometry.skinWeights));
-                       } //
-
-
-                       if (geometry.boundingSphere !== null) {
-                               this.boundingSphere = geometry.boundingSphere.clone();
-                       }
-
-                       if (geometry.boundingBox !== null) {
-                               this.boundingBox = geometry.boundingBox.clone();
-                       }
-
-                       return this;
-               },
                computeBoundingBox: function computeBoundingBox() {
                        if (this.boundingBox === null) {
                                this.boundingBox = new Box3();
                },
                computeFaceNormals: function computeFaceNormals() {// backwards compatibility
                },
+               computeTangents: function computeTangents() {
+                       var index = this.index;
+                       var attributes = this.attributes; // based on http://www.terathon.com/code/tangent.html
+                       // (per vertex tangents)
+
+                       if (index === null || attributes.position === undefined || attributes.normal === undefined || attributes.uv === undefined) {
+                               console.error('THREE.BufferGeometry: .computeTangents() failed. Missing required attributes (index, position, normal or uv)');
+                               return;
+                       }
+
+                       var indices = index.array;
+                       var positions = attributes.position.array;
+                       var normals = attributes.normal.array;
+                       var uvs = attributes.uv.array;
+                       var nVertices = positions.length / 3;
+
+                       if (attributes.tangent === undefined) {
+                               this.setAttribute('tangent', new BufferAttribute(new Float32Array(4 * nVertices), 4));
+                       }
+
+                       var tangents = attributes.tangent.array;
+                       var tan1 = [],
+                                       tan2 = [];
+
+                       for (var i = 0; i < nVertices; i++) {
+                               tan1[i] = new Vector3();
+                               tan2[i] = new Vector3();
+                       }
+
+                       var vA = new Vector3(),
+                                       vB = new Vector3(),
+                                       vC = new Vector3(),
+                                       uvA = new Vector2(),
+                                       uvB = new Vector2(),
+                                       uvC = new Vector2(),
+                                       sdir = new Vector3(),
+                                       tdir = new Vector3();
+
+                       function handleTriangle(a, b, c) {
+                               vA.fromArray(positions, a * 3);
+                               vB.fromArray(positions, b * 3);
+                               vC.fromArray(positions, c * 3);
+                               uvA.fromArray(uvs, a * 2);
+                               uvB.fromArray(uvs, b * 2);
+                               uvC.fromArray(uvs, c * 2);
+                               vB.sub(vA);
+                               vC.sub(vA);
+                               uvB.sub(uvA);
+                               uvC.sub(uvA);
+                               var r = 1.0 / (uvB.x * uvC.y - uvC.x * uvB.y); // silently ignore degenerate uv triangles having coincident or colinear vertices
+
+                               if (!isFinite(r)) return;
+                               sdir.copy(vB).multiplyScalar(uvC.y).addScaledVector(vC, -uvB.y).multiplyScalar(r);
+                               tdir.copy(vC).multiplyScalar(uvB.x).addScaledVector(vB, -uvC.x).multiplyScalar(r);
+                               tan1[a].add(sdir);
+                               tan1[b].add(sdir);
+                               tan1[c].add(sdir);
+                               tan2[a].add(tdir);
+                               tan2[b].add(tdir);
+                               tan2[c].add(tdir);
+                       }
+
+                       var groups = this.groups;
+
+                       if (groups.length === 0) {
+                               groups = [{
+                                       start: 0,
+                                       count: indices.length
+                               }];
+                       }
+
+                       for (var _i3 = 0, il = groups.length; _i3 < il; ++_i3) {
+                               var group = groups[_i3];
+                               var start = group.start;
+                               var count = group.count;
+
+                               for (var j = start, jl = start + count; j < jl; j += 3) {
+                                       handleTriangle(indices[j + 0], indices[j + 1], indices[j + 2]);
+                               }
+                       }
+
+                       var tmp = new Vector3(),
+                                       tmp2 = new Vector3();
+                       var n = new Vector3(),
+                                       n2 = new Vector3();
+
+                       function handleVertex(v) {
+                               n.fromArray(normals, v * 3);
+                               n2.copy(n);
+                               var t = tan1[v]; // Gram-Schmidt orthogonalize
+
+                               tmp.copy(t);
+                               tmp.sub(n.multiplyScalar(n.dot(t))).normalize(); // Calculate handedness
+
+                               tmp2.crossVectors(n2, t);
+                               var test = tmp2.dot(tan2[v]);
+                               var w = test < 0.0 ? -1.0 : 1.0;
+                               tangents[v * 4] = tmp.x;
+                               tangents[v * 4 + 1] = tmp.y;
+                               tangents[v * 4 + 2] = tmp.z;
+                               tangents[v * 4 + 3] = w;
+                       }
+
+                       for (var _i4 = 0, _il3 = groups.length; _i4 < _il3; ++_i4) {
+                               var _group = groups[_i4];
+                               var _start = _group.start;
+                               var _count = _group.count;
+
+                               for (var _j = _start, _jl = _start + _count; _j < _jl; _j += 3) {
+                                       handleVertex(indices[_j + 0]);
+                                       handleVertex(indices[_j + 1]);
+                                       handleVertex(indices[_j + 2]);
+                               }
+                       }
+               },
                computeVertexNormals: function computeVertexNormals() {
                        var index = this.index;
                        var positionAttribute = this.getAttribute('position');
                                                ab = new Vector3(); // indexed elements
 
                                if (index) {
-                                       for (var _i3 = 0, _il3 = index.count; _i3 < _il3; _i3 += 3) {
-                                               var vA = index.getX(_i3 + 0);
-                                               var vB = index.getX(_i3 + 1);
-                                               var vC = index.getX(_i3 + 2);
+                                       for (var _i5 = 0, _il4 = index.count; _i5 < _il4; _i5 += 3) {
+                                               var vA = index.getX(_i5 + 0);
+                                               var vB = index.getX(_i5 + 1);
+                                               var vC = index.getX(_i5 + 2);
                                                pA.fromBufferAttribute(positionAttribute, vA);
                                                pB.fromBufferAttribute(positionAttribute, vB);
                                                pC.fromBufferAttribute(positionAttribute, vC);
                                        }
                                } else {
                                        // non-indexed elements (unconnected triangle soup)
-                                       for (var _i4 = 0, _il4 = positionAttribute.count; _i4 < _il4; _i4 += 3) {
-                                               pA.fromBufferAttribute(positionAttribute, _i4 + 0);
-                                               pB.fromBufferAttribute(positionAttribute, _i4 + 1);
-                                               pC.fromBufferAttribute(positionAttribute, _i4 + 2);
+                                       for (var _i6 = 0, _il5 = positionAttribute.count; _i6 < _il5; _i6 += 3) {
+                                               pA.fromBufferAttribute(positionAttribute, _i6 + 0);
+                                               pB.fromBufferAttribute(positionAttribute, _i6 + 1);
+                                               pC.fromBufferAttribute(positionAttribute, _i6 + 2);
                                                cb.subVectors(pC, pB);
                                                ab.subVectors(pA, pB);
                                                cb.cross(ab);
-                                               normalAttribute.setXYZ(_i4 + 0, cb.x, cb.y, cb.z);
-                                               normalAttribute.setXYZ(_i4 + 1, cb.x, cb.y, cb.z);
-                                               normalAttribute.setXYZ(_i4 + 2, cb.x, cb.y, cb.z);
+                                               normalAttribute.setXYZ(_i6 + 0, cb.x, cb.y, cb.z);
+                                               normalAttribute.setXYZ(_i6 + 1, cb.x, cb.y, cb.z);
+                                               normalAttribute.setXYZ(_i6 + 2, cb.x, cb.y, cb.z);
                                        }
                                }
 
 
 
                        if (this.index === null) {
-                               console.warn('THREE.BufferGeometry.toNonIndexed(): Geometry is already non-indexed.');
+                               console.warn('THREE.BufferGeometry.toNonIndexed(): BufferGeometry is already non-indexed.');
                                return this;
                        }
 
                                var morphAttribute = morphAttributes[_name]; // morphAttribute: array of Float32BufferAttributes
 
                                for (var i = 0, il = morphAttribute.length; i < il; i++) {
-                                       var _attribute5 = morphAttribute[i];
+                                       var _attribute = morphAttribute[i];
 
-                                       var _newAttribute = convertBufferAttribute(_attribute5, indices);
+                                       var _newAttribute = convertBufferAttribute(_attribute, indices);
 
                                        morphArray.push(_newAttribute);
                                }
 
                        var groups = this.groups;
 
-                       for (var _i5 = 0, l = groups.length; _i5 < l; _i5++) {
-                               var group = groups[_i5];
+                       for (var _i7 = 0, l = groups.length; _i7 < l; _i7++) {
+                               var group = groups[_i7];
                                geometry2.addGroup(group.start, group.count, group.materialIndex);
                        }
 
                                var array = [];
 
                                for (var i = 0, il = attributeArray.length; i < il; i++) {
-                                       var _attribute6 = attributeArray[i];
+                                       var _attribute2 = attributeArray[i];
 
-                                       var _attributeData = _attribute6.toJSON(data.data);
+                                       var _attributeData = _attribute2.toJSON(data.data);
 
-                                       if (_attribute6.name !== '') _attributeData.name = _attribute6.name;
+                                       if (_attribute2.name !== '') _attributeData.name = _attribute2.name;
                                        array.push(_attributeData);
                                }
 
 
                        var groups = source.groups;
 
-                       for (var _i6 = 0, _l = groups.length; _i6 < _l; _i6++) {
-                               var group = groups[_i6];
+                       for (var _i8 = 0, _l = groups.length; _i8 < _l; _i8++) {
+                               var group = groups[_i8];
                                this.addGroup(group.start, group.count, group.materialIndex);
                        } // bounding box
 
        var _intersectionPointWorld = new Vector3();
 
        function Mesh(geometry, material) {
+               if (geometry === void 0) {
+                       geometry = new BufferGeometry();
+               }
+
+               if (material === void 0) {
+                       material = new MeshBasicMaterial();
+               }
+
                Object3D.call(this);
                this.type = 'Mesh';
-               this.geometry = geometry !== undefined ? geometry : new BufferGeometry();
-               this.material = material !== undefined ? material : new MeshBasicMaterial();
+               this.geometry = geometry;
+               this.material = material;
                this.updateMorphTargets();
        }
 
                                        }
                                }
                        } else if (geometry.isGeometry) {
-                               var isMultiMaterial = Array.isArray(material);
-                               var vertices = geometry.vertices;
-                               var faces = geometry.faces;
-                               var uvs;
-                               var faceVertexUvs = geometry.faceVertexUvs[0];
-                               if (faceVertexUvs.length > 0) uvs = faceVertexUvs;
-
-                               for (var f = 0, fl = faces.length; f < fl; f++) {
-                                       var face = faces[f];
-                                       var faceMaterial = isMultiMaterial ? material[face.materialIndex] : material;
-                                       if (faceMaterial === undefined) continue;
-                                       var fvA = vertices[face.a];
-                                       var fvB = vertices[face.b];
-                                       var fvC = vertices[face.c];
-                                       intersection = checkIntersection(this, faceMaterial, raycaster, _ray, fvA, fvB, fvC, _intersectionPoint);
-
-                                       if (intersection) {
-                                               if (uvs && uvs[f]) {
-                                                       var uvs_f = uvs[f];
-
-                                                       _uvA.copy(uvs_f[0]);
-
-                                                       _uvB.copy(uvs_f[1]);
-
-                                                       _uvC.copy(uvs_f[2]);
-
-                                                       intersection.uv = Triangle.getUV(_intersectionPoint, fvA, fvB, fvC, _uvA, _uvB, _uvC, new Vector2());
-                                               }
-
-                                               intersection.face = face;
-                                               intersection.faceIndex = f;
-                                               intersects.push(intersection);
-                                       }
-                               }
+                               console.error('THREE.Mesh.raycast() no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.');
                        }
                }
        });
                return intersection;
        }
 
-       var BoxBufferGeometry = /*#__PURE__*/function (_BufferGeometry) {
-               _inheritsLoose(BoxBufferGeometry, _BufferGeometry);
+       var BoxGeometry = /*#__PURE__*/function (_BufferGeometry) {
+               _inheritsLoose(BoxGeometry, _BufferGeometry);
 
-               function BoxBufferGeometry(width, height, depth, widthSegments, heightSegments, depthSegments) {
+               function BoxGeometry(width, height, depth, widthSegments, heightSegments, depthSegments) {
                        var _this;
 
                        if (width === void 0) {
                        }
 
                        _this = _BufferGeometry.call(this) || this;
-                       _this.type = 'BoxBufferGeometry';
+                       _this.type = 'BoxGeometry';
                        _this.parameters = {
                                width: width,
                                height: height,
                        return _this;
                }
 
-               return BoxBufferGeometry;
+               return BoxGeometry;
        }(BufferGeometry);
 
        /**
                 * Values for focal length and film gauge must have the same unit.
                 */
                setFocalLength: function setFocalLength(focalLength) {
-                       // see http://www.bobatkins.com/photography/technical/field_of_view.html
+                       /** see {@link http://www.bobatkins.com/photography/technical/field_of_view.html} */
                        var vExtentSlope = 0.5 * this.getFilmHeight() / focalLength;
                        this.fov = MathUtils.RAD2DEG * 2 * Math.atan(vExtentSlope);
                        this.updateProjectionMatrix();
                }
        });
 
-       function WebGLCubeRenderTarget(size, options, dummy) {
-               if (Number.isInteger(options)) {
-                       console.warn('THREE.WebGLCubeRenderTarget: constructor signature is now WebGLCubeRenderTarget( size, options )');
-                       options = dummy;
+       var WebGLCubeRenderTarget = /*#__PURE__*/function (_WebGLRenderTarget) {
+               _inheritsLoose(WebGLCubeRenderTarget, _WebGLRenderTarget);
+
+               function WebGLCubeRenderTarget(size, options, dummy) {
+                       var _this;
+
+                       if (Number.isInteger(options)) {
+                               console.warn('THREE.WebGLCubeRenderTarget: constructor signature is now WebGLCubeRenderTarget( size, options )');
+                               options = dummy;
+                       }
+
+                       _this = _WebGLRenderTarget.call(this, size, size, options) || this;
+                       Object.defineProperty(_assertThisInitialized(_this), 'isWebGLCubeRenderTarget', {
+                               value: true
+                       });
+                       options = options || {};
+                       _this.texture = new CubeTexture(undefined, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding);
+                       _this.texture._needsFlipEnvMap = false;
+                       return _this;
                }
 
-               WebGLRenderTarget.call(this, size, size, options);
-               options = options || {};
-               this.texture = new CubeTexture(undefined, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding);
-               this.texture._needsFlipEnvMap = false;
-       }
+               var _proto = WebGLCubeRenderTarget.prototype;
 
-       WebGLCubeRenderTarget.prototype = Object.create(WebGLRenderTarget.prototype);
-       WebGLCubeRenderTarget.prototype.constructor = WebGLCubeRenderTarget;
-       WebGLCubeRenderTarget.prototype.isWebGLCubeRenderTarget = true;
+               _proto.fromEquirectangularTexture = function fromEquirectangularTexture(renderer, texture) {
+                       this.texture.type = texture.type;
+                       this.texture.format = RGBAFormat; // see #18859
 
-       WebGLCubeRenderTarget.prototype.fromEquirectangularTexture = function (renderer, texture) {
-               this.texture.type = texture.type;
-               this.texture.format = RGBAFormat; // see #18859
+                       this.texture.encoding = texture.encoding;
+                       this.texture.generateMipmaps = texture.generateMipmaps;
+                       this.texture.minFilter = texture.minFilter;
+                       this.texture.magFilter = texture.magFilter;
+                       var shader = {
+                               uniforms: {
+                                       tEquirect: {
+                                               value: null
+                                       }
+                               },
+                               vertexShader:
+                               /* glsl */
+                               "\n\n\t\t\t\tvarying vec3 vWorldDirection;\n\n\t\t\t\tvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\n\t\t\t\t\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n\n\t\t\t\t}\n\n\t\t\t\tvoid main() {\n\n\t\t\t\t\tvWorldDirection = transformDirection( position, modelMatrix );\n\n\t\t\t\t\t#include <begin_vertex>\n\t\t\t\t\t#include <project_vertex>\n\n\t\t\t\t}\n\t\t\t",
+                               fragmentShader:
+                               /* glsl */
+                               "\n\n\t\t\t\tuniform sampler2D tEquirect;\n\n\t\t\t\tvarying vec3 vWorldDirection;\n\n\t\t\t\t#include <common>\n\n\t\t\t\tvoid main() {\n\n\t\t\t\t\tvec3 direction = normalize( vWorldDirection );\n\n\t\t\t\t\tvec2 sampleUV = equirectUv( direction );\n\n\t\t\t\t\tgl_FragColor = texture2D( tEquirect, sampleUV );\n\n\t\t\t\t}\n\t\t\t"
+                       };
+                       var geometry = new BoxGeometry(5, 5, 5);
+                       var material = new ShaderMaterial({
+                               name: 'CubemapFromEquirect',
+                               uniforms: cloneUniforms(shader.uniforms),
+                               vertexShader: shader.vertexShader,
+                               fragmentShader: shader.fragmentShader,
+                               side: BackSide,
+                               blending: NoBlending
+                       });
+                       material.uniforms.tEquirect.value = texture;
+                       var mesh = new Mesh(geometry, material);
+                       var currentMinFilter = texture.minFilter; // Avoid blurred poles
 
-               this.texture.encoding = texture.encoding;
-               this.texture.generateMipmaps = texture.generateMipmaps;
-               this.texture.minFilter = texture.minFilter;
-               this.texture.magFilter = texture.magFilter;
-               var shader = {
-                       uniforms: {
-                               tEquirect: {
-                                       value: null
-                               }
-                       },
-                       vertexShader:
-                       /* glsl */
-                       "\n\n\t\t\tvarying vec3 vWorldDirection;\n\n\t\t\tvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\n\t\t\t\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n\n\t\t\t}\n\n\t\t\tvoid main() {\n\n\t\t\t\tvWorldDirection = transformDirection( position, modelMatrix );\n\n\t\t\t\t#include <begin_vertex>\n\t\t\t\t#include <project_vertex>\n\n\t\t\t}\n\t\t",
-                       fragmentShader:
-                       /* glsl */
-                       "\n\n\t\t\tuniform sampler2D tEquirect;\n\n\t\t\tvarying vec3 vWorldDirection;\n\n\t\t\t#include <common>\n\n\t\t\tvoid main() {\n\n\t\t\t\tvec3 direction = normalize( vWorldDirection );\n\n\t\t\t\tvec2 sampleUV = equirectUv( direction );\n\n\t\t\t\tgl_FragColor = texture2D( tEquirect, sampleUV );\n\n\t\t\t}\n\t\t"
-               };
-               var geometry = new BoxBufferGeometry(5, 5, 5);
-               var material = new ShaderMaterial({
-                       name: 'CubemapFromEquirect',
-                       uniforms: cloneUniforms(shader.uniforms),
-                       vertexShader: shader.vertexShader,
-                       fragmentShader: shader.fragmentShader,
-                       side: BackSide,
-                       blending: NoBlending
-               });
-               material.uniforms.tEquirect.value = texture;
-               var mesh = new Mesh(geometry, material);
-               var currentMinFilter = texture.minFilter; // Avoid blurred poles
-
-               if (texture.minFilter === LinearMipmapLinearFilter) texture.minFilter = LinearFilter;
-               var camera = new CubeCamera(1, 10, this);
-               camera.update(renderer, mesh);
-               texture.minFilter = currentMinFilter;
-               mesh.geometry.dispose();
-               mesh.material.dispose();
-               return this;
-       };
+                       if (texture.minFilter === LinearMipmapLinearFilter) texture.minFilter = LinearFilter;
+                       var camera = new CubeCamera(1, 10, this);
+                       camera.update(renderer, mesh);
+                       texture.minFilter = currentMinFilter;
+                       mesh.geometry.dispose();
+                       mesh.material.dispose();
+                       return this;
+               };
 
-       WebGLCubeRenderTarget.prototype.clear = function (renderer, color, depth, stencil) {
-               var currentRenderTarget = renderer.getRenderTarget();
+               _proto.clear = function clear(renderer, color, depth, stencil) {
+                       var currentRenderTarget = renderer.getRenderTarget();
 
-               for (var i = 0; i < 6; i++) {
-                       renderer.setRenderTarget(this, i);
-                       renderer.clear(color, depth, stencil);
-               }
+                       for (var i = 0; i < 6; i++) {
+                               renderer.setRenderTarget(this, i);
+                               renderer.clear(color, depth, stencil);
+                       }
 
-               renderer.setRenderTarget(currentRenderTarget);
-       };
+                       renderer.setRenderTarget(currentRenderTarget);
+               };
+
+               return WebGLCubeRenderTarget;
+       }(WebGLRenderTarget);
 
        function DataTexture(data, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding) {
                Texture.call(this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding);
                };
        }
 
-       var PlaneBufferGeometry = /*#__PURE__*/function (_BufferGeometry) {
-               _inheritsLoose(PlaneBufferGeometry, _BufferGeometry);
+       var PlaneGeometry = /*#__PURE__*/function (_BufferGeometry) {
+               _inheritsLoose(PlaneGeometry, _BufferGeometry);
 
-               function PlaneBufferGeometry(width, height, widthSegments, heightSegments) {
+               function PlaneGeometry(width, height, widthSegments, heightSegments) {
                        var _this;
 
                        if (width === void 0) {
                        }
 
                        _this = _BufferGeometry.call(this) || this;
-                       _this.type = 'PlaneBufferGeometry';
+                       _this.type = 'PlaneGeometry';
                        _this.parameters = {
                                width: width,
                                height: height,
                        return _this;
                }
 
-               return PlaneBufferGeometry;
+               return PlaneGeometry;
        }(BufferGeometry);
 
        var alphamap_fragment = "#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, vUv ).g;\n#endif";
 
                        if (background && (background.isCubeTexture || background.isWebGLCubeRenderTarget || background.mapping === CubeUVReflectionMapping)) {
                                if (boxMesh === undefined) {
-                                       boxMesh = new Mesh(new BoxBufferGeometry(1, 1, 1), new ShaderMaterial({
+                                       boxMesh = new Mesh(new BoxGeometry(1, 1, 1), new ShaderMaterial({
                                                name: 'BackgroundCubeMaterial',
                                                uniforms: cloneUniforms(ShaderLib.cube.uniforms),
                                                vertexShader: ShaderLib.cube.vertexShader,
                                renderList.unshift(boxMesh, boxMesh.geometry, boxMesh.material, 0, 0, null);
                        } else if (background && background.isTexture) {
                                if (planeMesh === undefined) {
-                                       planeMesh = new Mesh(new PlaneBufferGeometry(2, 2), new ShaderMaterial({
+                                       planeMesh = new Mesh(new PlaneGeometry(2, 2), new ShaderMaterial({
                                                name: 'BackgroundMaterial',
                                                uniforms: cloneUniforms(ShaderLib.background.uniforms),
                                                vertexShader: ShaderLib.background.vertexShader,
                                                if (image && image.height > 0) {
                                                        var currentRenderList = renderer.getRenderList();
                                                        var currentRenderTarget = renderer.getRenderTarget();
-                                                       var currentRenderState = renderer.getRenderState();
                                                        var renderTarget = new WebGLCubeRenderTarget(image.height / 2);
                                                        renderTarget.fromEquirectangularTexture(renderer, texture);
                                                        cubemaps.set(texture, renderTarget);
                                                        renderer.setRenderTarget(currentRenderTarget);
                                                        renderer.setRenderList(currentRenderList);
-                                                       renderer.setRenderState(currentRenderState);
                                                        texture.addEventListener('dispose', onTextureDispose);
                                                        return mapTextureMapping(renderTarget.texture, texture.mapping);
                                                } else {
 
        function WebGLExtensions(gl) {
                var extensions = {};
-               return {
-                       has: function has(name) {
-                               if (extensions[name] !== undefined) {
-                                       return extensions[name] !== null;
-                               }
 
-                               var extension;
+               function getExtension(name) {
+                       if (extensions[name] !== undefined) {
+                               return extensions[name];
+                       }
 
-                               switch (name) {
-                                       case 'WEBGL_depth_texture':
-                                               extension = gl.getExtension('WEBGL_depth_texture') || gl.getExtension('MOZ_WEBGL_depth_texture') || gl.getExtension('WEBKIT_WEBGL_depth_texture');
-                                               break;
+                       var extension;
 
-                                       case 'EXT_texture_filter_anisotropic':
-                                               extension = gl.getExtension('EXT_texture_filter_anisotropic') || gl.getExtension('MOZ_EXT_texture_filter_anisotropic') || gl.getExtension('WEBKIT_EXT_texture_filter_anisotropic');
-                                               break;
+                       switch (name) {
+                               case 'WEBGL_depth_texture':
+                                       extension = gl.getExtension('WEBGL_depth_texture') || gl.getExtension('MOZ_WEBGL_depth_texture') || gl.getExtension('WEBKIT_WEBGL_depth_texture');
+                                       break;
 
-                                       case 'WEBGL_compressed_texture_s3tc':
-                                               extension = gl.getExtension('WEBGL_compressed_texture_s3tc') || gl.getExtension('MOZ_WEBGL_compressed_texture_s3tc') || gl.getExtension('WEBKIT_WEBGL_compressed_texture_s3tc');
-                                               break;
+                               case 'EXT_texture_filter_anisotropic':
+                                       extension = gl.getExtension('EXT_texture_filter_anisotropic') || gl.getExtension('MOZ_EXT_texture_filter_anisotropic') || gl.getExtension('WEBKIT_EXT_texture_filter_anisotropic');
+                                       break;
 
-                                       case 'WEBGL_compressed_texture_pvrtc':
-                                               extension = gl.getExtension('WEBGL_compressed_texture_pvrtc') || gl.getExtension('WEBKIT_WEBGL_compressed_texture_pvrtc');
-                                               break;
+                               case 'WEBGL_compressed_texture_s3tc':
+                                       extension = gl.getExtension('WEBGL_compressed_texture_s3tc') || gl.getExtension('MOZ_WEBGL_compressed_texture_s3tc') || gl.getExtension('WEBKIT_WEBGL_compressed_texture_s3tc');
+                                       break;
 
-                                       default:
-                                               extension = gl.getExtension(name);
-                               }
+                               case 'WEBGL_compressed_texture_pvrtc':
+                                       extension = gl.getExtension('WEBGL_compressed_texture_pvrtc') || gl.getExtension('WEBKIT_WEBGL_compressed_texture_pvrtc');
+                                       break;
 
-                               extensions[name] = extension;
-                               return extension !== null;
+                               default:
+                                       extension = gl.getExtension(name);
+                       }
+
+                       extensions[name] = extension;
+                       return extension;
+               }
+
+               return {
+                       has: function has(name) {
+                               return getExtension(name) !== null;
+                       },
+                       init: function init(capabilities) {
+                               if (capabilities.isWebGL2) {
+                                       getExtension('EXT_color_buffer_float');
+                               } else {
+                                       getExtension('WEBGL_depth_texture');
+                                       getExtension('OES_texture_float');
+                                       getExtension('OES_texture_half_float');
+                                       getExtension('OES_texture_half_float_linear');
+                                       getExtension('OES_standard_derivatives');
+                                       getExtension('OES_element_index_uint');
+                                       getExtension('OES_vertex_array_object');
+                                       getExtension('ANGLE_instanced_arrays');
+                               }
+
+                               getExtension('OES_texture_float_linear');
+                               getExtension('EXT_color_buffer_half_float');
                        },
                        get: function get(name) {
-                               if (!this.has(name)) {
+                               var extension = getExtension(name);
+
+                               if (extension === null) {
                                        console.warn('THREE.WebGLRenderer: ' + name + ' extension not supported.');
                                }
 
-                               return extensions[name];
+                               return extension;
                        }
                };
        }
 
        function WebGLGeometries(gl, attributes, info, bindingStates) {
-               var geometries = new WeakMap();
+               var geometries = {};
                var wireframeAttributes = new WeakMap();
 
                function onGeometryDispose(event) {
                        var geometry = event.target;
-                       var buffergeometry = geometries.get(geometry);
 
-                       if (buffergeometry.index !== null) {
-                               attributes.remove(buffergeometry.index);
+                       if (geometry.index !== null) {
+                               attributes.remove(geometry.index);
                        }
 
-                       for (var name in buffergeometry.attributes) {
-                               attributes.remove(buffergeometry.attributes[name]);
+                       for (var name in geometry.attributes) {
+                               attributes.remove(geometry.attributes[name]);
                        }
 
                        geometry.removeEventListener('dispose', onGeometryDispose);
-                       geometries.delete(geometry);
-                       var attribute = wireframeAttributes.get(buffergeometry);
+                       delete geometries[geometry.id];
+                       var attribute = wireframeAttributes.get(geometry);
 
                        if (attribute) {
                                attributes.remove(attribute);
-                               wireframeAttributes.delete(buffergeometry);
+                               wireframeAttributes.delete(geometry);
                        }
 
-                       bindingStates.releaseStatesOfGeometry(buffergeometry);
+                       bindingStates.releaseStatesOfGeometry(geometry);
 
                        if (geometry.isInstancedBufferGeometry === true) {
                                delete geometry._maxInstanceCount;
                }
 
                function get(object, geometry) {
-                       var buffergeometry = geometries.get(geometry);
-                       if (buffergeometry) return buffergeometry;
+                       if (geometries[geometry.id] === true) return geometry;
                        geometry.addEventListener('dispose', onGeometryDispose);
-
-                       if (geometry.isBufferGeometry) {
-                               buffergeometry = geometry;
-                       } else if (geometry.isGeometry) {
-                               if (geometry._bufferGeometry === undefined) {
-                                       geometry._bufferGeometry = new BufferGeometry().setFromObject(object);
-                               }
-
-                               buffergeometry = geometry._bufferGeometry;
-                       }
-
-                       geometries.set(geometry, buffergeometry);
+                       geometries[geometry.id] = true;
                        info.memory.geometries++;
-                       return buffergeometry;
+                       return geometry;
                }
 
                function update(geometry) {
                        var buffergeometry = geometries.get(object, geometry); // Update once per frame
 
                        if (updateMap.get(buffergeometry) !== frame) {
-                               if (geometry.isGeometry) {
-                                       buffergeometry.updateFromObject(object);
-                               }
-
                                geometries.update(buffergeometry);
                                updateMap.set(buffergeometry, frame);
                        }
 
                        if (object.isInstancedMesh) {
+                               if (object.hasEventListener('dispose', onInstancedMeshDispose) === false) {
+                                       object.addEventListener('dispose', onInstancedMeshDispose);
+                               }
+
                                attributes.update(object.instanceMatrix, 34962);
 
                                if (object.instanceColor !== null) {
                        updateMap = new WeakMap();
                }
 
+               function onInstancedMeshDispose(event) {
+                       var instancedMesh = event.target;
+                       instancedMesh.removeEventListener('dispose', onInstancedMeshDispose);
+                       attributes.remove(instancedMesh.instanceMatrix);
+                       if (instancedMesh.instanceColor !== null) attributes.remove(instancedMesh.instanceColor);
+               }
+
                return {
                        update: update,
                        dispose: dispose
        // Parser - builds up the property tree from the path strings
 
 
-       var RePathPart = /([\w\d_]+)(\])?(\[|\.)?/g; // extracts
+       var RePathPart = /(\w+)(\])?(\[|\.)?/g; // extracts
        //      - the identifier (member name or array index)
        //      - followed by an optional right bracket (found when array index)
        //      - followed by an optional left bracket or dot (type of subscript)
 
 
        function generatePrecision(parameters) {
-               var precisionstring = "precision " + parameters.precision + " float;\nprecision " + parameters.precision + " int;";
+               var precisionstring = 'precision ' + parameters.precision + ' float;\nprecision ' + parameters.precision + ' int;';
 
-               if (parameters.precision === "highp") {
-                       precisionstring += "\n#define HIGH_PRECISION";
-               } else if (parameters.precision === "mediump") {
-                       precisionstring += "\n#define MEDIUM_PRECISION";
-               } else if (parameters.precision === "lowp") {
-                       precisionstring += "\n#define LOW_PRECISION";
+               if (parameters.precision === 'highp') {
+                       precisionstring += '\n#define HIGH_PRECISION';
+               } else if (parameters.precision === 'mediump') {
+                       precisionstring += '\n#define MEDIUM_PRECISION';
+               } else if (parameters.precision === 'lowp') {
+                       precisionstring += '\n#define LOW_PRECISION';
                }
 
                return precisionstring;
                var customDefines = generateDefines(defines);
                var program = gl.createProgram();
                var prefixVertex, prefixFragment;
-               var versionString = parameters.glslVersion ? '#version ' + parameters.glslVersion + "\n" : '';
+               var versionString = parameters.glslVersion ? '#version ' + parameters.glslVersion + '\n' : '';
 
                if (parameters.isRawShaderMaterial) {
                        prefixVertex = [customDefines].filter(filterEmptyLine).join('\n');
                        ShadowMaterial: 'shadow',
                        SpriteMaterial: 'sprite'
                };
-               var parameterNames = ["precision", "isWebGL2", "supportsVertexTextures", "outputEncoding", "instancing", "instancingColor", "map", "mapEncoding", "matcap", "matcapEncoding", "envMap", "envMapMode", "envMapEncoding", "envMapCubeUV", "lightMap", "lightMapEncoding", "aoMap", "emissiveMap", "emissiveMapEncoding", "bumpMap", "normalMap", "objectSpaceNormalMap", "tangentSpaceNormalMap", "clearcoatMap", "clearcoatRoughnessMap", "clearcoatNormalMap", "displacementMap", "specularMap", "roughnessMap", "metalnessMap", "gradientMap", "alphaMap", "combine", "vertexColors", "vertexTangents", "vertexUvs", "uvsVertexOnly", "fog", "useFog", "fogExp2", "flatShading", "sizeAttenuation", "logarithmicDepthBuffer", "skinning", "maxBones", "useVertexTexture", "morphTargets", "morphNormals", "maxMorphTargets", "maxMorphNormals", "premultipliedAlpha", "numDirLights", "numPointLights", "numSpotLights", "numHemiLights", "numRectAreaLights", "numDirLightShadows", "numPointLightShadows", "numSpotLightShadows", "shadowMapEnabled", "shadowMapType", "toneMapping", 'physicallyCorrectLights', "alphaTest", "doubleSided", "flipSided", "numClippingPlanes", "numClipIntersection", "depthPacking", "dithering", "sheen", "transmissionMap"];
+               var parameterNames = ['precision', 'isWebGL2', 'supportsVertexTextures', 'outputEncoding', 'instancing', 'instancingColor', 'map', 'mapEncoding', 'matcap', 'matcapEncoding', 'envMap', 'envMapMode', 'envMapEncoding', 'envMapCubeUV', 'lightMap', 'lightMapEncoding', 'aoMap', 'emissiveMap', 'emissiveMapEncoding', 'bumpMap', 'normalMap', 'objectSpaceNormalMap', 'tangentSpaceNormalMap', 'clearcoatMap', 'clearcoatRoughnessMap', 'clearcoatNormalMap', 'displacementMap', 'specularMap', 'roughnessMap', 'metalnessMap', 'gradientMap', 'alphaMap', 'combine', 'vertexColors', 'vertexTangents', 'vertexUvs', 'uvsVertexOnly', 'fog', 'useFog', 'fogExp2', 'flatShading', 'sizeAttenuation', 'logarithmicDepthBuffer', 'skinning', 'maxBones', 'useVertexTexture', 'morphTargets', 'morphNormals', 'maxMorphTargets', 'maxMorphNormals', 'premultipliedAlpha', 'numDirLights', 'numPointLights', 'numSpotLights', 'numHemiLights', 'numRectAreaLights', 'numDirLightShadows', 'numPointLightShadows', 'numSpotLightShadows', 'shadowMapEnabled', 'shadowMapType', 'toneMapping', 'physicallyCorrectLights', 'alphaTest', 'doubleSided', 'flipSided', 'numClippingPlanes', 'numClipIntersection', 'depthPacking', 'dithering', 'sheen', 'transmissionMap'];
 
                function getMaxBones(object) {
                        var skeleton = object.skeleton;
                function getTextureEncodingFromMap(map) {
                        var encoding;
 
-                       if (!map) {
-                               encoding = LinearEncoding;
-                       } else if (map.isTexture) {
+                       if (map && map.isTexture) {
                                encoding = map.encoding;
-                       } else if (map.isWebGLRenderTarget) {
-                               console.warn("THREE.WebGLPrograms.getTextureEncodingFromMap: don't use render targets as textures. Use their .texture property instead.");
+                       } else if (map && map.isWebGLRenderTarget) {
+                               console.warn('THREE.WebGLPrograms.getTextureEncodingFromMap: don\'t use render targets as textures. Use their .texture property instead.');
                                encoding = map.texture.encoding;
+                       } else {
+                               encoding = LinearEncoding;
                        }
 
                        return encoding;
                var matrix4 = new Matrix4();
                var matrix42 = new Matrix4();
 
-               function setup(lights, shadows, camera) {
+               function setup(lights) {
                        var r = 0,
                                        g = 0,
                                        b = 0;
                        var numDirectionalShadows = 0;
                        var numPointShadows = 0;
                        var numSpotShadows = 0;
-                       var viewMatrix = camera.matrixWorldInverse;
                        lights.sort(shadowCastingLightsFirst);
 
                        for (var _i2 = 0, l = lights.length; _i2 < l; _i2++) {
                                } else if (light.isDirectionalLight) {
                                        var uniforms = cache.get(light);
                                        uniforms.color.copy(light.color).multiplyScalar(light.intensity);
-                                       uniforms.direction.setFromMatrixPosition(light.matrixWorld);
-                                       vector3.setFromMatrixPosition(light.target.matrixWorld);
-                                       uniforms.direction.sub(vector3);
-                                       uniforms.direction.transformDirection(viewMatrix);
 
                                        if (light.castShadow) {
                                                var shadow = light.shadow;
 
                                        _uniforms.position.setFromMatrixPosition(light.matrixWorld);
 
-                                       _uniforms.position.applyMatrix4(viewMatrix);
-
                                        _uniforms.color.copy(color).multiplyScalar(intensity);
 
                                        _uniforms.distance = distance;
-
-                                       _uniforms.direction.setFromMatrixPosition(light.matrixWorld);
-
-                                       vector3.setFromMatrixPosition(light.target.matrixWorld);
-
-                                       _uniforms.direction.sub(vector3);
-
-                                       _uniforms.direction.transformDirection(viewMatrix);
-
                                        _uniforms.coneCos = Math.cos(light.angle);
                                        _uniforms.penumbraCos = Math.cos(light.angle * (1 - light.penumbra));
                                        _uniforms.decay = light.decay;
 
                                        _uniforms2.color.copy(color).multiplyScalar(intensity);
 
-                                       _uniforms2.position.setFromMatrixPosition(light.matrixWorld);
-
-                                       _uniforms2.position.applyMatrix4(viewMatrix); // extract local rotation of light to derive width/height half vectors
-
-
-                                       matrix42.identity();
-                                       matrix4.copy(light.matrixWorld);
-                                       matrix4.premultiply(viewMatrix);
-                                       matrix42.extractRotation(matrix4);
-
                                        _uniforms2.halfWidth.set(light.width * 0.5, 0.0, 0.0);
 
                                        _uniforms2.halfHeight.set(0.0, light.height * 0.5, 0.0);
 
-                                       _uniforms2.halfWidth.applyMatrix4(matrix42);
-
-                                       _uniforms2.halfHeight.applyMatrix4(matrix42); // TODO (abelnation): RectAreaLight distance?
-                                       // uniforms.distance = distance;
-
-
                                        state.rectArea[rectAreaLength] = _uniforms2;
                                        rectAreaLength++;
                                } else if (light.isPointLight) {
                                        var _uniforms3 = cache.get(light);
 
-                                       _uniforms3.position.setFromMatrixPosition(light.matrixWorld);
-
-                                       _uniforms3.position.applyMatrix4(viewMatrix);
-
                                        _uniforms3.color.copy(light.color).multiplyScalar(light.intensity);
 
                                        _uniforms3.distance = light.distance;
                                } else if (light.isHemisphereLight) {
                                        var _uniforms4 = cache.get(light);
 
-                                       _uniforms4.direction.setFromMatrixPosition(light.matrixWorld);
-
-                                       _uniforms4.direction.transformDirection(viewMatrix);
-
-                                       _uniforms4.direction.normalize();
-
                                        _uniforms4.skyColor.copy(light.color).multiplyScalar(intensity);
 
                                        _uniforms4.groundColor.copy(light.groundColor).multiplyScalar(intensity);
                        }
                }
 
+               function setupView(lights, camera) {
+                       var directionalLength = 0;
+                       var pointLength = 0;
+                       var spotLength = 0;
+                       var rectAreaLength = 0;
+                       var hemiLength = 0;
+                       var viewMatrix = camera.matrixWorldInverse;
+
+                       for (var _i3 = 0, l = lights.length; _i3 < l; _i3++) {
+                               var light = lights[_i3];
+
+                               if (light.isDirectionalLight) {
+                                       var uniforms = state.directional[directionalLength];
+                                       uniforms.direction.setFromMatrixPosition(light.matrixWorld);
+                                       vector3.setFromMatrixPosition(light.target.matrixWorld);
+                                       uniforms.direction.sub(vector3);
+                                       uniforms.direction.transformDirection(viewMatrix);
+                                       directionalLength++;
+                               } else if (light.isSpotLight) {
+                                       var _uniforms5 = state.spot[spotLength];
+
+                                       _uniforms5.position.setFromMatrixPosition(light.matrixWorld);
+
+                                       _uniforms5.position.applyMatrix4(viewMatrix);
+
+                                       _uniforms5.direction.setFromMatrixPosition(light.matrixWorld);
+
+                                       vector3.setFromMatrixPosition(light.target.matrixWorld);
+
+                                       _uniforms5.direction.sub(vector3);
+
+                                       _uniforms5.direction.transformDirection(viewMatrix);
+
+                                       spotLength++;
+                               } else if (light.isRectAreaLight) {
+                                       var _uniforms6 = state.rectArea[rectAreaLength];
+
+                                       _uniforms6.position.setFromMatrixPosition(light.matrixWorld);
+
+                                       _uniforms6.position.applyMatrix4(viewMatrix); // extract local rotation of light to derive width/height half vectors
+
+
+                                       matrix42.identity();
+                                       matrix4.copy(light.matrixWorld);
+                                       matrix4.premultiply(viewMatrix);
+                                       matrix42.extractRotation(matrix4);
+
+                                       _uniforms6.halfWidth.set(light.width * 0.5, 0.0, 0.0);
+
+                                       _uniforms6.halfHeight.set(0.0, light.height * 0.5, 0.0);
+
+                                       _uniforms6.halfWidth.applyMatrix4(matrix42);
+
+                                       _uniforms6.halfHeight.applyMatrix4(matrix42);
+
+                                       rectAreaLength++;
+                               } else if (light.isPointLight) {
+                                       var _uniforms7 = state.point[pointLength];
+
+                                       _uniforms7.position.setFromMatrixPosition(light.matrixWorld);
+
+                                       _uniforms7.position.applyMatrix4(viewMatrix);
+
+                                       pointLength++;
+                               } else if (light.isHemisphereLight) {
+                                       var _uniforms8 = state.hemi[hemiLength];
+
+                                       _uniforms8.direction.setFromMatrixPosition(light.matrixWorld);
+
+                                       _uniforms8.direction.transformDirection(viewMatrix);
+
+                                       _uniforms8.direction.normalize();
+
+                                       hemiLength++;
+                               }
+                       }
+               }
+
                return {
                        setup: setup,
+                       setupView: setupView,
                        state: state
                };
        }
                        shadowsArray.push(shadowLight);
                }
 
-               function setupLights(camera) {
-                       lights.setup(lightsArray, shadowsArray, camera);
+               function setupLights() {
+                       lights.setup(lightsArray);
+               }
+
+               function setupLightsView(camera) {
+                       lights.setupView(lightsArray, camera);
                }
 
                var state = {
                        init: init,
                        state: state,
                        setupLights: setupLights,
+                       setupLightsView: setupLightsView,
                        pushLight: pushLight,
                        pushShadow: pushShadow
                };
        function WebGLRenderStates(extensions, capabilities) {
                var renderStates = new WeakMap();
 
-               function get(scene, camera) {
+               function get(scene, renderCallDepth) {
+                       if (renderCallDepth === void 0) {
+                               renderCallDepth = 0;
+                       }
+
                        var renderState;
 
                        if (renderStates.has(scene) === false) {
                                renderState = new WebGLRenderState(extensions, capabilities);
-                               renderStates.set(scene, new WeakMap());
-                               renderStates.get(scene).set(camera, renderState);
+                               renderStates.set(scene, []);
+                               renderStates.get(scene).push(renderState);
                        } else {
-                               if (renderStates.get(scene).has(camera) === false) {
+                               if (renderCallDepth >= renderStates.get(scene).length) {
                                        renderState = new WebGLRenderState(extensions, capabilities);
-                                       renderStates.get(scene).set(camera, renderState);
+                                       renderStates.get(scene).push(renderState);
                                } else {
-                                       renderState = renderStates.get(scene).get(camera);
+                                       renderState = renderStates.get(scene)[renderCallDepth];
                                }
                        }
 
                return this;
        };
 
-       var vsm_frag = "uniform sampler2D shadow_pass;\nuniform vec2 resolution;\nuniform float radius;\n#include <packing>\nvoid main() {\n\tfloat mean = 0.0;\n\tfloat squared_mean = 0.0;\n\tfloat depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy ) / resolution ) );\n\tfor ( float i = -1.0; i < 1.0 ; i += SAMPLE_RATE) {\n\t\t#ifdef HORIZONAL_PASS\n\t\t\tvec2 distribution = unpackRGBATo2Half( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( i, 0.0 ) * radius ) / resolution ) );\n\t\t\tmean += distribution.x;\n\t\t\tsquared_mean += distribution.y * distribution.y + distribution.x * distribution.x;\n\t\t#else\n\t\t\tfloat depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( 0.0, i ) * radius ) / resolution ) );\n\t\t\tmean += depth;\n\t\t\tsquared_mean += depth * depth;\n\t\t#endif\n\t}\n\tmean = mean * HALF_SAMPLE_RATE;\n\tsquared_mean = squared_mean * HALF_SAMPLE_RATE;\n\tfloat std_dev = sqrt( squared_mean - mean * mean );\n\tgl_FragColor = pack2HalfToRGBA( vec2( mean, std_dev ) );\n}";
+       var vsm_frag = "uniform sampler2D shadow_pass;\nuniform vec2 resolution;\nuniform float radius;\n#include <packing>\nvoid main() {\n\tfloat mean = 0.0;\n\tfloat squared_mean = 0.0;\n\tfloat depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy ) / resolution ) );\n\tfor ( float i = -1.0; i < 1.0 ; i += SAMPLE_RATE) {\n\t\t#ifdef HORIZONTAL_PASS\n\t\t\tvec2 distribution = unpackRGBATo2Half( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( i, 0.0 ) * radius ) / resolution ) );\n\t\t\tmean += distribution.x;\n\t\t\tsquared_mean += distribution.y * distribution.y + distribution.x * distribution.x;\n\t\t#else\n\t\t\tfloat depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( 0.0, i ) * radius ) / resolution ) );\n\t\t\tmean += depth;\n\t\t\tsquared_mean += depth * depth;\n\t\t#endif\n\t}\n\tmean = mean * HALF_SAMPLE_RATE;\n\tsquared_mean = squared_mean * HALF_SAMPLE_RATE;\n\tfloat std_dev = sqrt( squared_mean - mean * mean );\n\tgl_FragColor = pack2HalfToRGBA( vec2( mean, std_dev ) );\n}";
 
        var vsm_vert = "void main() {\n\tgl_Position = vec4( position, 1.0 );\n}";
 
                        vertexShader: vsm_vert,
                        fragmentShader: vsm_frag
                });
-               var shadowMaterialHorizonal = shadowMaterialVertical.clone();
-               shadowMaterialHorizonal.defines.HORIZONAL_PASS = 1;
+               var shadowMaterialHorizontal = shadowMaterialVertical.clone();
+               shadowMaterialHorizontal.defines.HORIZONTAL_PASS = 1;
                var fullScreenTri = new BufferGeometry();
-               fullScreenTri.setAttribute("position", new BufferAttribute(new Float32Array([-1, -1, 0.5, 3, -1, 0.5, -1, 3, 0.5]), 3));
+               fullScreenTri.setAttribute('position', new BufferAttribute(new Float32Array([-1, -1, 0.5, 3, -1, 0.5, -1, 3, 0.5]), 3));
                var fullScreenMesh = new Mesh(fullScreenTri, shadowMaterialVertical);
                var scope = this;
                this.enabled = false;
                                                format: RGBAFormat
                                        };
                                        shadow.map = new WebGLRenderTarget(_shadowMapSize.x, _shadowMapSize.y, pars);
-                                       shadow.map.texture.name = light.name + ".shadowMap";
+                                       shadow.map.texture.name = light.name + '.shadowMap';
                                        shadow.mapPass = new WebGLRenderTarget(_shadowMapSize.x, _shadowMapSize.y, pars);
                                        shadow.camera.updateProjectionMatrix();
                                }
                                                format: RGBAFormat
                                        };
                                        shadow.map = new WebGLRenderTarget(_shadowMapSize.x, _shadowMapSize.y, _pars);
-                                       shadow.map.texture.name = light.name + ".shadowMap";
+                                       shadow.map.texture.name = light.name + '.shadowMap';
                                        shadow.camera.updateProjectionMatrix();
                                }
 
 
                        _renderer.clear();
 
-                       _renderer.renderBufferDirect(camera, null, geometry, shadowMaterialVertical, fullScreenMesh, null); // horizonal pass
+                       _renderer.renderBufferDirect(camera, null, geometry, shadowMaterialVertical, fullScreenMesh, null); // horizontal pass
 
 
-                       shadowMaterialHorizonal.uniforms.shadow_pass.value = shadow.mapPass.texture;
-                       shadowMaterialHorizonal.uniforms.resolution.value = shadow.mapSize;
-                       shadowMaterialHorizonal.uniforms.radius.value = shadow.radius;
+                       shadowMaterialHorizontal.uniforms.shadow_pass.value = shadow.mapPass.texture;
+                       shadowMaterialHorizontal.uniforms.resolution.value = shadow.mapSize;
+                       shadowMaterialHorizontal.uniforms.radius.value = shadow.radius;
 
                        _renderer.setRenderTarget(shadow.map);
 
                        _renderer.clear();
 
-                       _renderer.renderBufferDirect(camera, null, geometry, shadowMaterialHorizonal, fullScreenMesh, null);
+                       _renderer.renderBufferDirect(camera, null, geometry, shadowMaterialHorizontal, fullScreenMesh, null);
                }
 
                function getDepthMaterialVariant(useMorphing, useSkinning, useInstancing) {
                var glVersion = gl.getParameter(7938);
 
                if (glVersion.indexOf('WebGL') !== -1) {
-                       version = parseFloat(/^WebGL\ ([0-9])/.exec(glVersion)[1]);
+                       version = parseFloat(/^WebGL (\d)/.exec(glVersion)[1]);
                        lineWidthAvailable = version >= 1.0;
                } else if (glVersion.indexOf('OpenGL ES') !== -1) {
-                       version = parseFloat(/^OpenGL\ ES\ ([0-9])/.exec(glVersion)[1]);
+                       version = parseFloat(/^OpenGL ES (\d)/.exec(glVersion)[1]);
                        lineWidthAvailable = version >= 2.0;
                }
 
                var useOffscreenCanvas = false;
 
                try {
-                       useOffscreenCanvas = typeof OffscreenCanvas !== 'undefined' && new OffscreenCanvas(1, 1).getContext("2d") !== null;
+                       useOffscreenCanvas = typeof OffscreenCanvas !== 'undefined' && new OffscreenCanvas(1, 1).getContext('2d') !== null;
                } catch (err) {// Ignore any errors
                }
 
 
                        _gl.pixelStorei(37440, texture.flipY);
 
+                       _gl.pixelStorei(37441, texture.premultiplyAlpha);
+
+                       _gl.pixelStorei(3317, texture.unpackAlignment);
+
                        var isCompressed = texture && (texture.isCompressedTexture || texture.image[0].isCompressedTexture);
                        var isDataTexture = texture.image[0] && texture.image[0].isDataTexture;
                        var cubeImage = [];
                function safeSetTexture2D(texture, slot) {
                        if (texture && texture.isWebGLRenderTarget) {
                                if (warnedTexture2D === false) {
-                                       console.warn("THREE.WebGLTextures.safeSetTexture2D: don't use render targets as textures. Use their .texture property instead.");
+                                       console.warn('THREE.WebGLTextures.safeSetTexture2D: don\'t use render targets as textures. Use their .texture property instead.');
                                        warnedTexture2D = true;
                                }
 
                function safeSetTextureCube(texture, slot) {
                        if (texture && texture.isWebGLCubeRenderTarget) {
                                if (warnedTextureCube === false) {
-                                       console.warn("THREE.WebGLTextures.safeSetTextureCube: don't use cube render targets as textures. Use their .texture property instead.");
+                                       console.warn('THREE.WebGLTextures.safeSetTextureCube: don\'t use cube render targets as textures. Use their .texture property instead.');
                                        warnedTextureCube = true;
                                }
 
                                this._hand = new Group();
                                this._hand.matrixAutoUpdate = false;
                                this._hand.visible = false;
-                               this._hand.joints = [];
+                               this._hand.joints = {};
                                this._hand.inputState = {
                                        pinching: false
                                };
-
-                               if (window.XRHand) {
-                                       for (var i = 0; i <= window.XRHand.LITTLE_PHALANX_TIP; i++) {
-                                               // The transform of this joint will be updated with the joint pose on each frame
-                                               var joint = new Group();
-                                               joint.matrixAutoUpdate = false;
-                                               joint.visible = false;
-
-                                               this._hand.joints.push(joint); // ??
-
-
-                                               this._hand.add(joint);
-                                       }
-                               }
                        }
 
                        return this._hand;
                                if (hand && inputSource.hand) {
                                        handPose = true;
 
-                                       for (var i = 0; i <= window.XRHand.LITTLE_PHALANX_TIP; i++) {
-                                               if (inputSource.hand[i]) {
-                                                       // Update the joints groups with the XRJoint poses
-                                                       var jointPose = frame.getJointPose(inputSource.hand[i], referenceSpace);
-                                                       var joint = hand.joints[i];
+                                       for (var _iterator = _createForOfIteratorHelperLoose(inputSource.hand.values()), _step; !(_step = _iterator()).done;) {
+                                               var inputjoint = _step.value;
+                                               // Update the joints groups with the XRJoint poses
+                                               var jointPose = frame.getJointPose(inputjoint, referenceSpace);
 
-                                                       if (jointPose !== null) {
-                                                               joint.matrix.fromArray(jointPose.transform.matrix);
-                                                               joint.matrix.decompose(joint.position, joint.rotation, joint.scale);
-                                                               joint.jointRadius = jointPose.radius;
-                                                       }
+                                               if (hand.joints[inputjoint.jointName] === undefined) {
+                                                       // The transform of this joint will be updated with the joint pose on each frame
+                                                       var _joint = new Group();
 
-                                                       joint.visible = jointPose !== null; // Custom events
-                                                       // Check pinch
-
-                                                       var indexTip = hand.joints[window.XRHand.INDEX_PHALANX_TIP];
-                                                       var thumbTip = hand.joints[window.XRHand.THUMB_PHALANX_TIP];
-                                                       var distance = indexTip.position.distanceTo(thumbTip.position);
-                                                       var distanceToPinch = 0.02;
-                                                       var threshold = 0.005;
-
-                                                       if (hand.inputState.pinching && distance > distanceToPinch + threshold) {
-                                                               hand.inputState.pinching = false;
-                                                               this.dispatchEvent({
-                                                                       type: "pinchend",
-                                                                       handedness: inputSource.handedness,
-                                                                       target: this
-                                                               });
-                                                       } else if (!hand.inputState.pinching && distance <= distanceToPinch - threshold) {
-                                                               hand.inputState.pinching = true;
-                                                               this.dispatchEvent({
-                                                                       type: "pinchstart",
-                                                                       handedness: inputSource.handedness,
-                                                                       target: this
-                                                               });
-                                                       }
+                                                       _joint.matrixAutoUpdate = false;
+                                                       _joint.visible = false;
+                                                       hand.joints[inputjoint.jointName] = _joint; // ??
+
+                                                       hand.add(_joint);
+                                               }
+
+                                               var joint = hand.joints[inputjoint.jointName];
+
+                                               if (jointPose !== null) {
+                                                       joint.matrix.fromArray(jointPose.transform.matrix);
+                                                       joint.matrix.decompose(joint.position, joint.rotation, joint.scale);
+                                                       joint.jointRadius = jointPose.radius;
                                                }
+
+                                               joint.visible = jointPose !== null;
+                                       } // Custom events
+                                       // Check pinchz
+
+
+                                       var indexTip = hand.joints['index-finger-tip'];
+                                       var thumbTip = hand.joints['thumb-tip'];
+                                       var distance = indexTip.position.distanceTo(thumbTip.position);
+                                       var distanceToPinch = 0.02;
+                                       var threshold = 0.005;
+
+                                       if (hand.inputState.pinching && distance > distanceToPinch + threshold) {
+                                               hand.inputState.pinching = false;
+                                               this.dispatchEvent({
+                                                       type: 'pinchend',
+                                                       handedness: inputSource.handedness,
+                                                       target: this
+                                               });
+                                       } else if (!hand.inputState.pinching && distance <= distanceToPinch - threshold) {
+                                               hand.inputState.pinching = true;
+                                               this.dispatchEvent({
+                                                       type: 'pinchstart',
+                                                       handedness: inputSource.handedness,
+                                                       target: this
+                                               });
                                        }
                                } else {
                                        if (targetRay !== null) {
                        inputSourcesMap.forEach(function (controller, inputSource) {
                                controller.disconnect(inputSource);
                        });
-                       inputSourcesMap.clear(); //
+                       inputSourcesMap.clear();
+                       _currentDepthNear = null;
+                       _currentDepthFar = null; //
 
                        renderer.setFramebuffer(null);
                        renderer.setRenderTarget(renderer.getRenderTarget()); // Hack #15830
                        });
                }
 
-               function onRequestReferenceSpace(value) {
-                       referenceSpace = value;
-                       animation.setContext(session);
-                       animation.start();
-                       scope.isPresenting = true;
-                       scope.dispatchEvent({
-                               type: 'sessionstart'
-                       });
-               }
-
                this.setFramebufferScaleFactor = function (value) {
                        framebufferScaleFactor = value;
 
                        return session;
                };
 
-               this.setSession = function (value) {
-                       session = value;
+               this.setSession = /*#__PURE__*/function () {
+                       var _ref = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee(value) {
+                               var attributes, layerInit, baseLayer;
+                               return regeneratorRuntime.wrap(function _callee$(_context) {
+                                       while (1) {
+                                               switch (_context.prev = _context.next) {
+                                                       case 0:
+                                                               session = value;
 
-                       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);
-                               var attributes = gl.getContextAttributes();
+                                                               if (!(session !== null)) {
+                                                                       _context.next = 24;
+                                                                       break;
+                                                               }
 
-                               if (attributes.xrCompatible !== true) {
-                                       gl.makeXRCompatible();
-                               }
+                                                               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);
+                                                               attributes = gl.getContextAttributes();
+
+                                                               if (!(attributes.xrCompatible !== true)) {
+                                                                       _context.next = 14;
+                                                                       break;
+                                                               }
 
-                               var layerInit = {
-                                       antialias: attributes.antialias,
-                                       alpha: attributes.alpha,
-                                       depth: attributes.depth,
-                                       stencil: attributes.stencil,
-                                       framebufferScaleFactor: framebufferScaleFactor
-                               }; // eslint-disable-next-line no-undef
+                                                               _context.next = 14;
+                                                               return gl.makeXRCompatible();
+
+                                                       case 14:
+                                                               layerInit = {
+                                                                       antialias: attributes.antialias,
+                                                                       alpha: attributes.alpha,
+                                                                       depth: attributes.depth,
+                                                                       stencil: attributes.stencil,
+                                                                       framebufferScaleFactor: framebufferScaleFactor
+                                                               }; // eslint-disable-next-line no-undef
+
+                                                               baseLayer = new XRWebGLLayer(session, gl, layerInit);
+                                                               session.updateRenderState({
+                                                                       baseLayer: baseLayer
+                                                               });
+                                                               _context.next = 19;
+                                                               return session.requestReferenceSpace(referenceSpaceType);
+
+                                                       case 19:
+                                                               referenceSpace = _context.sent;
+                                                               animation.setContext(session);
+                                                               animation.start();
+                                                               scope.isPresenting = true;
+                                                               scope.dispatchEvent({
+                                                                       type: 'sessionstart'
+                                                               });
 
-                               var baseLayer = new XRWebGLLayer(session, gl, layerInit);
-                               session.updateRenderState({
-                                       baseLayer: baseLayer
-                               });
-                               session.requestReferenceSpace(referenceSpaceType).then(onRequestReferenceSpace); //
+                                                       case 24:
+                                                       case "end":
+                                                               return _context.stop();
+                                               }
+                                       }
+                               }, _callee);
+                       }));
 
-                               session.addEventListener('inputsourceschange', updateInputSources);
-                       }
-               };
+                       return function (_x) {
+                               return _ref.apply(this, arguments);
+                       };
+               }();
 
-               function updateInputSources(event) {
+               function onInputSourcesChange(event) {
                        var inputSources = session.inputSources; // Assign inputSources to available controllers
 
                        for (var i = 0; i < controllers.length; i++) {
 
 
                        camera.matrixWorld.copy(cameraVR.matrixWorld);
+                       camera.matrix.copy(cameraVR.matrix);
+                       camera.matrix.decompose(camera.position, camera.quaternion, camera.scale);
                        var children = camera.children;
 
                        for (var _i3 = 0, l = children.length; _i3 < l; _i3++) {
                                _failIfMajorPerformanceCaveat = parameters.failIfMajorPerformanceCaveat !== undefined ? parameters.failIfMajorPerformanceCaveat : false;
 
                var currentRenderList = null;
-               var currentRenderState = null; // public properties
+               var currentRenderState = null; // render() can be called from within a callback triggered by another render.
+               // We track this so that the nested render call gets its state isolated from the parent render call.
+
+               var renderStateStack = []; // public properties
 
                this.domElement = _canvas; // Debug configuration container
 
                var _currentMaterialId = -1;
 
                var _currentCamera = null;
-               var _currentArrayCamera = null;
 
                var _currentViewport = new Vector4();
 
                function initGLContext() {
                        extensions = new WebGLExtensions(_gl);
                        capabilities = new WebGLCapabilities(_gl, extensions, parameters);
-
-                       if (capabilities.isWebGL2 === false) {
-                               extensions.get('WEBGL_depth_texture');
-                               extensions.get('OES_texture_float');
-                               extensions.get('OES_texture_half_float');
-                               extensions.get('OES_texture_half_float_linear');
-                               extensions.get('OES_standard_derivatives');
-                               extensions.get('OES_element_index_uint');
-                               extensions.get('OES_vertex_array_object');
-                               extensions.get('ANGLE_instanced_arrays');
-                       }
-
-                       extensions.get('OES_texture_float_linear');
+                       extensions.init(capabilities);
                        utils = new WebGLUtils(_gl, extensions, capabilities);
                        state = new WebGLState(_gl, extensions, capabilities);
                        state.scissor(_currentScissor.copy(_scissor).multiplyScalar(_pixelRatio).floor());
                }; // Clearing
 
 
-               this.getClearColor = function () {
-                       return background.getClearColor();
+               this.getClearColor = function (target) {
+                       if (target === undefined) {
+                               console.warn('WebGLRenderer: .getClearColor() now requires a Color as an argument');
+                               target = new Color();
+                       }
+
+                       return target.copy(background.getClearColor());
                };
 
                this.setClearColor = function () {
 
 
                this.compile = function (scene, camera) {
-                       currentRenderState = renderStates.get(scene, camera);
+                       currentRenderState = renderStates.get(scene);
                        currentRenderState.init();
                        scene.traverseVisible(function (object) {
                                if (object.isLight && object.layers.test(camera.layers)) {
                                        }
                                }
                        });
-                       currentRenderState.setupLights(camera);
+                       currentRenderState.setupLights();
                        var compiled = new WeakMap();
                        scene.traverse(function (object) {
                                var material = object.material;
 
 
                        if (scene.isScene === true) scene.onBeforeRender(_this, scene, camera, renderTarget || _currentRenderTarget);
-                       currentRenderState = renderStates.get(scene, camera);
+                       currentRenderState = renderStates.get(scene, renderStateStack.length);
                        currentRenderState.init();
+                       renderStateStack.push(currentRenderState);
 
                        _projScreenMatrix.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse);
 
                        if (_clippingEnabled === true) clipping.beginShadows();
                        var shadowsArray = currentRenderState.state.shadowsArray;
                        shadowMap.render(shadowsArray, scene, camera);
-                       currentRenderState.setupLights(camera);
+                       currentRenderState.setupLights();
+                       currentRenderState.setupLightsView(camera);
                        if (_clippingEnabled === true) clipping.endShadows(); //
 
                        if (this.info.autoReset === true) this.info.reset();
                        state.buffers.color.setMask(true);
                        state.setPolygonOffset(false); // _gl.finish();
 
+                       renderStateStack.pop();
+
+                       if (renderStateStack.length > 0) {
+                               currentRenderState = renderStateStack[renderStateStack.length - 1];
+                       } else {
+                               currentRenderState = null;
+                       }
+
                        currentRenderList = null;
-                       currentRenderState = null;
                };
 
                function projectObject(object, camera, groupOrder, sortObjects) {
                                var group = renderItem.group;
 
                                if (camera.isArrayCamera) {
-                                       _currentArrayCamera = camera;
                                        var cameras = camera.cameras;
 
                                        for (var j = 0, jl = cameras.length; j < jl; j++) {
 
                                                if (object.layers.test(camera2.layers)) {
                                                        state.viewport(_currentViewport.copy(camera2.viewport));
-                                                       currentRenderState.setupLights(camera2);
+                                                       currentRenderState.setupLightsView(camera2);
                                                        renderObject(object, scene, camera2, geometry, material, group);
                                                }
                                        }
                                } else {
-                                       _currentArrayCamera = null;
                                        renderObject(object, scene, camera, geometry, material, group);
                                }
                        }
 
                function renderObject(object, scene, camera, geometry, material, group) {
                        object.onBeforeRender(_this, scene, camera, geometry, material, group);
-                       currentRenderState = renderStates.get(scene, _currentArrayCamera || camera);
                        object.modelViewMatrix.multiplyMatrices(camera.matrixWorldInverse, object.matrixWorld);
                        object.normalMatrix.getNormalMatrix(object.modelViewMatrix);
 
                        }
 
                        object.onAfterRender(_this, scene, camera, geometry, material, group);
-                       currentRenderState = renderStates.get(scene, _currentArrayCamera || camera);
                }
 
                function initMaterial(material, scene, object) {
                        var parameters = programCache.getParameters(material, lights.state, shadowsArray, scene, object);
                        var programCacheKey = programCache.getProgramCacheKey(parameters);
                        var program = materialProperties.program;
-                       var programChange = true;
+                       var programChange = true; // always update environment and fog - changing these trigger an initMaterial call, but it's possible that the program doesn't change
+
+                       materialProperties.environment = material.isMeshStandardMaterial ? scene.environment : null;
+                       materialProperties.fog = scene.fog;
+                       materialProperties.envMap = cubemaps.get(material.envMap || materialProperties.environment);
 
                        if (program === undefined) {
                                // new material
                        } else if (materialProperties.lightsStateVersion !== lightsStateVersion) {
                                programChange = false;
                        } else if (parameters.shaderID !== undefined) {
-                               // same glsl and uniform list, envMap still needs the update here to avoid a frame-late effect
-                               var environment = material.isMeshStandardMaterial ? scene.environment : null;
-                               materialProperties.envMap = cubemaps.get(material.envMap || environment);
+                               // same glsl and uniform list
                                return;
                        } else {
                                // only rebuild uniform list
                                materialProperties.numClippingPlanes = clipping.numPlanes;
                                materialProperties.numIntersection = clipping.numIntersection;
                                uniforms.clippingPlanes = clipping.uniform;
-                       }
+                       } // store the light setup it was created for
 
-                       materialProperties.environment = material.isMeshStandardMaterial ? scene.environment : null;
-                       materialProperties.fog = scene.fog;
-                       materialProperties.envMap = cubemaps.get(material.envMap || materialProperties.environment); // store the light setup it was created for
 
                        materialProperties.needsLights = materialNeedsLights(material);
                        materialProperties.lightsStateVersion = lightsStateVersion;
                        currentRenderList = renderList;
                };
 
-               this.getRenderState = function () {
-                       return currentRenderState;
-               };
-
-               this.setRenderState = function (renderState) {
-                       currentRenderState = renderState;
-               };
-
                this.getRenderTarget = function () {
                        return _currentRenderTarget;
                };
                                                return;
                                        }
 
+                                       var halfFloatSupportedByExt = textureType === HalfFloatType && (extensions.has('EXT_color_buffer_half_float') || capabilities.isWebGL2 && extensions.has('EXT_color_buffer_float'));
+
                                        if (textureType !== UnsignedByteType && utils.convert(textureType) !== _gl.getParameter(35738) && // IE11, Edge and Chrome Mac < 52 (#9513)
-                                       !(textureType === FloatType && (capabilities.isWebGL2 || extensions.get('OES_texture_float') || extensions.get('WEBGL_color_buffer_float'))) && // Chrome Mac >= 52 and Firefox
-                                       !(textureType === HalfFloatType && (capabilities.isWebGL2 ? extensions.get('EXT_color_buffer_float') : extensions.get('EXT_color_buffer_half_float')))) {
+                                       !(textureType === FloatType && (capabilities.isWebGL2 || extensions.has('OES_texture_float') || extensions.has('WEBGL_color_buffer_float'))) && // Chrome Mac >= 52 and Firefox
+                                       !halfFloatSupportedByExt) {
                                                console.error('THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.');
                                                return;
                                        }
                        state.unbindTexture();
                };
 
+               this.resetState = function () {
+                       state.reset();
+                       bindingStates.reset();
+               };
+
                if (typeof __THREE_DEVTOOLS__ !== 'undefined') {
                        __THREE_DEVTOOLS__.dispatchEvent(new CustomEvent('observe', {
                                detail: this
                }
        });
 
+       var _basePosition = new Vector3();
+
+       var _skinIndex = new Vector4();
+
+       var _skinWeight = new Vector4();
+
+       var _vector$7 = new Vector3();
+
+       var _matrix$1 = new Matrix4();
+
        function SkinnedMesh(geometry, material) {
                if (geometry && geometry.isGeometry) {
                        console.error('THREE.SkinnedMesh no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.');
                                console.warn('THREE.SkinnedMesh: Unrecognized bindMode: ' + this.bindMode);
                        }
                },
-               boneTransform: function () {
-                       var basePosition = new Vector3();
-                       var skinIndex = new Vector4();
-                       var skinWeight = new Vector4();
-                       var vector = new Vector3();
-                       var matrix = new Matrix4();
-                       return function (index, target) {
-                               var skeleton = this.skeleton;
-                               var geometry = this.geometry;
-                               skinIndex.fromBufferAttribute(geometry.attributes.skinIndex, index);
-                               skinWeight.fromBufferAttribute(geometry.attributes.skinWeight, index);
-                               basePosition.fromBufferAttribute(geometry.attributes.position, index).applyMatrix4(this.bindMatrix);
-                               target.set(0, 0, 0);
-
-                               for (var i = 0; i < 4; i++) {
-                                       var weight = skinWeight.getComponent(i);
-
-                                       if (weight !== 0) {
-                                               var boneIndex = skinIndex.getComponent(i);
-                                               matrix.multiplyMatrices(skeleton.bones[boneIndex].matrixWorld, skeleton.boneInverses[boneIndex]);
-                                               target.addScaledVector(vector.copy(basePosition).applyMatrix4(matrix), weight);
-                                       }
+               boneTransform: function boneTransform(index, target) {
+                       var skeleton = this.skeleton;
+                       var geometry = this.geometry;
+
+                       _skinIndex.fromBufferAttribute(geometry.attributes.skinIndex, index);
+
+                       _skinWeight.fromBufferAttribute(geometry.attributes.skinWeight, index);
+
+                       _basePosition.fromBufferAttribute(geometry.attributes.position, index).applyMatrix4(this.bindMatrix);
+
+                       target.set(0, 0, 0);
+
+                       for (var i = 0; i < 4; i++) {
+                               var weight = _skinWeight.getComponent(i);
+
+                               if (weight !== 0) {
+                                       var boneIndex = _skinIndex.getComponent(i);
+
+                                       _matrix$1.multiplyMatrices(skeleton.bones[boneIndex].matrixWorld, skeleton.boneInverses[boneIndex]);
+
+                                       target.addScaledVector(_vector$7.copy(_basePosition).applyMatrix4(_matrix$1), weight);
                                }
+                       }
 
-                               return target.applyMatrix4(this.bindMatrixInverse);
-                       };
-               }()
+                       return target.applyMatrix4(this.bindMatrixInverse);
+               }
        });
 
        function Bone() {
                copy: function copy(source) {
                        Mesh.prototype.copy.call(this, source);
                        this.instanceMatrix.copy(source.instanceMatrix);
+                       if (source.instanceColor !== null) this.instanceColor = source.instanceColor.clone();
                        this.count = source.count;
                        return this;
                },
                setMatrixAt: function setMatrixAt(index, matrix) {
                        matrix.toArray(this.instanceMatrix.array, index * 16);
                },
-               updateMorphTargets: function updateMorphTargets() {}
+               updateMorphTargets: function updateMorphTargets() {},
+               dispose: function dispose() {
+                       this.dispatchEvent({
+                               type: 'dispose'
+                       });
+               }
        });
 
        /**
 
        var _sphere$2 = new Sphere();
 
-       function Line(geometry, material, mode) {
-               if (mode === 1) {
-                       console.error('THREE.Line: parameter THREE.LinePieces no longer supported. Use THREE.LineSegments instead.');
+       function Line(geometry, material) {
+               if (geometry === void 0) {
+                       geometry = new BufferGeometry();
+               }
+
+               if (material === void 0) {
+                       material = new LineBasicMaterial();
                }
 
                Object3D.call(this);
                this.type = 'Line';
-               this.geometry = geometry !== undefined ? geometry : new BufferGeometry();
-               this.material = material !== undefined ? material : new LineBasicMaterial();
+               this.geometry = geometry;
+               this.material = material;
                this.updateMorphTargets();
        }
 
                                        console.warn('THREE.Line.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.');
                                }
                        } else if (geometry.isGeometry) {
-                               var vertices = geometry.vertices;
-                               var _lineDistances = geometry.lineDistances;
-                               _lineDistances[0] = 0;
-
-                               for (var _i = 1, _l = vertices.length; _i < _l; _i++) {
-                                       _lineDistances[_i] = _lineDistances[_i - 1];
-                                       _lineDistances[_i] += vertices[_i - 1].distanceTo(vertices[_i]);
-                               }
+                               console.error('THREE.Line.computeLineDistances() no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.');
                        }
 
                        return this;
                                                });
                                        }
                                } else {
-                                       for (var _i2 = 0, _l2 = positionAttribute.count - 1; _i2 < _l2; _i2 += step) {
-                                               vStart.fromBufferAttribute(positionAttribute, _i2);
-                                               vEnd.fromBufferAttribute(positionAttribute, _i2 + 1);
+                                       for (var _i = 0, _l = positionAttribute.count - 1; _i < _l; _i += step) {
+                                               vStart.fromBufferAttribute(positionAttribute, _i);
+                                               vEnd.fromBufferAttribute(positionAttribute, _i + 1);
 
                                                var _distSq = _ray$1.distanceSqToSegment(vStart, vEnd, interRay, interSegment);
 
                                                        // What do we want? intersection point on the ray or on the segment??
                                                        // point: raycaster.ray.at( distance ),
                                                        point: interSegment.clone().applyMatrix4(this.matrixWorld),
-                                                       index: _i2,
+                                                       index: _i,
                                                        face: null,
                                                        faceIndex: null,
                                                        object: this
                                        }
                                }
                        } else if (geometry.isGeometry) {
-                               var vertices = geometry.vertices;
-                               var nbVertices = vertices.length;
-
-                               for (var _i3 = 0; _i3 < nbVertices - 1; _i3 += step) {
-                                       var _distSq2 = _ray$1.distanceSqToSegment(vertices[_i3], vertices[_i3 + 1], interRay, interSegment);
-
-                                       if (_distSq2 > localThresholdSq) continue;
-                                       interRay.applyMatrix4(this.matrixWorld); //Move back to world space for distance calculation
-
-                                       var _distance2 = raycaster.ray.origin.distanceTo(interRay);
-
-                                       if (_distance2 < raycaster.near || _distance2 > raycaster.far) continue;
-                                       intersects.push({
-                                               distance: _distance2,
-                                               // What do we want? intersection point on the ray or on the segment??
-                                               // point: raycaster.ray.at( distance ),
-                                               point: interSegment.clone().applyMatrix4(this.matrixWorld),
-                                               index: _i3,
-                                               face: null,
-                                               faceIndex: null,
-                                               object: this
-                                       });
-                               }
+                               console.error('THREE.Line.raycast() no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.');
                        }
                },
                updateMorphTargets: function updateMorphTargets() {
                                        console.warn('THREE.LineSegments.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.');
                                }
                        } else if (geometry.isGeometry) {
-                               var vertices = geometry.vertices;
-                               var _lineDistances = geometry.lineDistances;
-
-                               for (var _i = 0, _l = vertices.length; _i < _l; _i += 2) {
-                                       _start$1.copy(vertices[_i]);
-
-                                       _end$1.copy(vertices[_i + 1]);
-
-                                       _lineDistances[_i] = _i === 0 ? 0 : _lineDistances[_i - 1];
-                                       _lineDistances[_i + 1] = _lineDistances[_i] + _start$1.distanceTo(_end$1);
-                               }
+                               console.error('THREE.LineSegments.computeLineDistances() no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.');
                        }
 
                        return this;
        var _position$1 = new Vector3();
 
        function Points(geometry, material) {
+               if (geometry === void 0) {
+                       geometry = new BufferGeometry();
+               }
+
+               if (material === void 0) {
+                       material = new PointsMaterial();
+               }
+
                Object3D.call(this);
                this.type = 'Points';
-               this.geometry = geometry !== undefined ? geometry : new BufferGeometry();
-               this.material = material !== undefined ? material : new PointsMaterial();
+               this.geometry = geometry;
+               this.material = material;
                this.updateMorphTargets();
        }
 
                                        }
                                }
                        } else {
-                               var vertices = geometry.vertices;
-
-                               for (var _i2 = 0, _l = vertices.length; _i2 < _l; _i2++) {
-                                       testPoint(vertices[_i2], _i2, localThresholdSq, matrixWorld, raycaster, intersects, this);
-                               }
+                               console.error('THREE.Points.raycast() no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.');
                        }
                },
                updateMorphTargets: function updateMorphTargets() {
        DepthTexture.prototype.constructor = DepthTexture;
        DepthTexture.prototype.isDepthTexture = true;
 
-       var _geometryId = 0; // Geometry uses even numbers as Id
-
-       var _m1$3 = new Matrix4();
-
-       var _obj$1 = new Object3D();
-
-       var _offset$1 = new Vector3();
-
-       function Geometry() {
-               Object.defineProperty(this, 'id', {
-                       value: _geometryId += 2
-               });
-               this.uuid = MathUtils.generateUUID();
-               this.name = '';
-               this.type = 'Geometry';
-               this.vertices = [];
-               this.colors = [];
-               this.faces = [];
-               this.faceVertexUvs = [[]];
-               this.morphTargets = [];
-               this.morphNormals = [];
-               this.skinWeights = [];
-               this.skinIndices = [];
-               this.lineDistances = [];
-               this.boundingBox = null;
-               this.boundingSphere = null; // update flags
-
-               this.elementsNeedUpdate = false;
-               this.verticesNeedUpdate = false;
-               this.uvsNeedUpdate = false;
-               this.normalsNeedUpdate = false;
-               this.colorsNeedUpdate = false;
-               this.lineDistancesNeedUpdate = false;
-               this.groupsNeedUpdate = false;
-       }
-
-       Geometry.prototype = Object.assign(Object.create(EventDispatcher.prototype), {
-               constructor: Geometry,
-               isGeometry: true,
-               applyMatrix4: function applyMatrix4(matrix) {
-                       var normalMatrix = new Matrix3().getNormalMatrix(matrix);
-
-                       for (var i = 0, il = this.vertices.length; i < il; i++) {
-                               var vertex = this.vertices[i];
-                               vertex.applyMatrix4(matrix);
-                       }
-
-                       for (var _i = 0, _il = this.faces.length; _i < _il; _i++) {
-                               var face = this.faces[_i];
-                               face.normal.applyMatrix3(normalMatrix).normalize();
-
-                               for (var j = 0, jl = face.vertexNormals.length; j < jl; j++) {
-                                       face.vertexNormals[j].applyMatrix3(normalMatrix).normalize();
-                               }
-                       }
-
-                       if (this.boundingBox !== null) {
-                               this.computeBoundingBox();
-                       }
-
-                       if (this.boundingSphere !== null) {
-                               this.computeBoundingSphere();
-                       }
-
-                       this.verticesNeedUpdate = true;
-                       this.normalsNeedUpdate = true;
-                       return this;
-               },
-               rotateX: function rotateX(angle) {
-                       // rotate geometry around world x-axis
-                       _m1$3.makeRotationX(angle);
-
-                       this.applyMatrix4(_m1$3);
-                       return this;
-               },
-               rotateY: function rotateY(angle) {
-                       // rotate geometry around world y-axis
-                       _m1$3.makeRotationY(angle);
-
-                       this.applyMatrix4(_m1$3);
-                       return this;
-               },
-               rotateZ: function rotateZ(angle) {
-                       // rotate geometry around world z-axis
-                       _m1$3.makeRotationZ(angle);
-
-                       this.applyMatrix4(_m1$3);
-                       return this;
-               },
-               translate: function translate(x, y, z) {
-                       // translate geometry
-                       _m1$3.makeTranslation(x, y, z);
-
-                       this.applyMatrix4(_m1$3);
-                       return this;
-               },
-               scale: function scale(x, y, z) {
-                       // scale geometry
-                       _m1$3.makeScale(x, y, z);
-
-                       this.applyMatrix4(_m1$3);
-                       return this;
-               },
-               lookAt: function lookAt(vector) {
-                       _obj$1.lookAt(vector);
-
-                       _obj$1.updateMatrix();
-
-                       this.applyMatrix4(_obj$1.matrix);
-                       return this;
-               },
-               fromBufferGeometry: function fromBufferGeometry(geometry) {
-                       var scope = this;
-                       var index = geometry.index !== null ? geometry.index : undefined;
-                       var attributes = geometry.attributes;
-
-                       if (attributes.position === undefined) {
-                               console.error('THREE.Geometry.fromBufferGeometry(): Position attribute required for conversion.');
-                               return this;
-                       }
-
-                       var position = attributes.position;
-                       var normal = attributes.normal;
-                       var color = attributes.color;
-                       var uv = attributes.uv;
-                       var uv2 = attributes.uv2;
-                       if (uv2 !== undefined) this.faceVertexUvs[1] = [];
-
-                       for (var i = 0; i < position.count; i++) {
-                               scope.vertices.push(new Vector3().fromBufferAttribute(position, i));
-
-                               if (color !== undefined) {
-                                       scope.colors.push(new Color().fromBufferAttribute(color, i));
-                               }
-                       }
-
-                       function addFace(a, b, c, materialIndex) {
-                               var vertexColors = color === undefined ? [] : [scope.colors[a].clone(), scope.colors[b].clone(), scope.colors[c].clone()];
-                               var vertexNormals = normal === undefined ? [] : [new Vector3().fromBufferAttribute(normal, a), new Vector3().fromBufferAttribute(normal, b), new Vector3().fromBufferAttribute(normal, c)];
-                               var face = new Face3(a, b, c, vertexNormals, vertexColors, materialIndex);
-                               scope.faces.push(face);
-
-                               if (uv !== undefined) {
-                                       scope.faceVertexUvs[0].push([new Vector2().fromBufferAttribute(uv, a), new Vector2().fromBufferAttribute(uv, b), new Vector2().fromBufferAttribute(uv, c)]);
-                               }
-
-                               if (uv2 !== undefined) {
-                                       scope.faceVertexUvs[1].push([new Vector2().fromBufferAttribute(uv2, a), new Vector2().fromBufferAttribute(uv2, b), new Vector2().fromBufferAttribute(uv2, c)]);
-                               }
-                       }
-
-                       var groups = geometry.groups;
-
-                       if (groups.length > 0) {
-                               for (var _i2 = 0; _i2 < groups.length; _i2++) {
-                                       var group = groups[_i2];
-                                       var start = group.start;
-                                       var count = group.count;
-
-                                       for (var j = start, jl = start + count; j < jl; j += 3) {
-                                               if (index !== undefined) {
-                                                       addFace(index.getX(j), index.getX(j + 1), index.getX(j + 2), group.materialIndex);
-                                               } else {
-                                                       addFace(j, j + 1, j + 2, group.materialIndex);
-                                               }
-                                       }
-                               }
-                       } else {
-                               if (index !== undefined) {
-                                       for (var _i3 = 0; _i3 < index.count; _i3 += 3) {
-                                               addFace(index.getX(_i3), index.getX(_i3 + 1), index.getX(_i3 + 2));
-                                       }
-                               } else {
-                                       for (var _i4 = 0; _i4 < position.count; _i4 += 3) {
-                                               addFace(_i4, _i4 + 1, _i4 + 2);
-                                       }
-                               }
-                       }
-
-                       this.computeFaceNormals();
-
-                       if (geometry.boundingBox !== null) {
-                               this.boundingBox = geometry.boundingBox.clone();
-                       }
-
-                       if (geometry.boundingSphere !== null) {
-                               this.boundingSphere = geometry.boundingSphere.clone();
-                       }
-
-                       return this;
-               },
-               center: function center() {
-                       this.computeBoundingBox();
-                       this.boundingBox.getCenter(_offset$1).negate();
-                       this.translate(_offset$1.x, _offset$1.y, _offset$1.z);
-                       return this;
-               },
-               normalize: function normalize() {
-                       this.computeBoundingSphere();
-                       var center = this.boundingSphere.center;
-                       var radius = this.boundingSphere.radius;
-                       var s = radius === 0 ? 1 : 1.0 / radius;
-                       var matrix = new Matrix4();
-                       matrix.set(s, 0, 0, -s * center.x, 0, s, 0, -s * center.y, 0, 0, s, -s * center.z, 0, 0, 0, 1);
-                       this.applyMatrix4(matrix);
-                       return this;
-               },
-               computeFaceNormals: function computeFaceNormals() {
-                       var cb = new Vector3(),
-                                       ab = new Vector3();
-
-                       for (var f = 0, fl = this.faces.length; f < fl; f++) {
-                               var face = this.faces[f];
-                               var vA = this.vertices[face.a];
-                               var vB = this.vertices[face.b];
-                               var vC = this.vertices[face.c];
-                               cb.subVectors(vC, vB);
-                               ab.subVectors(vA, vB);
-                               cb.cross(ab);
-                               cb.normalize();
-                               face.normal.copy(cb);
-                       }
-               },
-               computeVertexNormals: function computeVertexNormals(areaWeighted) {
-                       if (areaWeighted === void 0) {
-                               areaWeighted = true;
-                       }
-
-                       var vertices = new Array(this.vertices.length);
-
-                       for (var v = 0, vl = this.vertices.length; v < vl; v++) {
-                               vertices[v] = new Vector3();
-                       }
-
-                       if (areaWeighted) {
-                               // vertex normals weighted by triangle areas
-                               // http://www.iquilezles.org/www/articles/normals/normals.htm
-                               var cb = new Vector3(),
-                                               ab = new Vector3();
-
-                               for (var f = 0, fl = this.faces.length; f < fl; f++) {
-                                       var face = this.faces[f];
-                                       var vA = this.vertices[face.a];
-                                       var vB = this.vertices[face.b];
-                                       var vC = this.vertices[face.c];
-                                       cb.subVectors(vC, vB);
-                                       ab.subVectors(vA, vB);
-                                       cb.cross(ab);
-                                       vertices[face.a].add(cb);
-                                       vertices[face.b].add(cb);
-                                       vertices[face.c].add(cb);
-                               }
-                       } else {
-                               this.computeFaceNormals();
-
-                               for (var _f = 0, _fl = this.faces.length; _f < _fl; _f++) {
-                                       var _face = this.faces[_f];
-
-                                       vertices[_face.a].add(_face.normal);
-
-                                       vertices[_face.b].add(_face.normal);
-
-                                       vertices[_face.c].add(_face.normal);
-                               }
-                       }
-
-                       for (var _v = 0, _vl = this.vertices.length; _v < _vl; _v++) {
-                               vertices[_v].normalize();
-                       }
-
-                       for (var _f2 = 0, _fl2 = this.faces.length; _f2 < _fl2; _f2++) {
-                               var _face2 = this.faces[_f2];
-                               var vertexNormals = _face2.vertexNormals;
-
-                               if (vertexNormals.length === 3) {
-                                       vertexNormals[0].copy(vertices[_face2.a]);
-                                       vertexNormals[1].copy(vertices[_face2.b]);
-                                       vertexNormals[2].copy(vertices[_face2.c]);
-                               } else {
-                                       vertexNormals[0] = vertices[_face2.a].clone();
-                                       vertexNormals[1] = vertices[_face2.b].clone();
-                                       vertexNormals[2] = vertices[_face2.c].clone();
-                               }
-                       }
-
-                       if (this.faces.length > 0) {
-                               this.normalsNeedUpdate = true;
-                       }
-               },
-               computeFlatVertexNormals: function computeFlatVertexNormals() {
-                       this.computeFaceNormals();
-
-                       for (var f = 0, fl = this.faces.length; f < fl; f++) {
-                               var face = this.faces[f];
-                               var vertexNormals = face.vertexNormals;
-
-                               if (vertexNormals.length === 3) {
-                                       vertexNormals[0].copy(face.normal);
-                                       vertexNormals[1].copy(face.normal);
-                                       vertexNormals[2].copy(face.normal);
-                               } else {
-                                       vertexNormals[0] = face.normal.clone();
-                                       vertexNormals[1] = face.normal.clone();
-                                       vertexNormals[2] = face.normal.clone();
-                               }
-                       }
-
-                       if (this.faces.length > 0) {
-                               this.normalsNeedUpdate = true;
-                       }
-               },
-               computeMorphNormals: function computeMorphNormals() {
-                       // save original normals
-                       // - create temp variables on first access
-                       //       otherwise just copy (for faster repeated calls)
-                       for (var f = 0, fl = this.faces.length; f < fl; f++) {
-                               var face = this.faces[f];
-
-                               if (!face.__originalFaceNormal) {
-                                       face.__originalFaceNormal = face.normal.clone();
-                               } else {
-                                       face.__originalFaceNormal.copy(face.normal);
-                               }
-
-                               if (!face.__originalVertexNormals) face.__originalVertexNormals = [];
-
-                               for (var i = 0, il = face.vertexNormals.length; i < il; i++) {
-                                       if (!face.__originalVertexNormals[i]) {
-                                               face.__originalVertexNormals[i] = face.vertexNormals[i].clone();
-                                       } else {
-                                               face.__originalVertexNormals[i].copy(face.vertexNormals[i]);
-                                       }
-                               }
-                       } // use temp geometry to compute face and vertex normals for each morph
-
-
-                       var tmpGeo = new Geometry();
-                       tmpGeo.faces = this.faces;
-
-                       for (var _i5 = 0, _il2 = this.morphTargets.length; _i5 < _il2; _i5++) {
-                               // create on first access
-                               if (!this.morphNormals[_i5]) {
-                                       this.morphNormals[_i5] = {};
-                                       this.morphNormals[_i5].faceNormals = [];
-                                       this.morphNormals[_i5].vertexNormals = [];
-                                       var dstNormalsFace = this.morphNormals[_i5].faceNormals;
-                                       var dstNormalsVertex = this.morphNormals[_i5].vertexNormals;
-
-                                       for (var _f3 = 0, _fl3 = this.faces.length; _f3 < _fl3; _f3++) {
-                                               var faceNormal = new Vector3();
-                                               var vertexNormals = {
-                                                       a: new Vector3(),
-                                                       b: new Vector3(),
-                                                       c: new Vector3()
-                                               };
-                                               dstNormalsFace.push(faceNormal);
-                                               dstNormalsVertex.push(vertexNormals);
-                                       }
-                               }
-
-                               var morphNormals = this.morphNormals[_i5]; // set vertices to morph target
-
-                               tmpGeo.vertices = this.morphTargets[_i5].vertices; // compute morph normals
-
-                               tmpGeo.computeFaceNormals();
-                               tmpGeo.computeVertexNormals(); // store morph normals
-
-                               for (var _f4 = 0, _fl4 = this.faces.length; _f4 < _fl4; _f4++) {
-                                       var _face3 = this.faces[_f4];
-                                       var _faceNormal = morphNormals.faceNormals[_f4];
-                                       var _vertexNormals = morphNormals.vertexNormals[_f4];
-
-                                       _faceNormal.copy(_face3.normal);
-
-                                       _vertexNormals.a.copy(_face3.vertexNormals[0]);
-
-                                       _vertexNormals.b.copy(_face3.vertexNormals[1]);
-
-                                       _vertexNormals.c.copy(_face3.vertexNormals[2]);
-                               }
-                       } // restore original normals
-
-
-                       for (var _f5 = 0, _fl5 = this.faces.length; _f5 < _fl5; _f5++) {
-                               var _face4 = this.faces[_f5];
-                               _face4.normal = _face4.__originalFaceNormal;
-                               _face4.vertexNormals = _face4.__originalVertexNormals;
-                       }
-               },
-               computeBoundingBox: function computeBoundingBox() {
-                       if (this.boundingBox === null) {
-                               this.boundingBox = new Box3();
-                       }
-
-                       this.boundingBox.setFromPoints(this.vertices);
-               },
-               computeBoundingSphere: function computeBoundingSphere() {
-                       if (this.boundingSphere === null) {
-                               this.boundingSphere = new Sphere();
-                       }
-
-                       this.boundingSphere.setFromPoints(this.vertices);
-               },
-               merge: function merge(geometry, matrix, materialIndexOffset) {
-                       if (materialIndexOffset === void 0) {
-                               materialIndexOffset = 0;
-                       }
-
-                       if (!(geometry && geometry.isGeometry)) {
-                               console.error('THREE.Geometry.merge(): geometry not an instance of THREE.Geometry.', geometry);
-                               return;
-                       }
-
-                       var normalMatrix;
-                       var vertexOffset = this.vertices.length,
-                                       vertices1 = this.vertices,
-                                       vertices2 = geometry.vertices,
-                                       faces1 = this.faces,
-                                       faces2 = geometry.faces,
-                                       colors1 = this.colors,
-                                       colors2 = geometry.colors;
-
-                       if (matrix !== undefined) {
-                               normalMatrix = new Matrix3().getNormalMatrix(matrix);
-                       } // vertices
-
-
-                       for (var i = 0, il = vertices2.length; i < il; i++) {
-                               var vertex = vertices2[i];
-                               var vertexCopy = vertex.clone();
-                               if (matrix !== undefined) vertexCopy.applyMatrix4(matrix);
-                               vertices1.push(vertexCopy);
-                       } // colors
-
-
-                       for (var _i6 = 0, _il3 = colors2.length; _i6 < _il3; _i6++) {
-                               colors1.push(colors2[_i6].clone());
-                       } // faces
-
-
-                       for (var _i7 = 0, _il4 = faces2.length; _i7 < _il4; _i7++) {
-                               var face = faces2[_i7];
-                               var normal = void 0,
-                                               color = void 0;
-                               var faceVertexNormals = face.vertexNormals,
-                                               faceVertexColors = face.vertexColors;
-                               var faceCopy = new Face3(face.a + vertexOffset, face.b + vertexOffset, face.c + vertexOffset);
-                               faceCopy.normal.copy(face.normal);
-
-                               if (normalMatrix !== undefined) {
-                                       faceCopy.normal.applyMatrix3(normalMatrix).normalize();
-                               }
-
-                               for (var j = 0, jl = faceVertexNormals.length; j < jl; j++) {
-                                       normal = faceVertexNormals[j].clone();
-
-                                       if (normalMatrix !== undefined) {
-                                               normal.applyMatrix3(normalMatrix).normalize();
-                                       }
-
-                                       faceCopy.vertexNormals.push(normal);
-                               }
-
-                               faceCopy.color.copy(face.color);
-
-                               for (var _j = 0, _jl = faceVertexColors.length; _j < _jl; _j++) {
-                                       color = faceVertexColors[_j];
-                                       faceCopy.vertexColors.push(color.clone());
-                               }
-
-                               faceCopy.materialIndex = face.materialIndex + materialIndexOffset;
-                               faces1.push(faceCopy);
-                       } // uvs
-
-
-                       for (var _i8 = 0, _il5 = geometry.faceVertexUvs.length; _i8 < _il5; _i8++) {
-                               var faceVertexUvs2 = geometry.faceVertexUvs[_i8];
-                               if (this.faceVertexUvs[_i8] === undefined) this.faceVertexUvs[_i8] = [];
-
-                               for (var _j2 = 0, _jl2 = faceVertexUvs2.length; _j2 < _jl2; _j2++) {
-                                       var uvs2 = faceVertexUvs2[_j2],
-                                                       uvsCopy = [];
-
-                                       for (var k = 0, kl = uvs2.length; k < kl; k++) {
-                                               uvsCopy.push(uvs2[k].clone());
-                                       }
-
-                                       this.faceVertexUvs[_i8].push(uvsCopy);
-                               }
-                       }
-               },
-               mergeMesh: function mergeMesh(mesh) {
-                       if (!(mesh && mesh.isMesh)) {
-                               console.error('THREE.Geometry.mergeMesh(): mesh not an instance of THREE.Mesh.', mesh);
-                               return;
-                       }
-
-                       if (mesh.matrixAutoUpdate) mesh.updateMatrix();
-                       this.merge(mesh.geometry, mesh.matrix);
-               },
-
-               /*
-                * Checks for duplicate vertices with hashmap.
-                * Duplicated vertices are removed
-                * and faces' vertices are updated.
-                */
-               mergeVertices: function mergeVertices(precisionPoints) {
-                       if (precisionPoints === void 0) {
-                               precisionPoints = 4;
-                       }
-
-                       var verticesMap = {}; // Hashmap for looking up vertices by position coordinates (and making sure they are unique)
-
-                       var unique = [],
-                                       changes = [];
-                       var precision = Math.pow(10, precisionPoints);
-
-                       for (var i = 0, il = this.vertices.length; i < il; i++) {
-                               var v = this.vertices[i];
-                               var key = Math.round(v.x * precision) + '_' + Math.round(v.y * precision) + '_' + Math.round(v.z * precision);
-
-                               if (verticesMap[key] === undefined) {
-                                       verticesMap[key] = i;
-                                       unique.push(this.vertices[i]);
-                                       changes[i] = unique.length - 1;
-                               } else {
-                                       //console.log('Duplicate vertex found. ', i, ' could be using ', verticesMap[key]);
-                                       changes[i] = changes[verticesMap[key]];
-                               }
-                       } // if faces are completely degenerate after merging vertices, we
-                       // have to remove them from the geometry.
-
-
-                       var faceIndicesToRemove = [];
-
-                       for (var _i9 = 0, _il6 = this.faces.length; _i9 < _il6; _i9++) {
-                               var face = this.faces[_i9];
-                               face.a = changes[face.a];
-                               face.b = changes[face.b];
-                               face.c = changes[face.c];
-                               var indices = [face.a, face.b, face.c]; // if any duplicate vertices are found in a Face3
-                               // we have to remove the face as nothing can be saved
-
-                               for (var n = 0; n < 3; n++) {
-                                       if (indices[n] === indices[(n + 1) % 3]) {
-                                               faceIndicesToRemove.push(_i9);
-                                               break;
-                                       }
-                               }
-                       }
-
-                       for (var _i10 = faceIndicesToRemove.length - 1; _i10 >= 0; _i10--) {
-                               var idx = faceIndicesToRemove[_i10];
-                               this.faces.splice(idx, 1);
-
-                               for (var j = 0, jl = this.faceVertexUvs.length; j < jl; j++) {
-                                       this.faceVertexUvs[j].splice(idx, 1);
-                               }
-                       } // Use unique set of vertices
-
-
-                       var diff = this.vertices.length - unique.length;
-                       this.vertices = unique;
-                       return diff;
-               },
-               setFromPoints: function setFromPoints(points) {
-                       this.vertices = [];
-
-                       for (var i = 0, l = points.length; i < l; i++) {
-                               var point = points[i];
-                               this.vertices.push(new Vector3(point.x, point.y, point.z || 0));
-                       }
-
-                       return this;
-               },
-               sortFacesByMaterialIndex: function sortFacesByMaterialIndex() {
-                       var faces = this.faces;
-                       var length = faces.length; // tag faces
-
-                       for (var i = 0; i < length; i++) {
-                               faces[i]._id = i;
-                       } // sort faces
-
-
-                       function materialIndexSort(a, b) {
-                               return a.materialIndex - b.materialIndex;
-                       }
-
-                       faces.sort(materialIndexSort); // sort uvs
-
-                       var uvs1 = this.faceVertexUvs[0];
-                       var uvs2 = this.faceVertexUvs[1];
-                       var newUvs1, newUvs2;
-                       if (uvs1 && uvs1.length === length) newUvs1 = [];
-                       if (uvs2 && uvs2.length === length) newUvs2 = [];
-
-                       for (var _i11 = 0; _i11 < length; _i11++) {
-                               var id = faces[_i11]._id;
-                               if (newUvs1) newUvs1.push(uvs1[id]);
-                               if (newUvs2) newUvs2.push(uvs2[id]);
-                       }
-
-                       if (newUvs1) this.faceVertexUvs[0] = newUvs1;
-                       if (newUvs2) this.faceVertexUvs[1] = newUvs2;
-               },
-               toJSON: function toJSON() {
-                       var data = {
-                               metadata: {
-                                       version: 4.5,
-                                       type: 'Geometry',
-                                       generator: 'Geometry.toJSON'
-                               }
-                       }; // standard Geometry serialization
-
-                       data.uuid = this.uuid;
-                       data.type = this.type;
-                       if (this.name !== '') data.name = this.name;
-
-                       if (this.parameters !== undefined) {
-                               var parameters = this.parameters;
-
-                               for (var key in parameters) {
-                                       if (parameters[key] !== undefined) data[key] = parameters[key];
-                               }
-
-                               return data;
-                       }
-
-                       var vertices = [];
-
-                       for (var i = 0; i < this.vertices.length; i++) {
-                               var vertex = this.vertices[i];
-                               vertices.push(vertex.x, vertex.y, vertex.z);
-                       }
-
-                       var faces = [];
-                       var normals = [];
-                       var normalsHash = {};
-                       var colors = [];
-                       var colorsHash = {};
-                       var uvs = [];
-                       var uvsHash = {};
-
-                       for (var _i12 = 0; _i12 < this.faces.length; _i12++) {
-                               var face = this.faces[_i12];
-                               var hasMaterial = true;
-                               var hasFaceUv = false; // deprecated
-
-                               var hasFaceVertexUv = this.faceVertexUvs[0][_i12] !== undefined;
-                               var hasFaceNormal = face.normal.length() > 0;
-                               var hasFaceVertexNormal = face.vertexNormals.length > 0;
-                               var hasFaceColor = face.color.r !== 1 || face.color.g !== 1 || face.color.b !== 1;
-                               var hasFaceVertexColor = face.vertexColors.length > 0;
-                               var faceType = 0;
-                               faceType = setBit(faceType, 0, 0); // isQuad
-
-                               faceType = setBit(faceType, 1, hasMaterial);
-                               faceType = setBit(faceType, 2, hasFaceUv);
-                               faceType = setBit(faceType, 3, hasFaceVertexUv);
-                               faceType = setBit(faceType, 4, hasFaceNormal);
-                               faceType = setBit(faceType, 5, hasFaceVertexNormal);
-                               faceType = setBit(faceType, 6, hasFaceColor);
-                               faceType = setBit(faceType, 7, hasFaceVertexColor);
-                               faces.push(faceType);
-                               faces.push(face.a, face.b, face.c);
-                               faces.push(face.materialIndex);
-
-                               if (hasFaceVertexUv) {
-                                       var faceVertexUvs = this.faceVertexUvs[0][_i12];
-                                       faces.push(getUvIndex(faceVertexUvs[0]), getUvIndex(faceVertexUvs[1]), getUvIndex(faceVertexUvs[2]));
-                               }
-
-                               if (hasFaceNormal) {
-                                       faces.push(getNormalIndex(face.normal));
-                               }
-
-                               if (hasFaceVertexNormal) {
-                                       var vertexNormals = face.vertexNormals;
-                                       faces.push(getNormalIndex(vertexNormals[0]), getNormalIndex(vertexNormals[1]), getNormalIndex(vertexNormals[2]));
-                               }
+       var CircleGeometry = /*#__PURE__*/function (_BufferGeometry) {
+               _inheritsLoose(CircleGeometry, _BufferGeometry);
 
-                               if (hasFaceColor) {
-                                       faces.push(getColorIndex(face.color));
-                               }
-
-                               if (hasFaceVertexColor) {
-                                       var vertexColors = face.vertexColors;
-                                       faces.push(getColorIndex(vertexColors[0]), getColorIndex(vertexColors[1]), getColorIndex(vertexColors[2]));
-                               }
-                       }
-
-                       function setBit(value, position, enabled) {
-                               return enabled ? value | 1 << position : value & ~(1 << position);
-                       }
-
-                       function getNormalIndex(normal) {
-                               var hash = normal.x.toString() + normal.y.toString() + normal.z.toString();
-
-                               if (normalsHash[hash] !== undefined) {
-                                       return normalsHash[hash];
-                               }
-
-                               normalsHash[hash] = normals.length / 3;
-                               normals.push(normal.x, normal.y, normal.z);
-                               return normalsHash[hash];
-                       }
-
-                       function getColorIndex(color) {
-                               var hash = color.r.toString() + color.g.toString() + color.b.toString();
-
-                               if (colorsHash[hash] !== undefined) {
-                                       return colorsHash[hash];
-                               }
-
-                               colorsHash[hash] = colors.length;
-                               colors.push(color.getHex());
-                               return colorsHash[hash];
-                       }
-
-                       function getUvIndex(uv) {
-                               var hash = uv.x.toString() + uv.y.toString();
-
-                               if (uvsHash[hash] !== undefined) {
-                                       return uvsHash[hash];
-                               }
-
-                               uvsHash[hash] = uvs.length / 2;
-                               uvs.push(uv.x, uv.y);
-                               return uvsHash[hash];
-                       }
-
-                       data.data = {};
-                       data.data.vertices = vertices;
-                       data.data.normals = normals;
-                       if (colors.length > 0) data.data.colors = colors;
-                       if (uvs.length > 0) data.data.uvs = [uvs]; // temporal backward compatibility
-
-                       data.data.faces = faces;
-                       return data;
-               },
-               clone: function clone() {
-                       /*
-                        // Handle primitives
-                                const parameters = this.parameters;
-                                if ( parameters !== undefined ) {
-                                const values = [];
-                                for ( const key in parameters ) {
-                                values.push( parameters[ key ] );
-                                }
-                                const geometry = Object.create( this.constructor.prototype );
-                        this.constructor.apply( geometry, values );
-                        return geometry;
-                                }
-                                return new this.constructor().copy( this );
-                        */
-                       return new Geometry().copy(this);
-               },
-               copy: function copy(source) {
-                       // reset
-                       this.vertices = [];
-                       this.colors = [];
-                       this.faces = [];
-                       this.faceVertexUvs = [[]];
-                       this.morphTargets = [];
-                       this.morphNormals = [];
-                       this.skinWeights = [];
-                       this.skinIndices = [];
-                       this.lineDistances = [];
-                       this.boundingBox = null;
-                       this.boundingSphere = null; // name
-
-                       this.name = source.name; // vertices
-
-                       var vertices = source.vertices;
-
-                       for (var i = 0, il = vertices.length; i < il; i++) {
-                               this.vertices.push(vertices[i].clone());
-                       } // colors
-
-
-                       var colors = source.colors;
-
-                       for (var _i13 = 0, _il7 = colors.length; _i13 < _il7; _i13++) {
-                               this.colors.push(colors[_i13].clone());
-                       } // faces
-
-
-                       var faces = source.faces;
-
-                       for (var _i14 = 0, _il8 = faces.length; _i14 < _il8; _i14++) {
-                               this.faces.push(faces[_i14].clone());
-                       } // face vertex uvs
-
-
-                       for (var _i15 = 0, _il9 = source.faceVertexUvs.length; _i15 < _il9; _i15++) {
-                               var faceVertexUvs = source.faceVertexUvs[_i15];
-
-                               if (this.faceVertexUvs[_i15] === undefined) {
-                                       this.faceVertexUvs[_i15] = [];
-                               }
-
-                               for (var j = 0, jl = faceVertexUvs.length; j < jl; j++) {
-                                       var uvs = faceVertexUvs[j],
-                                                       uvsCopy = [];
-
-                                       for (var k = 0, kl = uvs.length; k < kl; k++) {
-                                               var uv = uvs[k];
-                                               uvsCopy.push(uv.clone());
-                                       }
-
-                                       this.faceVertexUvs[_i15].push(uvsCopy);
-                               }
-                       } // morph targets
-
-
-                       var morphTargets = source.morphTargets;
-
-                       for (var _i16 = 0, _il10 = morphTargets.length; _i16 < _il10; _i16++) {
-                               var morphTarget = {};
-                               morphTarget.name = morphTargets[_i16].name; // vertices
-
-                               if (morphTargets[_i16].vertices !== undefined) {
-                                       morphTarget.vertices = [];
-
-                                       for (var _j3 = 0, _jl3 = morphTargets[_i16].vertices.length; _j3 < _jl3; _j3++) {
-                                               morphTarget.vertices.push(morphTargets[_i16].vertices[_j3].clone());
-                                       }
-                               } // normals
-
-
-                               if (morphTargets[_i16].normals !== undefined) {
-                                       morphTarget.normals = [];
-
-                                       for (var _j4 = 0, _jl4 = morphTargets[_i16].normals.length; _j4 < _jl4; _j4++) {
-                                               morphTarget.normals.push(morphTargets[_i16].normals[_j4].clone());
-                                       }
-                               }
-
-                               this.morphTargets.push(morphTarget);
-                       } // morph normals
-
-
-                       var morphNormals = source.morphNormals;
-
-                       for (var _i17 = 0, _il11 = morphNormals.length; _i17 < _il11; _i17++) {
-                               var morphNormal = {}; // vertex normals
-
-                               if (morphNormals[_i17].vertexNormals !== undefined) {
-                                       morphNormal.vertexNormals = [];
-
-                                       for (var _j5 = 0, _jl5 = morphNormals[_i17].vertexNormals.length; _j5 < _jl5; _j5++) {
-                                               var srcVertexNormal = morphNormals[_i17].vertexNormals[_j5];
-                                               var destVertexNormal = {};
-                                               destVertexNormal.a = srcVertexNormal.a.clone();
-                                               destVertexNormal.b = srcVertexNormal.b.clone();
-                                               destVertexNormal.c = srcVertexNormal.c.clone();
-                                               morphNormal.vertexNormals.push(destVertexNormal);
-                                       }
-                               } // face normals
-
-
-                               if (morphNormals[_i17].faceNormals !== undefined) {
-                                       morphNormal.faceNormals = [];
-
-                                       for (var _j6 = 0, _jl6 = morphNormals[_i17].faceNormals.length; _j6 < _jl6; _j6++) {
-                                               morphNormal.faceNormals.push(morphNormals[_i17].faceNormals[_j6].clone());
-                                       }
-                               }
-
-                               this.morphNormals.push(morphNormal);
-                       } // skin weights
-
-
-                       var skinWeights = source.skinWeights;
-
-                       for (var _i18 = 0, _il12 = skinWeights.length; _i18 < _il12; _i18++) {
-                               this.skinWeights.push(skinWeights[_i18].clone());
-                       } // skin indices
-
-
-                       var skinIndices = source.skinIndices;
-
-                       for (var _i19 = 0, _il13 = skinIndices.length; _i19 < _il13; _i19++) {
-                               this.skinIndices.push(skinIndices[_i19].clone());
-                       } // line distances
-
-
-                       var lineDistances = source.lineDistances;
-
-                       for (var _i20 = 0, _il14 = lineDistances.length; _i20 < _il14; _i20++) {
-                               this.lineDistances.push(lineDistances[_i20]);
-                       } // bounding box
-
-
-                       var boundingBox = source.boundingBox;
-
-                       if (boundingBox !== null) {
-                               this.boundingBox = boundingBox.clone();
-                       } // bounding sphere
-
-
-                       var boundingSphere = source.boundingSphere;
-
-                       if (boundingSphere !== null) {
-                               this.boundingSphere = boundingSphere.clone();
-                       } // update flags
-
-
-                       this.elementsNeedUpdate = source.elementsNeedUpdate;
-                       this.verticesNeedUpdate = source.verticesNeedUpdate;
-                       this.uvsNeedUpdate = source.uvsNeedUpdate;
-                       this.normalsNeedUpdate = source.normalsNeedUpdate;
-                       this.colorsNeedUpdate = source.colorsNeedUpdate;
-                       this.lineDistancesNeedUpdate = source.lineDistancesNeedUpdate;
-                       this.groupsNeedUpdate = source.groupsNeedUpdate;
-                       return this;
-               },
-               dispose: function dispose() {
-                       this.dispatchEvent({
-                               type: 'dispose'
-                       });
-               }
-       });
-
-       var BoxGeometry = /*#__PURE__*/function (_Geometry) {
-               _inheritsLoose(BoxGeometry, _Geometry);
-
-               function BoxGeometry(width, height, depth, widthSegments, heightSegments, depthSegments) {
-                       var _this;
-
-                       _this = _Geometry.call(this) || this;
-                       _this.type = 'BoxGeometry';
-                       _this.parameters = {
-                               width: width,
-                               height: height,
-                               depth: depth,
-                               widthSegments: widthSegments,
-                               heightSegments: heightSegments,
-                               depthSegments: depthSegments
-                       };
-
-                       _this.fromBufferGeometry(new BoxBufferGeometry(width, height, depth, widthSegments, heightSegments, depthSegments));
-
-                       _this.mergeVertices();
-
-                       return _this;
-               }
-
-               return BoxGeometry;
-       }(Geometry);
-
-       var CircleBufferGeometry = /*#__PURE__*/function (_BufferGeometry) {
-               _inheritsLoose(CircleBufferGeometry, _BufferGeometry);
-
-               function CircleBufferGeometry(radius, segments, thetaStart, thetaLength) {
+               function CircleGeometry(radius, segments, thetaStart, thetaLength) {
                        var _this;
 
                        if (radius === void 0) {
                        }
 
                        _this = _BufferGeometry.call(this) || this;
-                       _this.type = 'CircleBufferGeometry';
+                       _this.type = 'CircleGeometry';
                        _this.parameters = {
                                radius: radius,
                                segments: segments,
                        return _this;
                }
 
-               return CircleBufferGeometry;
-       }(BufferGeometry);
-
-       var CircleGeometry = /*#__PURE__*/function (_Geometry) {
-               _inheritsLoose(CircleGeometry, _Geometry);
-
-               function CircleGeometry(radius, segments, thetaStart, thetaLength) {
-                       var _this;
-
-                       _this = _Geometry.call(this) || this;
-                       _this.type = 'CircleGeometry';
-                       _this.parameters = {
-                               radius: radius,
-                               segments: segments,
-                               thetaStart: thetaStart,
-                               thetaLength: thetaLength
-                       };
-
-                       _this.fromBufferGeometry(new CircleBufferGeometry(radius, segments, thetaStart, thetaLength));
-
-                       _this.mergeVertices();
-
-                       return _this;
-               }
-
                return CircleGeometry;
-       }(Geometry);
+       }(BufferGeometry);
 
-       var CylinderBufferGeometry = /*#__PURE__*/function (_BufferGeometry) {
-               _inheritsLoose(CylinderBufferGeometry, _BufferGeometry);
+       var CylinderGeometry = /*#__PURE__*/function (_BufferGeometry) {
+               _inheritsLoose(CylinderGeometry, _BufferGeometry);
 
-               function CylinderBufferGeometry(radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength) {
+               function CylinderGeometry(radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength) {
                        var _this;
 
                        if (radiusTop === void 0) {
                        }
 
                        _this = _BufferGeometry.call(this) || this;
-                       _this.type = 'CylinderBufferGeometry';
+                       _this.type = 'CylinderGeometry';
                        _this.parameters = {
                                radiusTop: radiusTop,
                                radiusBottom: radiusBottom,
                        return _this;
                }
 
-               return CylinderBufferGeometry;
-       }(BufferGeometry);
-
-       var CylinderGeometry = /*#__PURE__*/function (_Geometry) {
-               _inheritsLoose(CylinderGeometry, _Geometry);
-
-               function CylinderGeometry(radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength) {
-                       var _this;
-
-                       _this = _Geometry.call(this) || this;
-                       _this.type = 'CylinderGeometry';
-                       _this.parameters = {
-                               radiusTop: radiusTop,
-                               radiusBottom: radiusBottom,
-                               height: height,
-                               radialSegments: radialSegments,
-                               heightSegments: heightSegments,
-                               openEnded: openEnded,
-                               thetaStart: thetaStart,
-                               thetaLength: thetaLength
-                       };
-
-                       _this.fromBufferGeometry(new CylinderBufferGeometry(radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength));
-
-                       _this.mergeVertices();
-
-                       return _this;
-               }
-
                return CylinderGeometry;
-       }(Geometry);
+       }(BufferGeometry);
 
        var ConeGeometry = /*#__PURE__*/function (_CylinderGeometry) {
                _inheritsLoose(ConeGeometry, _CylinderGeometry);
                function ConeGeometry(radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength) {
                        var _this;
 
-                       _this = _CylinderGeometry.call(this, 0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength) || this;
-                       _this.type = 'ConeGeometry';
-                       _this.parameters = {
-                               radius: radius,
-                               height: height,
-                               radialSegments: radialSegments,
-                               heightSegments: heightSegments,
-                               openEnded: openEnded,
-                               thetaStart: thetaStart,
-                               thetaLength: thetaLength
-                       };
-                       return _this;
-               }
-
-               return ConeGeometry;
-       }(CylinderGeometry);
-
-       var ConeBufferGeometry = /*#__PURE__*/function (_CylinderBufferGeomet) {
-               _inheritsLoose(ConeBufferGeometry, _CylinderBufferGeomet);
-
-               function ConeBufferGeometry(radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength) {
-                       var _this;
-
                        if (radius === void 0) {
                                radius = 1;
                        }
                                thetaLength = Math.PI * 2;
                        }
 
-                       _this = _CylinderBufferGeomet.call(this, 0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength) || this;
-                       _this.type = 'ConeBufferGeometry';
+                       _this = _CylinderGeometry.call(this, 0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength) || this;
+                       _this.type = 'ConeGeometry';
                        _this.parameters = {
                                radius: radius,
                                height: height,
                        return _this;
                }
 
-               return ConeBufferGeometry;
-       }(CylinderBufferGeometry);
+               return ConeGeometry;
+       }(CylinderGeometry);
 
-       var PolyhedronBufferGeometry = /*#__PURE__*/function (_BufferGeometry) {
-               _inheritsLoose(PolyhedronBufferGeometry, _BufferGeometry);
+       var PolyhedronGeometry = /*#__PURE__*/function (_BufferGeometry) {
+               _inheritsLoose(PolyhedronGeometry, _BufferGeometry);
 
-               function PolyhedronBufferGeometry(vertices, indices, radius, detail) {
+               function PolyhedronGeometry(vertices, indices, radius, detail) {
                        var _this;
 
                        if (radius === void 0) {
                        }
 
                        _this = _BufferGeometry.call(this) || this;
-                       _this.type = 'PolyhedronBufferGeometry';
+                       _this.type = 'PolyhedronGeometry';
                        _this.parameters = {
                                vertices: vertices,
                                indices: indices,
                        return _this;
                }
 
-               return PolyhedronBufferGeometry;
+               return PolyhedronGeometry;
        }(BufferGeometry);
 
-       var DodecahedronBufferGeometry = /*#__PURE__*/function (_PolyhedronBufferGeom) {
-               _inheritsLoose(DodecahedronBufferGeometry, _PolyhedronBufferGeom);
+       var DodecahedronGeometry = /*#__PURE__*/function (_PolyhedronGeometry) {
+               _inheritsLoose(DodecahedronGeometry, _PolyhedronGeometry);
 
-               function DodecahedronBufferGeometry(radius, detail) {
+               function DodecahedronGeometry(radius, detail) {
                        var _this;
 
                        if (radius === void 0) {
                        -r, -t, 0, -r, t, 0, r, -t, 0, r, t, 0, // (±φ, 0, ±1/φ)
                        -t, 0, -r, t, 0, -r, -t, 0, r, t, 0, r];
                        var indices = [3, 11, 7, 3, 7, 15, 3, 15, 13, 7, 19, 17, 7, 17, 6, 7, 6, 15, 17, 4, 8, 17, 8, 10, 17, 10, 6, 8, 0, 16, 8, 16, 2, 8, 2, 10, 0, 12, 1, 0, 1, 18, 0, 18, 16, 6, 10, 2, 6, 2, 13, 6, 13, 15, 2, 16, 18, 2, 18, 3, 2, 3, 13, 18, 1, 9, 18, 9, 11, 18, 11, 3, 4, 14, 12, 4, 12, 0, 4, 0, 8, 11, 9, 5, 11, 5, 19, 11, 19, 7, 19, 5, 14, 19, 14, 4, 19, 4, 17, 1, 12, 14, 1, 14, 5, 1, 5, 9];
-                       _this = _PolyhedronBufferGeom.call(this, vertices, indices, radius, detail) || this;
-                       _this.type = 'DodecahedronBufferGeometry';
-                       _this.parameters = {
-                               radius: radius,
-                               detail: detail
-                       };
-                       return _this;
-               }
-
-               return DodecahedronBufferGeometry;
-       }(PolyhedronBufferGeometry);
-
-       var DodecahedronGeometry = /*#__PURE__*/function (_Geometry) {
-               _inheritsLoose(DodecahedronGeometry, _Geometry);
-
-               function DodecahedronGeometry(radius, detail) {
-                       var _this;
-
-                       _this = _Geometry.call(this) || this;
+                       _this = _PolyhedronGeometry.call(this, vertices, indices, radius, detail) || this;
                        _this.type = 'DodecahedronGeometry';
                        _this.parameters = {
                                radius: radius,
                                detail: detail
                        };
-
-                       _this.fromBufferGeometry(new DodecahedronBufferGeometry(radius, detail));
-
-                       _this.mergeVertices();
-
                        return _this;
                }
 
                return DodecahedronGeometry;
-       }(Geometry);
+       }(PolyhedronGeometry);
 
        var _v0$2 = new Vector3();
 
                        };
                        thresholdAngle = thresholdAngle !== undefined ? thresholdAngle : 1;
 
-                       if (geometry.isGeometry) {
-                               geometry = new BufferGeometry().fromGeometry(geometry);
+                       if (geometry.isGeometry === true) {
+                               console.error('THREE.EdgesGeometry no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.');
+                               return _assertThisInitialized(_this);
                        }
 
                        var precisionPoints = 4;
                }
        }
 
-       var ExtrudeBufferGeometry = /*#__PURE__*/function (_BufferGeometry) {
-               _inheritsLoose(ExtrudeBufferGeometry, _BufferGeometry);
+       var ExtrudeGeometry = /*#__PURE__*/function (_BufferGeometry) {
+               _inheritsLoose(ExtrudeGeometry, _BufferGeometry);
 
-               function ExtrudeBufferGeometry(shapes, options) {
+               function ExtrudeGeometry(shapes, options) {
                        var _this;
 
                        _this = _BufferGeometry.call(this) || this;
-                       _this.type = 'ExtrudeBufferGeometry';
+                       _this.type = 'ExtrudeGeometry';
                        _this.parameters = {
                                shapes: shapes,
                                options: options
                                }
 
                                function scalePt2(pt, vec, size) {
-                                       if (!vec) console.error("THREE.ExtrudeGeometry: vec does not exist");
+                                       if (!vec) console.error('THREE.ExtrudeGeometry: vec does not exist');
                                        return vec.clone().multiplyScalar(size).add(pt);
                                }
 
                        return _this;
                }
 
-               var _proto = ExtrudeBufferGeometry.prototype;
+               var _proto = ExtrudeGeometry.prototype;
 
                _proto.toJSON = function toJSON() {
                        var data = BufferGeometry.prototype.toJSON.call(this);
                        return _toJSON(shapes, options, data);
                };
 
-               return ExtrudeBufferGeometry;
+               return ExtrudeGeometry;
        }(BufferGeometry);
 
        var WorldUVGenerator = {
                return data;
        }
 
-       var ExtrudeGeometry = /*#__PURE__*/function (_Geometry) {
-               _inheritsLoose(ExtrudeGeometry, _Geometry);
+       var IcosahedronGeometry = /*#__PURE__*/function (_PolyhedronGeometry) {
+               _inheritsLoose(IcosahedronGeometry, _PolyhedronGeometry);
 
-               function ExtrudeGeometry(shapes, options) {
-                       var _this;
-
-                       _this = _Geometry.call(this) || this;
-                       _this.type = 'ExtrudeGeometry';
-                       _this.parameters = {
-                               shapes: shapes,
-                               options: options
-                       };
-
-                       _this.fromBufferGeometry(new ExtrudeBufferGeometry(shapes, options));
-
-                       _this.mergeVertices();
-
-                       return _this;
-               }
-
-               var _proto = ExtrudeGeometry.prototype;
-
-               _proto.toJSON = function toJSON() {
-                       var data = _Geometry.prototype.toJSON.call(this);
-
-                       var shapes = this.parameters.shapes;
-                       var options = this.parameters.options;
-                       return _toJSON$1(shapes, options, data);
-               };
-
-               return ExtrudeGeometry;
-       }(Geometry);
-
-       function _toJSON$1(shapes, options, data) {
-               data.shapes = [];
-
-               if (Array.isArray(shapes)) {
-                       for (var i = 0, l = shapes.length; i < l; i++) {
-                               var shape = shapes[i];
-                               data.shapes.push(shape.uuid);
-                       }
-               } else {
-                       data.shapes.push(shapes.uuid);
-               }
-
-               if (options.extrudePath !== undefined) data.options.extrudePath = options.extrudePath.toJSON();
-               return data;
-       }
-
-       var IcosahedronBufferGeometry = /*#__PURE__*/function (_PolyhedronBufferGeom) {
-               _inheritsLoose(IcosahedronBufferGeometry, _PolyhedronBufferGeom);
-
-               function IcosahedronBufferGeometry(radius, detail) {
+               function IcosahedronGeometry(radius, detail) {
                        var _this;
 
                        if (radius === void 0) {
                        var t = (1 + Math.sqrt(5)) / 2;
                        var vertices = [-1, t, 0, 1, t, 0, -1, -t, 0, 1, -t, 0, 0, -1, t, 0, 1, t, 0, -1, -t, 0, 1, -t, t, 0, -1, t, 0, 1, -t, 0, -1, -t, 0, 1];
                        var indices = [0, 11, 5, 0, 5, 1, 0, 1, 7, 0, 7, 10, 0, 10, 11, 1, 5, 9, 5, 11, 4, 11, 10, 2, 10, 7, 6, 7, 1, 8, 3, 9, 4, 3, 4, 2, 3, 2, 6, 3, 6, 8, 3, 8, 9, 4, 9, 5, 2, 4, 11, 6, 2, 10, 8, 6, 7, 9, 8, 1];
-                       _this = _PolyhedronBufferGeom.call(this, vertices, indices, radius, detail) || this;
-                       _this.type = 'IcosahedronBufferGeometry';
-                       _this.parameters = {
-                               radius: radius,
-                               detail: detail
-                       };
-                       return _this;
-               }
-
-               return IcosahedronBufferGeometry;
-       }(PolyhedronBufferGeometry);
-
-       var IcosahedronGeometry = /*#__PURE__*/function (_Geometry) {
-               _inheritsLoose(IcosahedronGeometry, _Geometry);
-
-               function IcosahedronGeometry(radius, detail) {
-                       var _this;
-
-                       _this = _Geometry.call(this) || this;
+                       _this = _PolyhedronGeometry.call(this, vertices, indices, radius, detail) || this;
                        _this.type = 'IcosahedronGeometry';
                        _this.parameters = {
                                radius: radius,
                                detail: detail
                        };
-
-                       _this.fromBufferGeometry(new IcosahedronBufferGeometry(radius, detail));
-
-                       _this.mergeVertices();
-
                        return _this;
                }
 
                return IcosahedronGeometry;
-       }(Geometry);
+       }(PolyhedronGeometry);
 
-       var LatheBufferGeometry = /*#__PURE__*/function (_BufferGeometry) {
-               _inheritsLoose(LatheBufferGeometry, _BufferGeometry);
+       var LatheGeometry = /*#__PURE__*/function (_BufferGeometry) {
+               _inheritsLoose(LatheGeometry, _BufferGeometry);
 
-               function LatheBufferGeometry(points, segments, phiStart, phiLength) {
+               function LatheGeometry(points, segments, phiStart, phiLength) {
                        var _this;
 
                        if (segments === void 0) {
                        }
 
                        _this = _BufferGeometry.call(this) || this;
-                       _this.type = 'LatheBufferGeometry';
+                       _this.type = 'LatheGeometry';
                        _this.parameters = {
                                points: points,
                                segments: segments,
                        return _this;
                }
 
-               return LatheBufferGeometry;
-       }(BufferGeometry);
-
-       var LatheGeometry = /*#__PURE__*/function (_Geometry) {
-               _inheritsLoose(LatheGeometry, _Geometry);
-
-               function LatheGeometry(points, segments, phiStart, phiLength) {
-                       var _this;
-
-                       _this = _Geometry.call(this) || this;
-                       _this.type = 'LatheGeometry';
-                       _this.parameters = {
-                               points: points,
-                               segments: segments,
-                               phiStart: phiStart,
-                               phiLength: phiLength
-                       };
-
-                       _this.fromBufferGeometry(new LatheBufferGeometry(points, segments, phiStart, phiLength));
-
-                       _this.mergeVertices();
-
-                       return _this;
-               }
-
                return LatheGeometry;
-       }(Geometry);
+       }(BufferGeometry);
 
-       var OctahedronBufferGeometry = /*#__PURE__*/function (_PolyhedronBufferGeom) {
-               _inheritsLoose(OctahedronBufferGeometry, _PolyhedronBufferGeom);
+       var OctahedronGeometry = /*#__PURE__*/function (_PolyhedronGeometry) {
+               _inheritsLoose(OctahedronGeometry, _PolyhedronGeometry);
 
-               function OctahedronBufferGeometry(radius, detail) {
+               function OctahedronGeometry(radius, detail) {
                        var _this;
 
                        if (radius === void 0) {
 
                        var vertices = [1, 0, 0, -1, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 1, 0, 0, -1];
                        var indices = [0, 2, 4, 0, 4, 3, 0, 3, 5, 0, 5, 2, 1, 2, 5, 1, 5, 3, 1, 3, 4, 1, 4, 2];
-                       _this = _PolyhedronBufferGeom.call(this, vertices, indices, radius, detail) || this;
-                       _this.type = 'OctahedronBufferGeometry';
-                       _this.parameters = {
-                               radius: radius,
-                               detail: detail
-                       };
-                       return _this;
-               }
-
-               return OctahedronBufferGeometry;
-       }(PolyhedronBufferGeometry);
-
-       var OctahedronGeometry = /*#__PURE__*/function (_Geometry) {
-               _inheritsLoose(OctahedronGeometry, _Geometry);
-
-               function OctahedronGeometry(radius, detail) {
-                       var _this;
-
-                       _this = _Geometry.call(this) || this;
+                       _this = _PolyhedronGeometry.call(this, vertices, indices, radius, detail) || this;
                        _this.type = 'OctahedronGeometry';
                        _this.parameters = {
                                radius: radius,
                                detail: detail
                        };
-
-                       _this.fromBufferGeometry(new OctahedronBufferGeometry(radius, detail));
-
-                       _this.mergeVertices();
-
                        return _this;
                }
 
                return OctahedronGeometry;
-       }(Geometry);
+       }(PolyhedronGeometry);
 
        /**
         * Parametric Surfaces Geometry
         * based on the brilliant article by @prideout https://prideout.net/blog/old/blog/index.html@p=44.html
         */
 
-       function ParametricBufferGeometry(func, slices, stacks) {
+       function ParametricGeometry(func, slices, stacks) {
                BufferGeometry.call(this);
-               this.type = 'ParametricBufferGeometry';
+               this.type = 'ParametricGeometry';
                this.parameters = {
                        func: func,
                        slices: slices,
                this.setAttribute('uv', new Float32BufferAttribute(uvs, 2));
        }
 
-       ParametricBufferGeometry.prototype = Object.create(BufferGeometry.prototype);
-       ParametricBufferGeometry.prototype.constructor = ParametricBufferGeometry;
-
-       /**
-        * Parametric Surfaces Geometry
-        * based on the brilliant article by @prideout https://prideout.net/blog/old/blog/index.html@p=44.html
-        */
-
-       function ParametricGeometry(func, slices, stacks) {
-               Geometry.call(this);
-               this.type = 'ParametricGeometry';
-               this.parameters = {
-                       func: func,
-                       slices: slices,
-                       stacks: stacks
-               };
-               this.fromBufferGeometry(new ParametricBufferGeometry(func, slices, stacks));
-               this.mergeVertices();
-       }
-
-       ParametricGeometry.prototype = Object.create(Geometry.prototype);
+       ParametricGeometry.prototype = Object.create(BufferGeometry.prototype);
        ParametricGeometry.prototype.constructor = ParametricGeometry;
 
-       var PlaneGeometry = /*#__PURE__*/function (_Geometry) {
-               _inheritsLoose(PlaneGeometry, _Geometry);
-
-               function PlaneGeometry(width, height, widthSegments, heightSegments) {
-                       var _this;
-
-                       _this = _Geometry.call(this) || this;
-                       _this.type = 'PlaneGeometry';
-                       _this.parameters = {
-                               width: width,
-                               height: height,
-                               widthSegments: widthSegments,
-                               heightSegments: heightSegments
-                       };
-
-                       _this.fromBufferGeometry(new PlaneBufferGeometry(width, height, widthSegments, heightSegments));
-
-                       _this.mergeVertices();
-
-                       return _this;
-               }
-
-               return PlaneGeometry;
-       }(Geometry);
-
-       var PolyhedronGeometry = /*#__PURE__*/function (_Geometry) {
-               _inheritsLoose(PolyhedronGeometry, _Geometry);
-
-               function PolyhedronGeometry(vertices, indices, radius, detail) {
-                       var _this;
-
-                       _this = _Geometry.call(this) || this;
-                       _this.type = 'PolyhedronGeometry';
-                       _this.parameters = {
-                               vertices: vertices,
-                               indices: indices,
-                               radius: radius,
-                               detail: detail
-                       };
-
-                       _this.fromBufferGeometry(new PolyhedronBufferGeometry(vertices, indices, radius, detail));
+       var RingGeometry = /*#__PURE__*/function (_BufferGeometry) {
+               _inheritsLoose(RingGeometry, _BufferGeometry);
 
-                       _this.mergeVertices();
-
-                       return _this;
-               }
-
-               return PolyhedronGeometry;
-       }(Geometry);
-
-       var RingBufferGeometry = /*#__PURE__*/function (_BufferGeometry) {
-               _inheritsLoose(RingBufferGeometry, _BufferGeometry);
-
-               function RingBufferGeometry(innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength) {
+               function RingGeometry(innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength) {
                        var _this;
 
                        if (innerRadius === void 0) {
                        }
 
                        _this = _BufferGeometry.call(this) || this;
-                       _this.type = 'RingBufferGeometry';
+                       _this.type = 'RingGeometry';
                        _this.parameters = {
                                innerRadius: innerRadius,
                                outerRadius: outerRadius,
                        return _this;
                }
 
-               return RingBufferGeometry;
-       }(BufferGeometry);
-
-       var RingGeometry = /*#__PURE__*/function (_Geometry) {
-               _inheritsLoose(RingGeometry, _Geometry);
-
-               function RingGeometry(innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength) {
-                       var _this;
-
-                       _this = _Geometry.call(this) || this;
-                       _this.type = 'RingGeometry';
-                       _this.parameters = {
-                               innerRadius: innerRadius,
-                               outerRadius: outerRadius,
-                               thetaSegments: thetaSegments,
-                               phiSegments: phiSegments,
-                               thetaStart: thetaStart,
-                               thetaLength: thetaLength
-                       };
-
-                       _this.fromBufferGeometry(new RingBufferGeometry(innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength));
-
-                       _this.mergeVertices();
-
-                       return _this;
-               }
-
                return RingGeometry;
-       }(Geometry);
+       }(BufferGeometry);
 
-       var ShapeBufferGeometry = /*#__PURE__*/function (_BufferGeometry) {
-               _inheritsLoose(ShapeBufferGeometry, _BufferGeometry);
+       var ShapeGeometry = /*#__PURE__*/function (_BufferGeometry) {
+               _inheritsLoose(ShapeGeometry, _BufferGeometry);
 
-               function ShapeBufferGeometry(shapes, curveSegments) {
+               function ShapeGeometry(shapes, curveSegments) {
                        var _this;
 
                        if (curveSegments === void 0) {
                        }
 
                        _this = _BufferGeometry.call(this) || this;
-                       _this.type = 'ShapeBufferGeometry';
+                       _this.type = 'ShapeGeometry';
                        _this.parameters = {
                                shapes: shapes,
                                curveSegments: curveSegments
                        return _this;
                }
 
-               var _proto = ShapeBufferGeometry.prototype;
-
-               _proto.toJSON = function toJSON() {
-                       var data = BufferGeometry.prototype.toJSON.call(this);
-                       var shapes = this.parameters.shapes;
-                       return _toJSON$2(shapes, data);
-               };
-
-               return ShapeBufferGeometry;
-       }(BufferGeometry);
-
-       function _toJSON$2(shapes, data) {
-               data.shapes = [];
-
-               if (Array.isArray(shapes)) {
-                       for (var i = 0, l = shapes.length; i < l; i++) {
-                               var shape = shapes[i];
-                               data.shapes.push(shape.uuid);
-                       }
-               } else {
-                       data.shapes.push(shapes.uuid);
-               }
-
-               return data;
-       }
-
-       var ShapeGeometry = /*#__PURE__*/function (_Geometry) {
-               _inheritsLoose(ShapeGeometry, _Geometry);
-
-               function ShapeGeometry(shapes, curveSegments) {
-                       var _this;
-
-                       _this = _Geometry.call(this) || this;
-                       _this.type = 'ShapeGeometry';
-
-                       if (typeof curveSegments === 'object') {
-                               console.warn('THREE.ShapeGeometry: Options parameter has been removed.');
-                               curveSegments = curveSegments.curveSegments;
-                       }
-
-                       _this.parameters = {
-                               shapes: shapes,
-                               curveSegments: curveSegments
-                       };
-
-                       _this.fromBufferGeometry(new ShapeBufferGeometry(shapes, curveSegments));
-
-                       _this.mergeVertices();
-
-                       return _this;
-               }
-
                var _proto = ShapeGeometry.prototype;
 
                _proto.toJSON = function toJSON() {
-                       var data = Geometry.prototype.toJSON.call(this);
+                       var data = BufferGeometry.prototype.toJSON.call(this);
                        var shapes = this.parameters.shapes;
-                       return _toJSON$3(shapes, data);
+                       return _toJSON$1(shapes, data);
                };
 
                return ShapeGeometry;
-       }(Geometry);
+       }(BufferGeometry);
 
-       function _toJSON$3(shapes, data) {
+       function _toJSON$1(shapes, data) {
                data.shapes = [];
 
                if (Array.isArray(shapes)) {
                return data;
        }
 
-       var SphereBufferGeometry = /*#__PURE__*/function (_BufferGeometry) {
-               _inheritsLoose(SphereBufferGeometry, _BufferGeometry);
+       var SphereGeometry = /*#__PURE__*/function (_BufferGeometry) {
+               _inheritsLoose(SphereGeometry, _BufferGeometry);
 
-               function SphereBufferGeometry(radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength) {
+               function SphereGeometry(radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength) {
                        var _this;
 
                        if (radius === void 0) {
                        }
 
                        _this = _BufferGeometry.call(this) || this;
-                       _this.type = 'SphereBufferGeometry';
+                       _this.type = 'SphereGeometry';
                        _this.parameters = {
                                radius: radius,
                                widthSegments: widthSegments,
                        return _this;
                }
 
-               return SphereBufferGeometry;
-       }(BufferGeometry);
-
-       var SphereGeometry = /*#__PURE__*/function (_Geometry) {
-               _inheritsLoose(SphereGeometry, _Geometry);
-
-               function SphereGeometry(radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength) {
-                       var _this;
-
-                       _this = _Geometry.call(this) || this;
-                       _this.type = 'SphereGeometry';
-                       _this.parameters = {
-                               radius: radius,
-                               widthSegments: widthSegments,
-                               heightSegments: heightSegments,
-                               phiStart: phiStart,
-                               phiLength: phiLength,
-                               thetaStart: thetaStart,
-                               thetaLength: thetaLength
-                       };
-
-                       _this.fromBufferGeometry(new SphereBufferGeometry(radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength));
-
-                       _this.mergeVertices();
-
-                       return _this;
-               }
-
                return SphereGeometry;
-       }(Geometry);
+       }(BufferGeometry);
 
-       var TetrahedronBufferGeometry = /*#__PURE__*/function (_PolyhedronBufferGeom) {
-               _inheritsLoose(TetrahedronBufferGeometry, _PolyhedronBufferGeom);
+       var TetrahedronGeometry = /*#__PURE__*/function (_PolyhedronGeometry) {
+               _inheritsLoose(TetrahedronGeometry, _PolyhedronGeometry);
 
-               function TetrahedronBufferGeometry(radius, detail) {
+               function TetrahedronGeometry(radius, detail) {
                        var _this;
 
                        if (radius === void 0) {
 
                        var vertices = [1, 1, 1, -1, -1, 1, -1, 1, -1, 1, -1, -1];
                        var indices = [2, 1, 0, 0, 3, 2, 1, 3, 0, 2, 3, 1];
-                       _this = _PolyhedronBufferGeom.call(this, vertices, indices, radius, detail) || this;
-                       _this.type = 'TetrahedronBufferGeometry';
-                       _this.parameters = {
-                               radius: radius,
-                               detail: detail
-                       };
-                       return _this;
-               }
-
-               return TetrahedronBufferGeometry;
-       }(PolyhedronBufferGeometry);
-
-       var TetrahedronGeometry = /*#__PURE__*/function (_Geometry) {
-               _inheritsLoose(TetrahedronGeometry, _Geometry);
-
-               function TetrahedronGeometry(radius, detail) {
-                       var _this;
-
-                       _this = _Geometry.call(this) || this;
+                       _this = _PolyhedronGeometry.call(this, vertices, indices, radius, detail) || this;
                        _this.type = 'TetrahedronGeometry';
                        _this.parameters = {
                                radius: radius,
                                detail: detail
                        };
-
-                       _this.fromBufferGeometry(new TetrahedronBufferGeometry(radius, detail));
-
-                       _this.mergeVertices();
-
                        return _this;
                }
 
                return TetrahedronGeometry;
-       }(Geometry);
+       }(PolyhedronGeometry);
 
-       var TextBufferGeometry = /*#__PURE__*/function (_ExtrudeBufferGeometr) {
-               _inheritsLoose(TextBufferGeometry, _ExtrudeBufferGeometr);
+       var TextGeometry = /*#__PURE__*/function (_ExtrudeGeometry) {
+               _inheritsLoose(TextGeometry, _ExtrudeGeometry);
 
-               function TextBufferGeometry(text, parameters) {
+               function TextGeometry(text, parameters) {
                        var _this;
 
                        if (parameters === void 0) {
                        if (parameters.bevelThickness === undefined) parameters.bevelThickness = 10;
                        if (parameters.bevelSize === undefined) parameters.bevelSize = 8;
                        if (parameters.bevelEnabled === undefined) parameters.bevelEnabled = false;
-                       _this = _ExtrudeBufferGeometr.call(this, shapes, parameters) || this;
-                       _this.type = 'TextBufferGeometry';
-                       return _this;
-               }
-
-               return TextBufferGeometry;
-       }(ExtrudeBufferGeometry);
-
-       var TextGeometry = /*#__PURE__*/function (_Geometry) {
-               _inheritsLoose(TextGeometry, _Geometry);
-
-               function TextGeometry(text, parameters) {
-                       var _this;
-
-                       _this = _Geometry.call(this) || this;
+                       _this = _ExtrudeGeometry.call(this, shapes, parameters) || this;
                        _this.type = 'TextGeometry';
-                       _this.parameters = {
-                               text: text,
-                               parameters: parameters
-                       };
-
-                       _this.fromBufferGeometry(new TextBufferGeometry(text, parameters));
-
-                       _this.mergeVertices();
-
                        return _this;
                }
 
                return TextGeometry;
-       }(Geometry);
+       }(ExtrudeGeometry);
 
-       var TorusBufferGeometry = /*#__PURE__*/function (_BufferGeometry) {
-               _inheritsLoose(TorusBufferGeometry, _BufferGeometry);
+       var TorusGeometry = /*#__PURE__*/function (_BufferGeometry) {
+               _inheritsLoose(TorusGeometry, _BufferGeometry);
 
-               function TorusBufferGeometry(radius, tube, radialSegments, tubularSegments, arc) {
+               function TorusGeometry(radius, tube, radialSegments, tubularSegments, arc) {
                        var _this;
 
                        if (radius === void 0) {
                        }
 
                        _this = _BufferGeometry.call(this) || this;
-                       _this.type = 'TorusBufferGeometry';
+                       _this.type = 'TorusGeometry';
                        _this.parameters = {
                                radius: radius,
                                tube: tube,
                        return _this;
                }
 
-               return TorusBufferGeometry;
-       }(BufferGeometry);
-
-       var TorusGeometry = /*#__PURE__*/function (_Geometry) {
-               _inheritsLoose(TorusGeometry, _Geometry);
-
-               function TorusGeometry(radius, tube, radialSegments, tubularSegments, arc) {
-                       var _this;
-
-                       _this = _Geometry.call(this) || this;
-                       _this.type = 'TorusGeometry';
-                       _this.parameters = {
-                               radius: radius,
-                               tube: tube,
-                               radialSegments: radialSegments,
-                               tubularSegments: tubularSegments,
-                               arc: arc
-                       };
-
-                       _this.fromBufferGeometry(new TorusBufferGeometry(radius, tube, radialSegments, tubularSegments, arc));
-
-                       _this.mergeVertices();
-
-                       return _this;
-               }
-
                return TorusGeometry;
-       }(Geometry);
+       }(BufferGeometry);
 
-       var TorusKnotBufferGeometry = /*#__PURE__*/function (_BufferGeometry) {
-               _inheritsLoose(TorusKnotBufferGeometry, _BufferGeometry);
+       var TorusKnotGeometry = /*#__PURE__*/function (_BufferGeometry) {
+               _inheritsLoose(TorusKnotGeometry, _BufferGeometry);
 
-               function TorusKnotBufferGeometry(radius, tube, tubularSegments, radialSegments, p, q) {
+               function TorusKnotGeometry(radius, tube, tubularSegments, radialSegments, p, q) {
                        var _this;
 
                        if (radius === void 0) {
                        }
 
                        _this = _BufferGeometry.call(this) || this;
-                       _this.type = 'TorusKnotBufferGeometry';
+                       _this.type = 'TorusKnotGeometry';
                        _this.parameters = {
                                radius: radius,
                                tube: tube,
                        return _this;
                }
 
-               return TorusKnotBufferGeometry;
-       }(BufferGeometry);
-
-       var TorusKnotGeometry = /*#__PURE__*/function (_Geometry) {
-               _inheritsLoose(TorusKnotGeometry, _Geometry);
-
-               function TorusKnotGeometry(radius, tube, tubularSegments, radialSegments, p, q, heightScale) {
-                       var _this;
-
-                       _this = _Geometry.call(this) || this;
-                       _this.type = 'TorusKnotGeometry';
-                       _this.parameters = {
-                               radius: radius,
-                               tube: tube,
-                               tubularSegments: tubularSegments,
-                               radialSegments: radialSegments,
-                               p: p,
-                               q: q
-                       };
-                       if (heightScale !== undefined) console.warn('THREE.TorusKnotGeometry: heightScale has been deprecated. Use .scale( x, y, z ) instead.');
-
-                       _this.fromBufferGeometry(new TorusKnotBufferGeometry(radius, tube, tubularSegments, radialSegments, p, q));
-
-                       _this.mergeVertices();
-
-                       return _this;
-               }
-
                return TorusKnotGeometry;
-       }(Geometry);
+       }(BufferGeometry);
 
-       var TubeBufferGeometry = /*#__PURE__*/function (_BufferGeometry) {
-               _inheritsLoose(TubeBufferGeometry, _BufferGeometry);
+       var TubeGeometry = /*#__PURE__*/function (_BufferGeometry) {
+               _inheritsLoose(TubeGeometry, _BufferGeometry);
 
-               function TubeBufferGeometry(path, tubularSegments, radius, radialSegments, closed) {
+               function TubeGeometry(path, tubularSegments, radius, radialSegments, closed) {
                        var _this;
 
                        if (tubularSegments === void 0) {
                        }
 
                        _this = _BufferGeometry.call(this) || this;
-                       _this.type = 'TubeBufferGeometry';
+                       _this.type = 'TubeGeometry';
                        _this.parameters = {
                                path: path,
                                tubularSegments: tubularSegments,
                        return _this;
                }
 
-               var _proto = TubeBufferGeometry.prototype;
+               var _proto = TubeGeometry.prototype;
 
                _proto.toJSON = function toJSON() {
                        var data = BufferGeometry.prototype.toJSON.call(this);
                        return data;
                };
 
-               return TubeBufferGeometry;
-       }(BufferGeometry);
-
-       var TubeGeometry = /*#__PURE__*/function (_Geometry) {
-               _inheritsLoose(TubeGeometry, _Geometry);
-
-               function TubeGeometry(path, tubularSegments, radius, radialSegments, closed, taper) {
-                       var _this;
-
-                       _this = _Geometry.call(this) || this;
-                       _this.type = 'TubeGeometry';
-                       _this.parameters = {
-                               path: path,
-                               tubularSegments: tubularSegments,
-                               radius: radius,
-                               radialSegments: radialSegments,
-                               closed: closed
-                       };
-                       if (taper !== undefined) console.warn('THREE.TubeGeometry: taper has been removed.');
-                       var bufferGeometry = new TubeBufferGeometry(path, tubularSegments, radius, radialSegments, closed); // expose internals
-
-                       _this.tangents = bufferGeometry.tangents;
-                       _this.normals = bufferGeometry.normals;
-                       _this.binormals = bufferGeometry.binormals; // create geometry
-
-                       _this.fromBufferGeometry(bufferGeometry);
-
-                       _this.mergeVertices();
-
-                       return _this;
-               }
-
                return TubeGeometry;
-       }(Geometry);
+       }(BufferGeometry);
 
        var WireframeGeometry = /*#__PURE__*/function (_BufferGeometry) {
                _inheritsLoose(WireframeGeometry, _BufferGeometry);
                        var _this;
 
                        _this = _BufferGeometry.call(this) || this;
-                       _this.type = 'WireframeGeometry'; // buffer
+                       _this.type = 'WireframeGeometry';
+
+                       if (geometry.isGeometry === true) {
+                               console.error('THREE.WireframeGeometry no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.');
+                               return _assertThisInitialized(_this);
+                       } // buffer
+
 
                        var vertices = []; // helper variables
 
                        var edge = [0, 0],
                                        edges = {};
-                       var keys = ['a', 'b', 'c']; // different logic for Geometry and BufferGeometry
+                       var vertex = new Vector3();
+
+                       if (geometry.index !== null) {
+                               // indexed BufferGeometry
+                               var position = geometry.attributes.position;
+                               var indices = geometry.index;
+                               var groups = geometry.groups;
 
-                       if (geometry && geometry.isGeometry) {
-                               // create a data structure that contains all edges without duplicates
-                               var faces = geometry.faces;
+                               if (groups.length === 0) {
+                                       groups = [{
+                                               start: 0,
+                                               count: indices.count,
+                                               materialIndex: 0
+                                       }];
+                               } // create a data structure that contains all eges without duplicates
 
-                               for (var i = 0, l = faces.length; i < l; i++) {
-                                       var face = faces[i];
 
-                                       for (var j = 0; j < 3; j++) {
-                                               var edge1 = face[keys[j]];
-                                               var edge2 = face[keys[(j + 1) % 3]];
-                                               edge[0] = Math.min(edge1, edge2); // sorting prevents duplicates
+                               for (var o = 0, ol = groups.length; o < ol; ++o) {
+                                       var group = groups[o];
+                                       var start = group.start;
+                                       var count = group.count;
 
-                                               edge[1] = Math.max(edge1, edge2);
-                                               var key = edge[0] + ',' + edge[1];
+                                       for (var i = start, l = start + count; i < l; i += 3) {
+                                               for (var j = 0; j < 3; j++) {
+                                                       var edge1 = indices.getX(i + j);
+                                                       var edge2 = indices.getX(i + (j + 1) % 3);
+                                                       edge[0] = Math.min(edge1, edge2); // sorting prevents duplicates
 
-                                               if (edges[key] === undefined) {
-                                                       edges[key] = {
-                                                               index1: edge[0],
-                                                               index2: edge[1]
-                                                       };
+                                                       edge[1] = Math.max(edge1, edge2);
+                                                       var key = edge[0] + ',' + edge[1];
+
+                                                       if (edges[key] === undefined) {
+                                                               edges[key] = {
+                                                                       index1: edge[0],
+                                                                       index2: edge[1]
+                                                               };
+                                                       }
                                                }
                                        }
                                } // generate vertices
 
                                for (var _key in edges) {
                                        var e = edges[_key];
-                                       var vertex = geometry.vertices[e.index1];
+                                       vertex.fromBufferAttribute(position, e.index1);
                                        vertices.push(vertex.x, vertex.y, vertex.z);
-                                       vertex = geometry.vertices[e.index2];
+                                       vertex.fromBufferAttribute(position, e.index2);
                                        vertices.push(vertex.x, vertex.y, vertex.z);
                                }
-                       } else if (geometry && geometry.isBufferGeometry) {
-                               var _vertex = new Vector3();
-
-                               if (geometry.index !== null) {
-                                       // indexed BufferGeometry
-                                       var position = geometry.attributes.position;
-                                       var indices = geometry.index;
-                                       var groups = geometry.groups;
-
-                                       if (groups.length === 0) {
-                                               groups = [{
-                                                       start: 0,
-                                                       count: indices.count,
-                                                       materialIndex: 0
-                                               }];
-                                       } // create a data structure that contains all eges without duplicates
-
-
-                                       for (var o = 0, ol = groups.length; o < ol; ++o) {
-                                               var group = groups[o];
-                                               var start = group.start;
-                                               var count = group.count;
-
-                                               for (var _i = start, _l = start + count; _i < _l; _i += 3) {
-                                                       for (var _j = 0; _j < 3; _j++) {
-                                                               var _edge = indices.getX(_i + _j);
-
-                                                               var _edge2 = indices.getX(_i + (_j + 1) % 3);
-
-                                                               edge[0] = Math.min(_edge, _edge2); // sorting prevents duplicates
-
-                                                               edge[1] = Math.max(_edge, _edge2);
-
-                                                               var _key2 = edge[0] + ',' + edge[1];
-
-                                                               if (edges[_key2] === undefined) {
-                                                                       edges[_key2] = {
-                                                                               index1: edge[0],
-                                                                               index2: edge[1]
-                                                                       };
-                                                               }
-                                                       }
-                                               }
-                                       } // generate vertices
-
-
-                                       for (var _key3 in edges) {
-                                               var _e = edges[_key3];
-
-                                               _vertex.fromBufferAttribute(position, _e.index1);
-
-                                               vertices.push(_vertex.x, _vertex.y, _vertex.z);
-
-                                               _vertex.fromBufferAttribute(position, _e.index2);
-
-                                               vertices.push(_vertex.x, _vertex.y, _vertex.z);
-                                       }
-                               } else {
-                                       // non-indexed BufferGeometry
-                                       var _position = geometry.attributes.position;
-
-                                       for (var _i2 = 0, _l2 = _position.count / 3; _i2 < _l2; _i2++) {
-                                               for (var _j2 = 0; _j2 < 3; _j2++) {
-                                                       // three edges per triangle, an edge is represented as (index1, index2)
-                                                       // e.g. the first triangle has the following edges: (0,1),(1,2),(2,0)
-                                                       var index1 = 3 * _i2 + _j2;
-
-                                                       _vertex.fromBufferAttribute(_position, index1);
-
-                                                       vertices.push(_vertex.x, _vertex.y, _vertex.z);
-                                                       var index2 = 3 * _i2 + (_j2 + 1) % 3;
-
-                                                       _vertex.fromBufferAttribute(_position, index2);
-
-                                                       vertices.push(_vertex.x, _vertex.y, _vertex.z);
-                                               }
+                       } else {
+                               // non-indexed BufferGeometry
+                               var _position = geometry.attributes.position;
+
+                               for (var _i = 0, _l = _position.count / 3; _i < _l; _i++) {
+                                       for (var _j = 0; _j < 3; _j++) {
+                                               // three edges per triangle, an edge is represented as (index1, index2)
+                                               // e.g. the first triangle has the following edges: (0,1),(1,2),(2,0)
+                                               var index1 = 3 * _i + _j;
+                                               vertex.fromBufferAttribute(_position, index1);
+                                               vertices.push(vertex.x, vertex.y, vertex.z);
+                                               var index2 = 3 * _i + (_j + 1) % 3;
+                                               vertex.fromBufferAttribute(_position, index2);
+                                               vertices.push(vertex.x, vertex.y, vertex.z);
                                        }
                                }
                        } // build geometry
        var Geometries = /*#__PURE__*/Object.freeze({
                __proto__: null,
                BoxGeometry: BoxGeometry,
-               BoxBufferGeometry: BoxBufferGeometry,
+               BoxBufferGeometry: BoxGeometry,
                CircleGeometry: CircleGeometry,
-               CircleBufferGeometry: CircleBufferGeometry,
+               CircleBufferGeometry: CircleGeometry,
                ConeGeometry: ConeGeometry,
-               ConeBufferGeometry: ConeBufferGeometry,
+               ConeBufferGeometry: ConeGeometry,
                CylinderGeometry: CylinderGeometry,
-               CylinderBufferGeometry: CylinderBufferGeometry,
+               CylinderBufferGeometry: CylinderGeometry,
                DodecahedronGeometry: DodecahedronGeometry,
-               DodecahedronBufferGeometry: DodecahedronBufferGeometry,
+               DodecahedronBufferGeometry: DodecahedronGeometry,
                EdgesGeometry: EdgesGeometry,
                ExtrudeGeometry: ExtrudeGeometry,
-               ExtrudeBufferGeometry: ExtrudeBufferGeometry,
+               ExtrudeBufferGeometry: ExtrudeGeometry,
                IcosahedronGeometry: IcosahedronGeometry,
-               IcosahedronBufferGeometry: IcosahedronBufferGeometry,
+               IcosahedronBufferGeometry: IcosahedronGeometry,
                LatheGeometry: LatheGeometry,
-               LatheBufferGeometry: LatheBufferGeometry,
+               LatheBufferGeometry: LatheGeometry,
                OctahedronGeometry: OctahedronGeometry,
-               OctahedronBufferGeometry: OctahedronBufferGeometry,
+               OctahedronBufferGeometry: OctahedronGeometry,
                ParametricGeometry: ParametricGeometry,
-               ParametricBufferGeometry: ParametricBufferGeometry,
+               ParametricBufferGeometry: ParametricGeometry,
                PlaneGeometry: PlaneGeometry,
-               PlaneBufferGeometry: PlaneBufferGeometry,
+               PlaneBufferGeometry: PlaneGeometry,
                PolyhedronGeometry: PolyhedronGeometry,
-               PolyhedronBufferGeometry: PolyhedronBufferGeometry,
+               PolyhedronBufferGeometry: PolyhedronGeometry,
                RingGeometry: RingGeometry,
-               RingBufferGeometry: RingBufferGeometry,
+               RingBufferGeometry: RingGeometry,
                ShapeGeometry: ShapeGeometry,
-               ShapeBufferGeometry: ShapeBufferGeometry,
+               ShapeBufferGeometry: ShapeGeometry,
                SphereGeometry: SphereGeometry,
-               SphereBufferGeometry: SphereBufferGeometry,
+               SphereBufferGeometry: SphereGeometry,
                TetrahedronGeometry: TetrahedronGeometry,
-               TetrahedronBufferGeometry: TetrahedronBufferGeometry,
+               TetrahedronBufferGeometry: TetrahedronGeometry,
                TextGeometry: TextGeometry,
-               TextBufferGeometry: TextBufferGeometry,
+               TextBufferGeometry: TextGeometry,
                TorusGeometry: TorusGeometry,
-               TorusBufferGeometry: TorusBufferGeometry,
+               TorusBufferGeometry: TorusGeometry,
                TorusKnotGeometry: TorusKnotGeometry,
-               TorusKnotBufferGeometry: TorusKnotBufferGeometry,
+               TorusKnotBufferGeometry: TorusKnotGeometry,
                TubeGeometry: TubeGeometry,
-               TubeBufferGeometry: TubeBufferGeometry,
+               TubeBufferGeometry: TubeGeometry,
                WireframeGeometry: WireframeGeometry
        });
 
                        }
 
                        if (factoryMethod === undefined) {
-                               var message = "unsupported interpolation for " + this.ValueTypeName + " keyframe track named " + this.name;
+                               var message = 'unsupported interpolation for ' + this.ValueTypeName + ' keyframe track named ' + this.name;
 
                                if (this.createInterpolant === undefined) {
                                        // fall back to default, unless the default itself is messed up
                                var time = times[i];
                                var timeNext = times[i + 1]; // remove adjacent keyframes scheduled at the same time
 
-                               if (time !== timeNext && (i !== 1 || time !== time[0])) {
+                               if (time !== timeNext && (i !== 1 || time !== times[0])) {
                                        if (!smoothInterpolation) {
                                                // remove unnecessary keyframes same as their neighbors
                                                var offset = i * stride,
        });
 
        function AnimationClip(name, duration, tracks, blendMode) {
+               if (duration === void 0) {
+                       duration = -1;
+               }
+
+               if (blendMode === void 0) {
+                       blendMode = NormalAnimationBlendMode;
+               }
+
                this.name = name;
                this.tracks = tracks;
-               this.duration = duration !== undefined ? duration : -1;
-               this.blendMode = blendMode !== undefined ? blendMode : NormalAnimationBlendMode;
+               this.duration = duration;
+               this.blendMode = blendMode;
                this.uuid = MathUtils.generateUUID(); // this means it should figure out its duration by scanning the tracks
 
                if (this.duration < 0) {
                        var scope = this;
                        var images = [];
                        var texture = new CompressedTexture();
-                       texture.image = images;
                        var loader = new FileLoader(this.manager);
                        loader.setPath(this.path);
                        loader.setResponseType('arraybuffer');
 
                                        if (loaded === 6) {
                                                if (texDatas.mipmapCount === 1) texture.minFilter = LinearFilter;
+                                               texture.image = images;
                                                texture.format = texDatas.format;
                                                texture.needsUpdate = true;
                                                if (onLoad) onLoad(texture);
                                                                images[f].height = texDatas.height;
                                                        }
                                                }
+
+                                               texture.image = images;
                                        } else {
                                                texture.image.width = texDatas.width;
                                                texture.image.height = texDatas.height;
                                texture.minFilter = texData.minFilter !== undefined ? texData.minFilter : LinearFilter;
                                texture.anisotropy = texData.anisotropy !== undefined ? texData.anisotropy : 1;
 
+                               if (texData.encoding !== undefined) {
+                                       texture.encoding = texData.encoding;
+                               }
+
+                               if (texData.flipY !== undefined) {
+                                       texture.flipY = texData.flipY;
+                               }
+
                                if (texData.format !== undefined) {
                                        texture.format = texData.format;
                                }
        });
 
        function OrthographicCamera(left, right, top, bottom, near, far) {
+               if (left === void 0) {
+                       left = -1;
+               }
+
+               if (right === void 0) {
+                       right = 1;
+               }
+
+               if (top === void 0) {
+                       top = 1;
+               }
+
+               if (bottom === void 0) {
+                       bottom = -1;
+               }
+
+               if (near === void 0) {
+                       near = 0.1;
+               }
+
+               if (far === void 0) {
+                       far = 2000;
+               }
+
                Camera.call(this);
                this.type = 'OrthographicCamera';
                this.zoom = 1;
                this.view = null;
-               this.left = left !== undefined ? left : -1;
-               this.right = right !== undefined ? right : 1;
-               this.top = top !== undefined ? top : 1;
-               this.bottom = bottom !== undefined ? bottom : -1;
-               this.near = near !== undefined ? near : 0.1;
-               this.far = far !== undefined ? far : 2000;
+               this.left = left;
+               this.right = right;
+               this.top = top;
+               this.bottom = bottom;
+               this.near = near;
+               this.far = far;
                this.updateProjectionMatrix();
        }
 
 
                                                case 'BoxGeometry':
                                                case 'BoxBufferGeometry':
-                                               case 'CubeGeometry':
-                                                       // backwards compatible
                                                        geometry = new Geometries[data.type](data.width, data.height, data.depth, data.widthSegments, data.heightSegments, data.depthSegments);
                                                        break;
 
                                        break;
 
                                case 'Line':
-                                       object = new Line(getGeometry(data.geometry), getMaterial(data.material), data.mode);
+                                       object = new Line(getGeometry(data.geometry), getMaterial(data.material));
                                        break;
 
                                case 'LineLoop':
                }
        });
 
-       function Font(data) {
-               this.type = 'Font';
-               this.data = data;
-       }
+       var Font = /*#__PURE__*/function () {
+               function Font(data) {
+                       Object.defineProperty(this, 'isFont', {
+                               value: true
+                       });
+                       this.type = 'Font';
+                       this.data = data;
+               }
 
-       Object.assign(Font.prototype, {
-               isFont: true,
-               generateShapes: function generateShapes(text, size) {
+               var _proto = Font.prototype;
+
+               _proto.generateShapes = function generateShapes(text, size) {
                        if (size === void 0) {
                                size = 100;
                        }
                        }
 
                        return shapes;
-               }
-       });
+               };
+
+               return Font;
+       }();
 
        function createPaths(text, size, data) {
                var chars = Array.from ? Array.from(text) : String(text).split(''); // workaround for IE11, see #13988
                        return results;
                },
                findNode: function findNode(root, nodeName) {
-                       if (!nodeName || nodeName === "" || nodeName === "." || nodeName === -1 || nodeName === root.name || nodeName === root.uuid) {
+                       if (!nodeName || nodeName === '' || nodeName === '.' || nodeName === -1 || nodeName === root.name || nodeName === root.uuid) {
                                return root;
                        } // search into skeleton bones.
 
 
                        if (propertyIndex !== undefined) {
                                // access a sub element of the property array (only primitives are supported right now)
-                               if (propertyName === "morphTargetInfluences") {
+                               if (propertyName === 'morphTargetInfluences') {
                                        // potential optimization, skip this if propertyIndex is already an integer, and convert the integer string to a true integer.
                                        // support resolving morphTarget names into indices.
                                        if (!targetObject.geometry) {
                                this.ray.direction.set(0, 0, -1).transformDirection(camera.matrixWorld);
                                this.camera = camera;
                        } else {
-                               console.error('THREE.Raycaster: Unsupported camera type.');
+                               console.error('THREE.Raycaster: Unsupported camera type: ' + camera.type);
                        }
                },
                intersectObject: function intersectObject(object, recursive, optionalTarget) {
                return Cylindrical;
        }();
 
-       var _vector$7 = /*@__PURE__*/new Vector2();
+       var _vector$8 = /*@__PURE__*/new Vector2();
 
        var Box2 = /*#__PURE__*/function () {
                function Box2(min, max) {
                };
 
                _proto.setFromCenterAndSize = function setFromCenterAndSize(center, size) {
-                       var halfSize = _vector$7.copy(size).multiplyScalar(0.5);
+                       var halfSize = _vector$8.copy(size).multiplyScalar(0.5);
 
                        this.min.copy(center).sub(halfSize);
                        this.max.copy(center).add(halfSize);
                };
 
                _proto.distanceToPoint = function distanceToPoint(point) {
-                       var clampedPoint = _vector$7.copy(point).clamp(this.min, this.max);
+                       var clampedPoint = _vector$8.copy(point).clamp(this.min, this.max);
 
                        return clampedPoint.sub(point).length();
                };
        ImmediateRenderObject.prototype.constructor = ImmediateRenderObject;
        ImmediateRenderObject.prototype.isImmediateRenderObject = true;
 
-       var _vector$8 = /*@__PURE__*/new Vector3();
+       var _vector$9 = /*@__PURE__*/new Vector3();
 
        var SpotLightHelper = /*#__PURE__*/function (_Object3D) {
                _inheritsLoose(SpotLightHelper, _Object3D);
                        var coneWidth = coneLength * Math.tan(this.light.angle);
                        this.cone.scale.set(coneWidth, coneWidth, coneLength);
 
-                       _vector$8.setFromMatrixPosition(this.light.target.matrixWorld);
+                       _vector$9.setFromMatrixPosition(this.light.target.matrixWorld);
 
-                       this.cone.lookAt(_vector$8);
+                       this.cone.lookAt(_vector$9);
 
                        if (this.color !== undefined) {
                                this.cone.material.color.set(this.color);
                return SpotLightHelper;
        }(Object3D);
 
-       var _vector$9 = /*@__PURE__*/new Vector3();
+       var _vector$a = /*@__PURE__*/new Vector3();
 
        var _boneMatrix = /*@__PURE__*/new Matrix4();
 
                                if (bone.parent && bone.parent.isBone) {
                                        _boneMatrix.multiplyMatrices(_matrixWorldInv, bone.matrixWorld);
 
-                                       _vector$9.setFromMatrixPosition(_boneMatrix);
+                                       _vector$a.setFromMatrixPosition(_boneMatrix);
 
-                                       position.setXYZ(j, _vector$9.x, _vector$9.y, _vector$9.z);
+                                       position.setXYZ(j, _vector$a.x, _vector$a.y, _vector$a.z);
 
                                        _boneMatrix.multiplyMatrices(_matrixWorldInv, bone.parent.matrixWorld);
 
-                                       _vector$9.setFromMatrixPosition(_boneMatrix);
+                                       _vector$a.setFromMatrixPosition(_boneMatrix);
 
-                                       position.setXYZ(j + 1, _vector$9.x, _vector$9.y, _vector$9.z);
+                                       position.setXYZ(j + 1, _vector$a.x, _vector$a.y, _vector$a.z);
                                        j += 2;
                                }
                        }
                function PointLightHelper(light, sphereSize, color) {
                        var _this;
 
-                       var geometry = new SphereBufferGeometry(sphereSize, 4, 2);
+                       var geometry = new SphereGeometry(sphereSize, 4, 2);
                        var material = new MeshBasicMaterial({
                                wireframe: true,
                                fog: false,
                return PointLightHelper;
        }(Mesh);
 
-       var _vector$a = /*@__PURE__*/new Vector3();
+       var _vector$b = /*@__PURE__*/new Vector3();
 
        var _color1 = /*@__PURE__*/new Color();
 
                        _this.matrix = light.matrixWorld;
                        _this.matrixAutoUpdate = false;
                        _this.color = color;
-                       var geometry = new OctahedronBufferGeometry(size);
+                       var geometry = new OctahedronGeometry(size);
                        geometry.rotateY(Math.PI * 0.5);
                        _this.material = new MeshBasicMaterial({
                                wireframe: true,
                                colors.needsUpdate = true;
                        }
 
-                       mesh.lookAt(_vector$a.setFromMatrixPosition(this.light.matrixWorld).negate());
+                       mesh.lookAt(_vector$b.setFromMatrixPosition(this.light.matrixWorld).negate());
                };
 
                return HemisphereLightHelper;
                return DirectionalLightHelper;
        }(Object3D);
 
-       var _vector$b = /*@__PURE__*/new Vector3();
+       var _vector$c = /*@__PURE__*/new Vector3();
 
        var _camera = /*@__PURE__*/new Camera();
        /**
        }(LineSegments);
 
        function setPoint(point, pointMap, geometry, camera, x, y, z) {
-               _vector$b.set(x, y, z).unproject(camera);
+               _vector$c.set(x, y, z).unproject(camera);
 
                var points = pointMap[point];
 
                        var position = geometry.getAttribute('position');
 
                        for (var i = 0, l = points.length; i < l; i++) {
-                               position.setXYZ(points[i], _vector$b.x, _vector$b.y, _vector$b.z);
+                               position.setXYZ(points[i], _vector$c.x, _vector$c.y, _vector$c.z);
                        }
                }
        }
 
                                _lineGeometry.setAttribute('position', new Float32BufferAttribute([0, 0, 0, 0, 1, 0], 3));
 
-                               _coneGeometry = new CylinderBufferGeometry(0, 0.5, 1, 5, 1);
+                               _coneGeometry = new CylinderGeometry(0, 0.5, 1, 5, 1);
 
                                _coneGeometry.translate(0, -0.5, 0);
                        }
 
        var MAX_SAMPLES = 20;
        var ENCODINGS = (_ENCODINGS = {}, _ENCODINGS[LinearEncoding] = 0, _ENCODINGS[sRGBEncoding] = 1, _ENCODINGS[RGBEEncoding] = 2, _ENCODINGS[RGBM7Encoding] = 3, _ENCODINGS[RGBM16Encoding] = 4, _ENCODINGS[RGBDEncoding] = 5, _ENCODINGS[GammaEncoding] = 6, _ENCODINGS);
+       var backgroundMaterial = new MeshBasicMaterial({
+               side: BackSide,
+               depthWrite: false,
+               depthTest: false
+       });
+       var backgroundBox = new Mesh(new BoxGeometry(), backgroundMaterial);
 
        var _flatCamera = /*@__PURE__*/new OrthographicCamera();
 
                        _sizeLods = _createPlanes2._sizeLods,
                        _sigmas = _createPlanes2._sigmas;
 
+       var _clearColor = /*@__PURE__*/new Color();
+
        var _oldTarget = null; // Golden Ratio
 
        var PHI = (1 + Math.sqrt(5)) / 2;
         * interpolate diffuse lighting while limiting sampling computation.
         */
 
+       function convertLinearToRGBE(color) {
+               var maxComponent = Math.max(color.r, color.g, color.b);
+               var fExp = Math.min(Math.max(Math.ceil(Math.log2(maxComponent)), -128.0), 127.0);
+               color.multiplyScalar(Math.pow(2.0, -fExp));
+               var alpha = (fExp + 128.0) / 255.0;
+               return alpha;
+       }
+
        var PMREMGenerator = /*#__PURE__*/function () {
                function PMREMGenerator(renderer) {
                        this._renderer = renderer;
                        var upSign = [1, -1, 1, 1, 1, 1];
                        var forwardSign = [1, 1, 1, -1, -1, -1];
                        var renderer = this._renderer;
+                       var originalAutoClear = renderer.autoClear;
                        var outputEncoding = renderer.outputEncoding;
                        var toneMapping = renderer.toneMapping;
-                       var clearColor = renderer.getClearColor();
-                       var clearAlpha = renderer.getClearAlpha();
+                       renderer.getClearColor(_clearColor);
                        renderer.toneMapping = NoToneMapping;
                        renderer.outputEncoding = LinearEncoding;
+                       renderer.autoClear = false;
+                       var useSolidColor = false;
                        var background = scene.background;
 
-                       if (background && background.isColor) {
-                               background.convertSRGBToLinear(); // Convert linear to RGBE
+                       if (background) {
+                               if (background.isColor) {
+                                       backgroundMaterial.color.copy(background).convertSRGBToLinear();
+                                       scene.background = null;
+                                       var alpha = convertLinearToRGBE(backgroundMaterial.color);
+                                       backgroundMaterial.opacity = alpha;
+                                       useSolidColor = true;
+                               }
+                       } else {
+                               backgroundMaterial.color.copy(_clearColor).convertSRGBToLinear();
+
+                               var _alpha = convertLinearToRGBE(backgroundMaterial.color);
 
-                               var maxComponent = Math.max(background.r, background.g, background.b);
-                               var fExp = Math.min(Math.max(Math.ceil(Math.log2(maxComponent)), -128.0), 127.0);
-                               background = background.multiplyScalar(Math.pow(2.0, -fExp));
-                               var alpha = (fExp + 128.0) / 255.0;
-                               renderer.setClearColor(background, alpha);
-                               scene.background = null;
+                               backgroundMaterial.opacity = _alpha;
+                               useSolidColor = true;
                        }
 
                        for (var i = 0; i < 6; i++) {
                                _setViewport(cubeUVRenderTarget, col * SIZE_MAX, i > 2 ? SIZE_MAX : 0, SIZE_MAX, SIZE_MAX);
 
                                renderer.setRenderTarget(cubeUVRenderTarget);
+
+                               if (useSolidColor) {
+                                       renderer.render(backgroundBox, cubeCamera);
+                               }
+
                                renderer.render(scene, cubeCamera);
                        }
 
                        renderer.toneMapping = toneMapping;
                        renderer.outputEncoding = outputEncoding;
-                       renderer.setClearColor(clearColor, clearAlpha);
+                       renderer.autoClear = originalAutoClear;
                };
 
                _proto._textureToCubeUV = function _textureToCubeUV(texture, cubeUVRenderTarget) {
        }; //
 
 
-       Object.assign(CurvePath.prototype, {
-               createPointsGeometry: function createPointsGeometry(divisions) {
-                       console.warn('THREE.CurvePath: .createPointsGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.'); // generate geometry from path points (for Line or Points objects)
-
-                       var pts = this.getPoints(divisions);
-                       return this.createGeometry(pts);
-               },
-               createSpacedPointsGeometry: function createSpacedPointsGeometry(divisions) {
-                       console.warn('THREE.CurvePath: .createSpacedPointsGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.'); // generate geometry from equidistant sampling along the path
-
-                       var pts = this.getSpacedPoints(divisions);
-                       return this.createGeometry(pts);
-               },
-               createGeometry: function createGeometry(points) {
-                       console.warn('THREE.CurvePath: .createGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.');
-                       var geometry = new Geometry();
-
-                       for (var i = 0, l = points.length; i < l; i++) {
-                               var point = points[i];
-                               geometry.vertices.push(new Vector3(point.x, point.y, point.z || 0));
-                       }
-
-                       return geometry;
-               }
-       }); //
-
        Object.assign(Path.prototype, {
                fromPoints: function fromPoints(points) {
                        console.warn('THREE.Path: .fromPoints() has been renamed to .setFromPoints().');
        });
        Object.assign(Matrix3.prototype, {
                flattenToArrayOffset: function flattenToArrayOffset(array, offset) {
-                       console.warn("THREE.Matrix3: .flattenToArrayOffset() has been deprecated. Use .toArray() instead.");
+                       console.warn('THREE.Matrix3: .flattenToArrayOffset() has been deprecated. Use .toArray() instead.');
                        return this.toArray(array, offset);
                },
                multiplyVector3: function multiplyVector3(vector) {
                        return this.copyPosition(m);
                },
                flattenToArrayOffset: function flattenToArrayOffset(array, offset) {
-                       console.warn("THREE.Matrix4: .flattenToArrayOffset() has been deprecated. Use .toArray() instead.");
+                       console.warn('THREE.Matrix4: .flattenToArrayOffset() has been deprecated. Use .toArray() instead.');
                        return this.toArray(array, offset);
                },
                getPosition: function getPosition() {
                }
        }); //
 
-       Object.assign(Geometry.prototype, {
-               computeTangents: function computeTangents() {
-                       console.error('THREE.Geometry: .computeTangents() has been removed.');
-               },
-               computeLineDistances: function computeLineDistances() {
-                       console.error('THREE.Geometry: .computeLineDistances() has been removed. Use THREE.Line.computeLineDistances() instead.');
-               },
-               applyMatrix: function applyMatrix(matrix) {
-                       console.warn('THREE.Geometry: .applyMatrix() has been renamed to .applyMatrix4().');
-                       return this.applyMatrix4(matrix);
-               }
-       });
        Object.assign(Object3D.prototype, {
                getChildByName: function getChildByName(name) {
                        console.warn('THREE.Object3D: .getChildByName() has been renamed to .getObjectByName().');
        }); //
 
        PerspectiveCamera.prototype.setLens = function (focalLength, filmGauge) {
-               console.warn("THREE.PerspectiveCamera.setLens is deprecated. " + "Use .setFocalLength and .filmGauge for a photographic setup.");
+               console.warn('THREE.PerspectiveCamera.setLens is deprecated. ' + 'Use .setFocalLength and .filmGauge for a photographic setup.');
                if (filmGauge !== undefined) this.filmGauge = filmGauge;
                this.setFocalLength(focalLength);
        }; //
                        console.warn('THREE.BufferGeometry: .clearDrawCalls() is now .clearGroups().');
                        this.clearGroups();
                },
-               computeTangents: function computeTangents() {
-                       console.warn('THREE.BufferGeometry: .computeTangents() has been removed.');
-               },
                computeOffsets: function computeOffsets() {
                        console.warn('THREE.BufferGeometry: .computeOffsets() has been removed.');
                },
                }
        }); //
 
-       Object.assign(ExtrudeBufferGeometry.prototype, {
+       Object.assign(ExtrudeGeometry.prototype, {
                getArrays: function getArrays() {
-                       console.error('THREE.ExtrudeBufferGeometry: .getArrays() has been removed.');
+                       console.error('THREE.ExtrudeGeometry: .getArrays() has been removed.');
                },
                addShapeList: function addShapeList() {
-                       console.error('THREE.ExtrudeBufferGeometry: .addShapeList() has been removed.');
+                       console.error('THREE.ExtrudeGeometry: .addShapeList() has been removed.');
                },
                addShape: function addShape() {
-                       console.error('THREE.ExtrudeBufferGeometry: .addShape() has been removed.');
+                       console.error('THREE.ExtrudeGeometry: .addShape() has been removed.');
                }
        }); //
 
 
        }
 
+       if (typeof window !== 'undefined') {
+               if (window.__THREE__) {
+                       console.warn('WARNING: Multiple instances of Three.js being imported.');
+               } else {
+                       window.__THREE__ = REVISION;
+               }
+       }
+
        exports.ACESFilmicToneMapping = ACESFilmicToneMapping;
        exports.AddEquation = AddEquation;
        exports.AddOperation = AddOperation;
        exports.Box2 = Box2;
        exports.Box3 = Box3;
        exports.Box3Helper = Box3Helper;
-       exports.BoxBufferGeometry = BoxBufferGeometry;
+       exports.BoxBufferGeometry = BoxGeometry;
        exports.BoxGeometry = BoxGeometry;
        exports.BoxHelper = BoxHelper;
        exports.BufferAttribute = BufferAttribute;
        exports.CanvasTexture = CanvasTexture;
        exports.CatmullRomCurve3 = CatmullRomCurve3;
        exports.CineonToneMapping = CineonToneMapping;
-       exports.CircleBufferGeometry = CircleBufferGeometry;
+       exports.CircleBufferGeometry = CircleGeometry;
        exports.CircleGeometry = CircleGeometry;
        exports.ClampToEdgeWrapping = ClampToEdgeWrapping;
        exports.Clock = Clock;
        exports.ColorKeyframeTrack = ColorKeyframeTrack;
        exports.CompressedTexture = CompressedTexture;
        exports.CompressedTextureLoader = CompressedTextureLoader;
-       exports.ConeBufferGeometry = ConeBufferGeometry;
+       exports.ConeBufferGeometry = ConeGeometry;
        exports.ConeGeometry = ConeGeometry;
        exports.CubeCamera = CubeCamera;
-       exports.CubeGeometry = BoxGeometry;
        exports.CubeReflectionMapping = CubeReflectionMapping;
        exports.CubeRefractionMapping = CubeRefractionMapping;
        exports.CubeTexture = CubeTexture;
        exports.CurvePath = CurvePath;
        exports.CustomBlending = CustomBlending;
        exports.CustomToneMapping = CustomToneMapping;
-       exports.CylinderBufferGeometry = CylinderBufferGeometry;
+       exports.CylinderBufferGeometry = CylinderGeometry;
        exports.CylinderGeometry = CylinderGeometry;
        exports.Cylindrical = Cylindrical;
        exports.DataTexture = DataTexture;
        exports.DirectionalLight = DirectionalLight;
        exports.DirectionalLightHelper = DirectionalLightHelper;
        exports.DiscreteInterpolant = DiscreteInterpolant;
-       exports.DodecahedronBufferGeometry = DodecahedronBufferGeometry;
+       exports.DodecahedronBufferGeometry = DodecahedronGeometry;
        exports.DodecahedronGeometry = DodecahedronGeometry;
        exports.DoubleSide = DoubleSide;
        exports.DstAlphaFactor = DstAlphaFactor;
        exports.EquirectangularRefractionMapping = EquirectangularRefractionMapping;
        exports.Euler = Euler;
        exports.EventDispatcher = EventDispatcher;
-       exports.ExtrudeBufferGeometry = ExtrudeBufferGeometry;
+       exports.ExtrudeBufferGeometry = ExtrudeGeometry;
        exports.ExtrudeGeometry = ExtrudeGeometry;
        exports.Face3 = Face3;
        exports.Face4 = Face4;
        exports.GLSL1 = GLSL1;
        exports.GLSL3 = GLSL3;
        exports.GammaEncoding = GammaEncoding;
-       exports.Geometry = Geometry;
        exports.GeometryUtils = GeometryUtils;
        exports.GreaterDepth = GreaterDepth;
        exports.GreaterEqualDepth = GreaterEqualDepth;
        exports.HemisphereLight = HemisphereLight;
        exports.HemisphereLightHelper = HemisphereLightHelper;
        exports.HemisphereLightProbe = HemisphereLightProbe;
-       exports.IcosahedronBufferGeometry = IcosahedronBufferGeometry;
+       exports.IcosahedronBufferGeometry = IcosahedronGeometry;
        exports.IcosahedronGeometry = IcosahedronGeometry;
        exports.ImageBitmapLoader = ImageBitmapLoader;
        exports.ImageLoader = ImageLoader;
        exports.KeepStencilOp = KeepStencilOp;
        exports.KeyframeTrack = KeyframeTrack;
        exports.LOD = LOD;
-       exports.LatheBufferGeometry = LatheBufferGeometry;
+       exports.LatheBufferGeometry = LatheGeometry;
        exports.LatheGeometry = LatheGeometry;
        exports.Layers = Layers;
        exports.LensFlare = LensFlare;
        exports.Object3D = Object3D;
        exports.ObjectLoader = ObjectLoader;
        exports.ObjectSpaceNormalMap = ObjectSpaceNormalMap;
-       exports.OctahedronBufferGeometry = OctahedronBufferGeometry;
+       exports.OctahedronBufferGeometry = OctahedronGeometry;
        exports.OctahedronGeometry = OctahedronGeometry;
        exports.OneFactor = OneFactor;
        exports.OneMinusDstAlphaFactor = OneMinusDstAlphaFactor;
        exports.PCFShadowMap = PCFShadowMap;
        exports.PCFSoftShadowMap = PCFSoftShadowMap;
        exports.PMREMGenerator = PMREMGenerator;
-       exports.ParametricBufferGeometry = ParametricBufferGeometry;
+       exports.ParametricBufferGeometry = ParametricGeometry;
        exports.ParametricGeometry = ParametricGeometry;
        exports.Particle = Particle;
        exports.ParticleBasicMaterial = ParticleBasicMaterial;
        exports.Path = Path;
        exports.PerspectiveCamera = PerspectiveCamera;
        exports.Plane = Plane;
-       exports.PlaneBufferGeometry = PlaneBufferGeometry;
+       exports.PlaneBufferGeometry = PlaneGeometry;
        exports.PlaneGeometry = PlaneGeometry;
        exports.PlaneHelper = PlaneHelper;
        exports.PointCloud = PointCloud;
        exports.Points = Points;
        exports.PointsMaterial = PointsMaterial;
        exports.PolarGridHelper = PolarGridHelper;
-       exports.PolyhedronBufferGeometry = PolyhedronBufferGeometry;
+       exports.PolyhedronBufferGeometry = PolyhedronGeometry;
        exports.PolyhedronGeometry = PolyhedronGeometry;
        exports.PositionalAudio = PositionalAudio;
        exports.PropertyBinding = PropertyBinding;
        exports.RepeatWrapping = RepeatWrapping;
        exports.ReplaceStencilOp = ReplaceStencilOp;
        exports.ReverseSubtractEquation = ReverseSubtractEquation;
-       exports.RingBufferGeometry = RingBufferGeometry;
+       exports.RingBufferGeometry = RingGeometry;
        exports.RingGeometry = RingGeometry;
        exports.SRGB8_ALPHA8_ASTC_10x10_Format = SRGB8_ALPHA8_ASTC_10x10_Format;
        exports.SRGB8_ALPHA8_ASTC_10x5_Format = SRGB8_ALPHA8_ASTC_10x5_Format;
        exports.ShaderMaterial = ShaderMaterial;
        exports.ShadowMaterial = ShadowMaterial;
        exports.Shape = Shape;
-       exports.ShapeBufferGeometry = ShapeBufferGeometry;
+       exports.ShapeBufferGeometry = ShapeGeometry;
        exports.ShapeGeometry = ShapeGeometry;
        exports.ShapePath = ShapePath;
        exports.ShapeUtils = ShapeUtils;
        exports.SkinnedMesh = SkinnedMesh;
        exports.SmoothShading = SmoothShading;
        exports.Sphere = Sphere;
-       exports.SphereBufferGeometry = SphereBufferGeometry;
+       exports.SphereBufferGeometry = SphereGeometry;
        exports.SphereGeometry = SphereGeometry;
        exports.Spherical = Spherical;
        exports.SphericalHarmonics3 = SphericalHarmonics3;
        exports.SubtractiveBlending = SubtractiveBlending;
        exports.TOUCH = TOUCH;
        exports.TangentSpaceNormalMap = TangentSpaceNormalMap;
-       exports.TetrahedronBufferGeometry = TetrahedronBufferGeometry;
+       exports.TetrahedronBufferGeometry = TetrahedronGeometry;
        exports.TetrahedronGeometry = TetrahedronGeometry;
-       exports.TextBufferGeometry = TextBufferGeometry;
+       exports.TextBufferGeometry = TextGeometry;
        exports.TextGeometry = TextGeometry;
        exports.Texture = Texture;
        exports.TextureLoader = TextureLoader;
-       exports.TorusBufferGeometry = TorusBufferGeometry;
+       exports.TorusBufferGeometry = TorusGeometry;
        exports.TorusGeometry = TorusGeometry;
-       exports.TorusKnotBufferGeometry = TorusKnotBufferGeometry;
+       exports.TorusKnotBufferGeometry = TorusKnotGeometry;
        exports.TorusKnotGeometry = TorusKnotGeometry;
        exports.Triangle = Triangle;
        exports.TriangleFanDrawMode = TriangleFanDrawMode;
        exports.TriangleStripDrawMode = TriangleStripDrawMode;
        exports.TrianglesDrawMode = TrianglesDrawMode;
-       exports.TubeBufferGeometry = TubeBufferGeometry;
+       exports.TubeBufferGeometry = TubeGeometry;
        exports.TubeGeometry = TubeGeometry;
        exports.UVMapping = UVMapping;
        exports.Uint16Attribute = Uint16Attribute;
index 4f400532591c6d2e39b422157a194112390f154a..a499d33400b6416d0462bb59ac85d05a9765ad6f 100644 (file)
@@ -1,5 +1,5 @@
 // threejs.org/license
-const REVISION = '123';
+const REVISION = '125';
 const MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2, ROTATE: 0, DOLLY: 1, PAN: 2 };
 const TOUCH = { ROTATE: 0, PAN: 1, DOLLY_PAN: 2, DOLLY_ROTATE: 3 };
 const CullFaceNone = 0;
@@ -197,8 +197,8 @@ const StaticCopyUsage = 35046;
 const DynamicCopyUsage = 35050;
 const StreamCopyUsage = 35042;
 
-const GLSL1 = "100";
-const GLSL3 = "300 es";
+const GLSL1 = '100';
+const GLSL3 = '300 es';
 
 /**
  * https://github.com/mrdoob/eventdispatcher.js/
@@ -349,6 +349,22 @@ const MathUtils = {
 
        },
 
+       // http://www.rorydriscoll.com/2016/03/07/frame-rate-independent-damping-using-lerp/
+
+       damp: function ( x, y, lambda, dt ) {
+
+               return MathUtils.lerp( x, y, 1 - Math.exp( - lambda * dt ) );
+
+       },
+
+       // https://www.desmos.com/calculator/vcsjnyz7x4
+
+       pingpong: function ( x, length = 1 ) {
+
+               return length - Math.abs( MathUtils.euclideanModulo( x, length * 2 ) - length );
+
+       },
+
        // http://en.wikipedia.org/wiki/Smoothstep
 
        smoothstep: function ( x, min, max ) {
@@ -1216,6 +1232,8 @@ class Matrix3 {
                        0, 0, 1
                );
 
+               return this;
+
        }
 
        scale( sx, sy ) {
@@ -1683,7 +1701,7 @@ Texture.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
 
 } );
 
-Object.defineProperty( Texture.prototype, "needsUpdate", {
+Object.defineProperty( Texture.prototype, 'needsUpdate', {
 
        set: function ( value ) {
 
@@ -1956,6 +1974,17 @@ class Vector4 {
 
        }
 
+       multiply( v ) {
+
+               this.x *= v.x;
+               this.y *= v.y;
+               this.z *= v.z;
+               this.w *= v.w;
+
+               return this;
+
+       }
+
        multiplyScalar( scalar ) {
 
                this.x *= scalar;
@@ -2375,40 +2404,40 @@ class Vector4 {
  * Texture parameters for an auto-generated target texture
  * depthBuffer/stencilBuffer: Booleans to indicate if we should generate these buffers
 */
-function WebGLRenderTarget( width, height, options ) {
+class WebGLRenderTarget extends EventDispatcher {
 
-       this.width = width;
-       this.height = height;
+       constructor( width, height, options ) {
 
-       this.scissor = new Vector4( 0, 0, width, height );
-       this.scissorTest = false;
+               super();
 
-       this.viewport = new Vector4( 0, 0, width, height );
+               Object.defineProperty( this, 'isWebGLRenderTarget', { value: true } );
 
-       options = options || {};
+               this.width = width;
+               this.height = height;
 
-       this.texture = new Texture( undefined, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding );
+               this.scissor = new Vector4( 0, 0, width, height );
+               this.scissorTest = false;
 
-       this.texture.image = {};
-       this.texture.image.width = width;
-       this.texture.image.height = height;
+               this.viewport = new Vector4( 0, 0, width, height );
 
-       this.texture.generateMipmaps = options.generateMipmaps !== undefined ? options.generateMipmaps : false;
-       this.texture.minFilter = options.minFilter !== undefined ? options.minFilter : LinearFilter;
+               options = options || {};
 
-       this.depthBuffer = options.depthBuffer !== undefined ? options.depthBuffer : true;
-       this.stencilBuffer = options.stencilBuffer !== undefined ? options.stencilBuffer : false;
-       this.depthTexture = options.depthTexture !== undefined ? options.depthTexture : null;
+               this.texture = new Texture( undefined, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding );
 
-}
+               this.texture.image = {};
+               this.texture.image.width = width;
+               this.texture.image.height = height;
 
-WebGLRenderTarget.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
+               this.texture.generateMipmaps = options.generateMipmaps !== undefined ? options.generateMipmaps : false;
+               this.texture.minFilter = options.minFilter !== undefined ? options.minFilter : LinearFilter;
 
-       constructor: WebGLRenderTarget,
+               this.depthBuffer = options.depthBuffer !== undefined ? options.depthBuffer : true;
+               this.stencilBuffer = options.stencilBuffer !== undefined ? options.stencilBuffer : false;
+               this.depthTexture = options.depthTexture !== undefined ? options.depthTexture : null;
 
-       isWebGLRenderTarget: true,
+       }
 
-       setSize: function ( width, height ) {
+       setSize( width, height ) {
 
                if ( this.width !== width || this.height !== height ) {
 
@@ -2425,15 +2454,15 @@ WebGLRenderTarget.prototype = Object.assign( Object.create( EventDispatcher.prot
                this.viewport.set( 0, 0, width, height );
                this.scissor.set( 0, 0, width, height );
 
-       },
+       }
 
-       clone: function () {
+       clone() {
 
                return new this.constructor().copy( this );
 
-       },
+       }
 
-       copy: function ( source ) {
+       copy( source ) {
 
                this.width = source.width;
                this.height = source.height;
@@ -2448,33 +2477,31 @@ WebGLRenderTarget.prototype = Object.assign( Object.create( EventDispatcher.prot
 
                return this;
 
-       },
+       }
 
-       dispose: function () {
+       dispose() {
 
                this.dispatchEvent( { type: 'dispose' } );
 
        }
 
-} );
-
-function WebGLMultisampleRenderTarget( width, height, options ) {
+}
 
-       WebGLRenderTarget.call( this, width, height, options );
+class WebGLMultisampleRenderTarget extends WebGLRenderTarget {
 
-       this.samples = 4;
+       constructor( width, height, options ) {
 
-}
+               super( width, height, options );
 
-WebGLMultisampleRenderTarget.prototype = Object.assign( Object.create( WebGLRenderTarget.prototype ), {
+               Object.defineProperty( this, 'isWebGLMultisampleRenderTarget', { value: true } );
 
-       constructor: WebGLMultisampleRenderTarget,
+               this.samples = 4;
 
-       isWebGLMultisampleRenderTarget: true,
+       }
 
-       copy: function ( source ) {
+       copy( source ) {
 
-               WebGLRenderTarget.prototype.copy.call( this, source );
+               super.copy.call( this, source );
 
                this.samples = source.samples;
 
@@ -2482,7 +2509,7 @@ WebGLMultisampleRenderTarget.prototype = Object.assign( Object.create( WebGLRend
 
        }
 
-} );
+}
 
 class Quaternion {
 
@@ -5160,6 +5187,23 @@ class Matrix4 {
 
        }
 
+       setFromMatrix3( m ) {
+
+               const me = m.elements;
+
+               this.set(
+
+                       me[ 0 ], me[ 3 ], me[ 6 ], 0,
+                       me[ 1 ], me[ 4 ], me[ 7 ], 0,
+                       me[ 2 ], me[ 5 ], me[ 8 ], 0,
+                       0, 0, 0, 1
+
+               );
+
+               return this;
+
+       }
+
        extractBasis( xAxis, yAxis, zAxis ) {
 
                xAxis.setFromMatrixColumn( this, 0 );
@@ -6622,12 +6666,12 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ),
 
                if ( object === this ) {
 
-                       console.error( "THREE.Object3D.add: object can't be added as a child of itself.", object );
+                       console.error( 'THREE.Object3D.add: object can\'t be added as a child of itself.', object );
                        return this;
 
                }
 
-               if ( ( object && object.isObject3D ) ) {
+               if ( object && object.isObject3D ) {
 
                        if ( object.parent !== null ) {
 
@@ -6642,7 +6686,7 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ),
 
                } else {
 
-                       console.error( "THREE.Object3D.add: object not an instance of THREE.Object3D.", object );
+                       console.error( 'THREE.Object3D.add: object not an instance of THREE.Object3D.', object );
 
                }
 
@@ -7922,7 +7966,7 @@ class Color {
 
                let m;
 
-               if ( m = /^((?:rgb|hsl)a?)\(\s*([^\)]*)\)/.exec( style ) ) {
+               if ( m = /^((?:rgb|hsl)a?)\(([^\)]*)\)/.exec( style ) ) {
 
                        // rgb / hsl
 
@@ -7935,27 +7979,27 @@ class Color {
                                case 'rgb':
                                case 'rgba':
 
-                                       if ( color = /^(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec( components ) ) {
+                                       if ( color = /^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) {
 
                                                // rgb(255,0,0) rgba(255,0,0,0.5)
                                                this.r = Math.min( 255, parseInt( color[ 1 ], 10 ) ) / 255;
                                                this.g = Math.min( 255, parseInt( color[ 2 ], 10 ) ) / 255;
                                                this.b = Math.min( 255, parseInt( color[ 3 ], 10 ) ) / 255;
 
-                                               handleAlpha( color[ 5 ] );
+                                               handleAlpha( color[ 4 ] );
 
                                                return this;
 
                                        }
 
-                                       if ( color = /^(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec( components ) ) {
+                                       if ( color = /^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) {
 
                                                // rgb(100%,0%,0%) rgba(100%,0%,0%,0.5)
                                                this.r = Math.min( 100, parseInt( color[ 1 ], 10 ) ) / 100;
                                                this.g = Math.min( 100, parseInt( color[ 2 ], 10 ) ) / 100;
                                                this.b = Math.min( 100, parseInt( color[ 3 ], 10 ) ) / 100;
 
-                                               handleAlpha( color[ 5 ] );
+                                               handleAlpha( color[ 4 ] );
 
                                                return this;
 
@@ -7966,14 +8010,14 @@ class Color {
                                case 'hsl':
                                case 'hsla':
 
-                                       if ( color = /^([0-9]*\.?[0-9]+)\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec( components ) ) {
+                                       if ( color = /^\s*(\d*\.?\d+)\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) {
 
                                                // hsl(120,50%,50%) hsla(120,50%,50%,0.5)
                                                const h = parseFloat( color[ 1 ] ) / 360;
                                                const s = parseInt( color[ 2 ], 10 ) / 100;
                                                const l = parseInt( color[ 3 ], 10 ) / 100;
 
-                                               handleAlpha( color[ 5 ] );
+                                               handleAlpha( color[ 4 ] );
 
                                                return this.setHSL( h, s, l );
 
@@ -7983,7 +8027,7 @@ class Color {
 
                        }
 
-               } else if ( m = /^\#([A-Fa-f0-9]+)$/.exec( style ) ) {
+               } else if ( m = /^\#([A-Fa-f\d]+)$/.exec( style ) ) {
 
                        // hex color
 
@@ -8283,6 +8327,16 @@ class Color {
 
        }
 
+       lerpColors( color1, color2, alpha ) {
+
+               this.r = color1.r + ( color2.r - color1.r ) * alpha;
+               this.g = color1.g + ( color2.g - color1.g ) * alpha;
+               this.b = color1.b + ( color2.b - color1.b ) * alpha;
+
+               return this;
+
+       }
+
        lerpHSL( color, alpha ) {
 
                this.getHSL( _hslA );
@@ -8504,7 +8558,7 @@ Material.prototype = Object.assign( Object.create( EventDispatcher.prototype ),
 
                        if ( newValue === undefined ) {
 
-                               console.warn( "THREE.Material: '" + key + "' parameter is undefined." );
+                               console.warn( 'THREE.Material: \'' + key + '\' parameter is undefined.' );
                                continue;
 
                        }
@@ -8522,7 +8576,7 @@ Material.prototype = Object.assign( Object.create( EventDispatcher.prototype ),
 
                        if ( currentValue === undefined ) {
 
-                               console.warn( "THREE." + this.type + ": '" + key + "' is not a property of this material." );
+                               console.warn( 'THREE.' + this.type + ': \'' + key + '\' is not a property of this material.' );
                                continue;
 
                        }
@@ -9464,285 +9518,6 @@ function Float64BufferAttribute( array, itemSize, normalized ) {
 Float64BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
 Float64BufferAttribute.prototype.constructor = Float64BufferAttribute;
 
-class DirectGeometry {
-
-       constructor() {
-
-               this.vertices = [];
-               this.normals = [];
-               this.colors = [];
-               this.uvs = [];
-               this.uvs2 = [];
-
-               this.groups = [];
-
-               this.morphTargets = {};
-
-               this.skinWeights = [];
-               this.skinIndices = [];
-
-               // this.lineDistances = [];
-
-               this.boundingBox = null;
-               this.boundingSphere = null;
-
-               // update flags
-
-               this.verticesNeedUpdate = false;
-               this.normalsNeedUpdate = false;
-               this.colorsNeedUpdate = false;
-               this.uvsNeedUpdate = false;
-               this.groupsNeedUpdate = false;
-
-       }
-
-       computeGroups( geometry ) {
-
-               const groups = [];
-
-               let group, i;
-               let materialIndex = undefined;
-
-               const faces = geometry.faces;
-
-               for ( i = 0; i < faces.length; i ++ ) {
-
-                       const face = faces[ i ];
-
-                       // materials
-
-                       if ( face.materialIndex !== materialIndex ) {
-
-                               materialIndex = face.materialIndex;
-
-                               if ( group !== undefined ) {
-
-                                       group.count = ( i * 3 ) - group.start;
-                                       groups.push( group );
-
-                               }
-
-                               group = {
-                                       start: i * 3,
-                                       materialIndex: materialIndex
-                               };
-
-                       }
-
-               }
-
-               if ( group !== undefined ) {
-
-                       group.count = ( i * 3 ) - group.start;
-                       groups.push( group );
-
-               }
-
-               this.groups = groups;
-
-       }
-
-       fromGeometry( geometry ) {
-
-               const faces = geometry.faces;
-               const vertices = geometry.vertices;
-               const faceVertexUvs = geometry.faceVertexUvs;
-
-               const hasFaceVertexUv = faceVertexUvs[ 0 ] && faceVertexUvs[ 0 ].length > 0;
-               const hasFaceVertexUv2 = faceVertexUvs[ 1 ] && faceVertexUvs[ 1 ].length > 0;
-
-               // morphs
-
-               const morphTargets = geometry.morphTargets;
-               const morphTargetsLength = morphTargets.length;
-
-               let morphTargetsPosition;
-
-               if ( morphTargetsLength > 0 ) {
-
-                       morphTargetsPosition = [];
-
-                       for ( let i = 0; i < morphTargetsLength; i ++ ) {
-
-                               morphTargetsPosition[ i ] = {
-                                       name: morphTargets[ i ].name,
-                                       data: []
-                               };
-
-                       }
-
-                       this.morphTargets.position = morphTargetsPosition;
-
-               }
-
-               const morphNormals = geometry.morphNormals;
-               const morphNormalsLength = morphNormals.length;
-
-               let morphTargetsNormal;
-
-               if ( morphNormalsLength > 0 ) {
-
-                       morphTargetsNormal = [];
-
-                       for ( let i = 0; i < morphNormalsLength; i ++ ) {
-
-                               morphTargetsNormal[ i ] = {
-                                       name: morphNormals[ i ].name,
-                                       data: []
-                               };
-
-                       }
-
-                       this.morphTargets.normal = morphTargetsNormal;
-
-               }
-
-               // skins
-
-               const skinIndices = geometry.skinIndices;
-               const skinWeights = geometry.skinWeights;
-
-               const hasSkinIndices = skinIndices.length === vertices.length;
-               const hasSkinWeights = skinWeights.length === vertices.length;
-
-               //
-
-               if ( vertices.length > 0 && faces.length === 0 ) {
-
-                       console.error( 'THREE.DirectGeometry: Faceless geometries are not supported.' );
-
-               }
-
-               for ( let i = 0; i < faces.length; i ++ ) {
-
-                       const face = faces[ i ];
-
-                       this.vertices.push( vertices[ face.a ], vertices[ face.b ], vertices[ face.c ] );
-
-                       const vertexNormals = face.vertexNormals;
-
-                       if ( vertexNormals.length === 3 ) {
-
-                               this.normals.push( vertexNormals[ 0 ], vertexNormals[ 1 ], vertexNormals[ 2 ] );
-
-                       } else {
-
-                               const normal = face.normal;
-
-                               this.normals.push( normal, normal, normal );
-
-                       }
-
-                       const vertexColors = face.vertexColors;
-
-                       if ( vertexColors.length === 3 ) {
-
-                               this.colors.push( vertexColors[ 0 ], vertexColors[ 1 ], vertexColors[ 2 ] );
-
-                       } else {
-
-                               const color = face.color;
-
-                               this.colors.push( color, color, color );
-
-                       }
-
-                       if ( hasFaceVertexUv === true ) {
-
-                               const vertexUvs = faceVertexUvs[ 0 ][ i ];
-
-                               if ( vertexUvs !== undefined ) {
-
-                                       this.uvs.push( vertexUvs[ 0 ], vertexUvs[ 1 ], vertexUvs[ 2 ] );
-
-                               } else {
-
-                                       console.warn( 'THREE.DirectGeometry.fromGeometry(): Undefined vertexUv ', i );
-
-                                       this.uvs.push( new Vector2(), new Vector2(), new Vector2() );
-
-                               }
-
-                       }
-
-                       if ( hasFaceVertexUv2 === true ) {
-
-                               const vertexUvs = faceVertexUvs[ 1 ][ i ];
-
-                               if ( vertexUvs !== undefined ) {
-
-                                       this.uvs2.push( vertexUvs[ 0 ], vertexUvs[ 1 ], vertexUvs[ 2 ] );
-
-                               } else {
-
-                                       console.warn( 'THREE.DirectGeometry.fromGeometry(): Undefined vertexUv2 ', i );
-
-                                       this.uvs2.push( new Vector2(), new Vector2(), new Vector2() );
-
-                               }
-
-                       }
-
-                       // morphs
-
-                       for ( let j = 0; j < morphTargetsLength; j ++ ) {
-
-                               const morphTarget = morphTargets[ j ].vertices;
-
-                               morphTargetsPosition[ j ].data.push( morphTarget[ face.a ], morphTarget[ face.b ], morphTarget[ face.c ] );
-
-                       }
-
-                       for ( let j = 0; j < morphNormalsLength; j ++ ) {
-
-                               const morphNormal = morphNormals[ j ].vertexNormals[ i ];
-
-                               morphTargetsNormal[ j ].data.push( morphNormal.a, morphNormal.b, morphNormal.c );
-
-                       }
-
-                       // skins
-
-                       if ( hasSkinIndices ) {
-
-                               this.skinIndices.push( skinIndices[ face.a ], skinIndices[ face.b ], skinIndices[ face.c ] );
-
-                       }
-
-                       if ( hasSkinWeights ) {
-
-                               this.skinWeights.push( skinWeights[ face.a ], skinWeights[ face.b ], skinWeights[ face.c ] );
-
-                       }
-
-               }
-
-               this.computeGroups( geometry );
-
-               this.verticesNeedUpdate = geometry.verticesNeedUpdate;
-               this.normalsNeedUpdate = geometry.normalsNeedUpdate;
-               this.colorsNeedUpdate = geometry.colorsNeedUpdate;
-               this.uvsNeedUpdate = geometry.uvsNeedUpdate;
-               this.groupsNeedUpdate = geometry.groupsNeedUpdate;
-
-               if ( geometry.boundingSphere !== null ) {
-
-                       this.boundingSphere = geometry.boundingSphere.clone();
-
-               }
-
-               if ( geometry.boundingBox !== null ) {
-
-                       this.boundingBox = geometry.boundingBox.clone();
-
-               }
-
-               return this;
-
-       }
-
-}
-
 function arrayMax( array ) {
 
        if ( array.length === 0 ) return - Infinity;
@@ -9778,7 +9553,7 @@ function getTypedArray( type, buffer ) {
 
 }
 
-let _bufferGeometryId = 1; // BufferGeometry uses odd numbers as Id
+let _id = 0;
 
 const _m1$2 = new Matrix4();
 const _obj = new Object3D();
@@ -9789,7 +9564,7 @@ const _vector$4 = new Vector3();
 
 function BufferGeometry() {
 
-       Object.defineProperty( this, 'id', { value: _bufferGeometryId += 2 } );
+       Object.defineProperty( this, 'id', { value: _id ++ } );
 
        this.uuid = MathUtils.generateUUID();
 
@@ -10028,54 +9803,6 @@ BufferGeometry.prototype = Object.assign( Object.create( EventDispatcher.prototy
 
        },
 
-       setFromObject: function ( object ) {
-
-               // console.log( 'THREE.BufferGeometry.setFromObject(). Converting', object, this );
-
-               const geometry = object.geometry;
-
-               if ( object.isPoints || object.isLine ) {
-
-                       const positions = new Float32BufferAttribute( geometry.vertices.length * 3, 3 );
-                       const colors = new Float32BufferAttribute( geometry.colors.length * 3, 3 );
-
-                       this.setAttribute( 'position', positions.copyVector3sArray( geometry.vertices ) );
-                       this.setAttribute( 'color', colors.copyColorsArray( geometry.colors ) );
-
-                       if ( geometry.lineDistances && geometry.lineDistances.length === geometry.vertices.length ) {
-
-                               const lineDistances = new Float32BufferAttribute( geometry.lineDistances.length, 1 );
-
-                               this.setAttribute( 'lineDistance', lineDistances.copyArray( geometry.lineDistances ) );
-
-                       }
-
-                       if ( geometry.boundingSphere !== null ) {
-
-                               this.boundingSphere = geometry.boundingSphere.clone();
-
-                       }
-
-                       if ( geometry.boundingBox !== null ) {
-
-                               this.boundingBox = geometry.boundingBox.clone();
-
-                       }
-
-               } else if ( object.isMesh ) {
-
-                       if ( geometry && geometry.isGeometry ) {
-
-                               this.fromGeometry( geometry );
-
-                       }
-
-               }
-
-               return this;
-
-       },
-
        setFromPoints: function ( points ) {
 
                const position = [];
@@ -10093,232 +9820,6 @@ BufferGeometry.prototype = Object.assign( Object.create( EventDispatcher.prototy
 
        },
 
-       updateFromObject: function ( object ) {
-
-               let geometry = object.geometry;
-
-               if ( object.isMesh ) {
-
-                       let direct = geometry.__directGeometry;
-
-                       if ( geometry.elementsNeedUpdate === true ) {
-
-                               direct = undefined;
-                               geometry.elementsNeedUpdate = false;
-
-                       }
-
-                       if ( direct === undefined ) {
-
-                               return this.fromGeometry( geometry );
-
-                       }
-
-                       direct.verticesNeedUpdate = geometry.verticesNeedUpdate;
-                       direct.normalsNeedUpdate = geometry.normalsNeedUpdate;
-                       direct.colorsNeedUpdate = geometry.colorsNeedUpdate;
-                       direct.uvsNeedUpdate = geometry.uvsNeedUpdate;
-                       direct.groupsNeedUpdate = geometry.groupsNeedUpdate;
-
-                       geometry.verticesNeedUpdate = false;
-                       geometry.normalsNeedUpdate = false;
-                       geometry.colorsNeedUpdate = false;
-                       geometry.uvsNeedUpdate = false;
-                       geometry.groupsNeedUpdate = false;
-
-                       geometry = direct;
-
-               }
-
-               if ( geometry.verticesNeedUpdate === true ) {
-
-                       const attribute = this.attributes.position;
-
-                       if ( attribute !== undefined ) {
-
-                               attribute.copyVector3sArray( geometry.vertices );
-                               attribute.needsUpdate = true;
-
-                       }
-
-                       geometry.verticesNeedUpdate = false;
-
-               }
-
-               if ( geometry.normalsNeedUpdate === true ) {
-
-                       const attribute = this.attributes.normal;
-
-                       if ( attribute !== undefined ) {
-
-                               attribute.copyVector3sArray( geometry.normals );
-                               attribute.needsUpdate = true;
-
-                       }
-
-                       geometry.normalsNeedUpdate = false;
-
-               }
-
-               if ( geometry.colorsNeedUpdate === true ) {
-
-                       const attribute = this.attributes.color;
-
-                       if ( attribute !== undefined ) {
-
-                               attribute.copyColorsArray( geometry.colors );
-                               attribute.needsUpdate = true;
-
-                       }
-
-                       geometry.colorsNeedUpdate = false;
-
-               }
-
-               if ( geometry.uvsNeedUpdate ) {
-
-                       const attribute = this.attributes.uv;
-
-                       if ( attribute !== undefined ) {
-
-                               attribute.copyVector2sArray( geometry.uvs );
-                               attribute.needsUpdate = true;
-
-                       }
-
-                       geometry.uvsNeedUpdate = false;
-
-               }
-
-               if ( geometry.lineDistancesNeedUpdate ) {
-
-                       const attribute = this.attributes.lineDistance;
-
-                       if ( attribute !== undefined ) {
-
-                               attribute.copyArray( geometry.lineDistances );
-                               attribute.needsUpdate = true;
-
-                       }
-
-                       geometry.lineDistancesNeedUpdate = false;
-
-               }
-
-               if ( geometry.groupsNeedUpdate ) {
-
-                       geometry.computeGroups( object.geometry );
-                       this.groups = geometry.groups;
-
-                       geometry.groupsNeedUpdate = false;
-
-               }
-
-               return this;
-
-       },
-
-       fromGeometry: function ( geometry ) {
-
-               geometry.__directGeometry = new DirectGeometry().fromGeometry( geometry );
-
-               return this.fromDirectGeometry( geometry.__directGeometry );
-
-       },
-
-       fromDirectGeometry: function ( geometry ) {
-
-               const positions = new Float32Array( geometry.vertices.length * 3 );
-               this.setAttribute( 'position', new BufferAttribute( positions, 3 ).copyVector3sArray( geometry.vertices ) );
-
-               if ( geometry.normals.length > 0 ) {
-
-                       const normals = new Float32Array( geometry.normals.length * 3 );
-                       this.setAttribute( 'normal', new BufferAttribute( normals, 3 ).copyVector3sArray( geometry.normals ) );
-
-               }
-
-               if ( geometry.colors.length > 0 ) {
-
-                       const colors = new Float32Array( geometry.colors.length * 3 );
-                       this.setAttribute( 'color', new BufferAttribute( colors, 3 ).copyColorsArray( geometry.colors ) );
-
-               }
-
-               if ( geometry.uvs.length > 0 ) {
-
-                       const uvs = new Float32Array( geometry.uvs.length * 2 );
-                       this.setAttribute( 'uv', new BufferAttribute( uvs, 2 ).copyVector2sArray( geometry.uvs ) );
-
-               }
-
-               if ( geometry.uvs2.length > 0 ) {
-
-                       const uvs2 = new Float32Array( geometry.uvs2.length * 2 );
-                       this.setAttribute( 'uv2', new BufferAttribute( uvs2, 2 ).copyVector2sArray( geometry.uvs2 ) );
-
-               }
-
-               // groups
-
-               this.groups = geometry.groups;
-
-               // morphs
-
-               for ( const name in geometry.morphTargets ) {
-
-                       const array = [];
-                       const morphTargets = geometry.morphTargets[ name ];
-
-                       for ( let i = 0, l = morphTargets.length; i < l; i ++ ) {
-
-                               const morphTarget = morphTargets[ i ];
-
-                               const attribute = new Float32BufferAttribute( morphTarget.data.length * 3, 3 );
-                               attribute.name = morphTarget.name;
-
-                               array.push( attribute.copyVector3sArray( morphTarget.data ) );
-
-                       }
-
-                       this.morphAttributes[ name ] = array;
-
-               }
-
-               // skinning
-
-               if ( geometry.skinIndices.length > 0 ) {
-
-                       const skinIndices = new Float32BufferAttribute( geometry.skinIndices.length * 4, 4 );
-                       this.setAttribute( 'skinIndex', skinIndices.copyVector4sArray( geometry.skinIndices ) );
-
-               }
-
-               if ( geometry.skinWeights.length > 0 ) {
-
-                       const skinWeights = new Float32BufferAttribute( geometry.skinWeights.length * 4, 4 );
-                       this.setAttribute( 'skinWeight', skinWeights.copyVector4sArray( geometry.skinWeights ) );
-
-               }
-
-               //
-
-               if ( geometry.boundingSphere !== null ) {
-
-                       this.boundingSphere = geometry.boundingSphere.clone();
-
-               }
-
-               if ( geometry.boundingBox !== null ) {
-
-                       this.boundingBox = geometry.boundingBox.clone();
-
-               }
-
-               return this;
-
-       },
-
        computeBoundingBox: function () {
 
                if ( this.boundingBox === null ) {
@@ -10507,6 +10008,171 @@ BufferGeometry.prototype = Object.assign( Object.create( EventDispatcher.prototy
 
        },
 
+       computeTangents: function () {
+
+               const index = this.index;
+               const attributes = this.attributes;
+
+               // based on http://www.terathon.com/code/tangent.html
+               // (per vertex tangents)
+
+               if ( index === null ||
+                        attributes.position === undefined ||
+                        attributes.normal === undefined ||
+                        attributes.uv === undefined ) {
+
+                       console.error( 'THREE.BufferGeometry: .computeTangents() failed. Missing required attributes (index, position, normal or uv)' );
+                       return;
+
+               }
+
+               const indices = index.array;
+               const positions = attributes.position.array;
+               const normals = attributes.normal.array;
+               const uvs = attributes.uv.array;
+
+               const nVertices = positions.length / 3;
+
+               if ( attributes.tangent === undefined ) {
+
+                       this.setAttribute( 'tangent', new BufferAttribute( new Float32Array( 4 * nVertices ), 4 ) );
+
+               }
+
+               const tangents = attributes.tangent.array;
+
+               const tan1 = [], tan2 = [];
+
+               for ( let i = 0; i < nVertices; i ++ ) {
+
+                       tan1[ i ] = new Vector3();
+                       tan2[ i ] = new Vector3();
+
+               }
+
+               const vA = new Vector3(),
+                       vB = new Vector3(),
+                       vC = new Vector3(),
+
+                       uvA = new Vector2(),
+                       uvB = new Vector2(),
+                       uvC = new Vector2(),
+
+                       sdir = new Vector3(),
+                       tdir = new Vector3();
+
+               function handleTriangle( a, b, c ) {
+
+                       vA.fromArray( positions, a * 3 );
+                       vB.fromArray( positions, b * 3 );
+                       vC.fromArray( positions, c * 3 );
+
+                       uvA.fromArray( uvs, a * 2 );
+                       uvB.fromArray( uvs, b * 2 );
+                       uvC.fromArray( uvs, c * 2 );
+
+                       vB.sub( vA );
+                       vC.sub( vA );
+
+                       uvB.sub( uvA );
+                       uvC.sub( uvA );
+
+                       const r = 1.0 / ( uvB.x * uvC.y - uvC.x * uvB.y );
+
+                       // silently ignore degenerate uv triangles having coincident or colinear vertices
+
+                       if ( ! isFinite( r ) ) return;
+
+                       sdir.copy( vB ).multiplyScalar( uvC.y ).addScaledVector( vC, - uvB.y ).multiplyScalar( r );
+                       tdir.copy( vC ).multiplyScalar( uvB.x ).addScaledVector( vB, - uvC.x ).multiplyScalar( r );
+
+                       tan1[ a ].add( sdir );
+                       tan1[ b ].add( sdir );
+                       tan1[ c ].add( sdir );
+
+                       tan2[ a ].add( tdir );
+                       tan2[ b ].add( tdir );
+                       tan2[ c ].add( tdir );
+
+               }
+
+               let groups = this.groups;
+
+               if ( groups.length === 0 ) {
+
+                       groups = [ {
+                               start: 0,
+                               count: indices.length
+                       } ];
+
+               }
+
+               for ( let i = 0, il = groups.length; i < il; ++ i ) {
+
+                       const group = groups[ i ];
+
+                       const start = group.start;
+                       const count = group.count;
+
+                       for ( let j = start, jl = start + count; j < jl; j += 3 ) {
+
+                               handleTriangle(
+                                       indices[ j + 0 ],
+                                       indices[ j + 1 ],
+                                       indices[ j + 2 ]
+                               );
+
+                       }
+
+               }
+
+               const tmp = new Vector3(), tmp2 = new Vector3();
+               const n = new Vector3(), n2 = new Vector3();
+
+               function handleVertex( v ) {
+
+                       n.fromArray( normals, v * 3 );
+                       n2.copy( n );
+
+                       const t = tan1[ v ];
+
+                       // Gram-Schmidt orthogonalize
+
+                       tmp.copy( t );
+                       tmp.sub( n.multiplyScalar( n.dot( t ) ) ).normalize();
+
+                       // Calculate handedness
+
+                       tmp2.crossVectors( n2, t );
+                       const test = tmp2.dot( tan2[ v ] );
+                       const w = ( test < 0.0 ) ? - 1.0 : 1.0;
+
+                       tangents[ v * 4 ] = tmp.x;
+                       tangents[ v * 4 + 1 ] = tmp.y;
+                       tangents[ v * 4 + 2 ] = tmp.z;
+                       tangents[ v * 4 + 3 ] = w;
+
+               }
+
+               for ( let i = 0, il = groups.length; i < il; ++ i ) {
+
+                       const group = groups[ i ];
+
+                       const start = group.start;
+                       const count = group.count;
+
+                       for ( let j = start, jl = start + count; j < jl; j += 3 ) {
+
+                               handleVertex( indices[ j + 0 ] );
+                               handleVertex( indices[ j + 1 ] );
+                               handleVertex( indices[ j + 2 ] );
+
+                       }
+
+               }
+
+       },
+
        computeVertexNormals: function () {
 
                const index = this.index;
@@ -10694,7 +10360,7 @@ BufferGeometry.prototype = Object.assign( Object.create( EventDispatcher.prototy
 
                if ( this.index === null ) {
 
-                       console.warn( 'THREE.BufferGeometry.toNonIndexed(): Geometry is already non-indexed.' );
+                       console.warn( 'THREE.BufferGeometry.toNonIndexed(): BufferGeometry is already non-indexed.' );
                        return this;
 
                }
@@ -11041,14 +10707,14 @@ const _uvC = new Vector2();
 const _intersectionPoint = new Vector3();
 const _intersectionPointWorld = new Vector3();
 
-function Mesh( geometry, material ) {
+function Mesh( geometry = new BufferGeometry(), material = new MeshBasicMaterial() ) {
 
        Object3D.call( this );
 
        this.type = 'Mesh';
 
-       this.geometry = geometry !== undefined ? geometry : new BufferGeometry();
-       this.material = material !== undefined ? material : new MeshBasicMaterial();
+       this.geometry = geometry;
+       this.material = material;
 
        this.updateMorphTargets();
 
@@ -11291,48 +10957,7 @@ Mesh.prototype = Object.assign( Object.create( Object3D.prototype ), {
 
                } else if ( geometry.isGeometry ) {
 
-                       const isMultiMaterial = Array.isArray( material );
-
-                       const vertices = geometry.vertices;
-                       const faces = geometry.faces;
-                       let uvs;
-
-                       const faceVertexUvs = geometry.faceVertexUvs[ 0 ];
-                       if ( faceVertexUvs.length > 0 ) uvs = faceVertexUvs;
-
-                       for ( let f = 0, fl = faces.length; f < fl; f ++ ) {
-
-                               const face = faces[ f ];
-                               const faceMaterial = isMultiMaterial ? material[ face.materialIndex ] : material;
-
-                               if ( faceMaterial === undefined ) continue;
-
-                               const fvA = vertices[ face.a ];
-                               const fvB = vertices[ face.b ];
-                               const fvC = vertices[ face.c ];
-
-                               intersection = checkIntersection( this, faceMaterial, raycaster, _ray, fvA, fvB, fvC, _intersectionPoint );
-
-                               if ( intersection ) {
-
-                                       if ( uvs && uvs[ f ] ) {
-
-                                               const uvs_f = uvs[ f ];
-                                               _uvA.copy( uvs_f[ 0 ] );
-                                               _uvB.copy( uvs_f[ 1 ] );
-                                               _uvC.copy( uvs_f[ 2 ] );
-
-                                               intersection.uv = Triangle.getUV( _intersectionPoint, fvA, fvB, fvC, _uvA, _uvB, _uvC, new Vector2() );
-
-                                       }
-
-                                       intersection.face = face;
-                                       intersection.faceIndex = f;
-                                       intersects.push( intersection );
-
-                               }
-
-                       }
+                       console.error( 'THREE.Mesh.raycast() no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.' );
 
                }
 
@@ -11461,13 +11086,13 @@ function checkBufferGeometryIntersection( object, material, raycaster, ray, posi
 
 }
 
-class BoxBufferGeometry extends BufferGeometry {
+class BoxGeometry extends BufferGeometry {
 
        constructor( width = 1, height = 1, depth = 1, widthSegments = 1, heightSegments = 1, depthSegments = 1 ) {
 
                super();
 
-               this.type = 'BoxBufferGeometry';
+               this.type = 'BoxGeometry';
 
                this.parameters = {
                        width: width,
@@ -12027,7 +11652,7 @@ PerspectiveCamera.prototype = Object.assign( Object.create( Camera.prototype ),
         */
        setFocalLength: function ( focalLength ) {
 
-               // see http://www.bobatkins.com/photography/technical/field_of_view.html
+               /** see {@link http://www.bobatkins.com/photography/technical/field_of_view.html} */
                const vExtentSlope = 0.5 * this.getFilmHeight() / focalLength;
 
                this.fov = MathUtils.RAD2DEG * 2 * Math.atan( vExtentSlope );
@@ -12340,137 +11965,138 @@ Object.defineProperty( CubeTexture.prototype, 'images', {
 
 } );
 
-function WebGLCubeRenderTarget( size, options, dummy ) {
+class WebGLCubeRenderTarget extends WebGLRenderTarget {
 
-       if ( Number.isInteger( options ) ) {
+       constructor( size, options, dummy ) {
 
-               console.warn( 'THREE.WebGLCubeRenderTarget: constructor signature is now WebGLCubeRenderTarget( size, options )' );
+               if ( Number.isInteger( options ) ) {
 
-               options = dummy;
+                       console.warn( 'THREE.WebGLCubeRenderTarget: constructor signature is now WebGLCubeRenderTarget( size, options )' );
 
-       }
+                       options = dummy;
 
-       WebGLRenderTarget.call( this, size, size, options );
+               }
 
-       options = options || {};
+               super( size, size, options );
 
-       this.texture = new CubeTexture( undefined, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding );
+               Object.defineProperty( this, 'isWebGLCubeRenderTarget', { value: true } );
 
-       this.texture._needsFlipEnvMap = false;
+               options = options || {};
 
-}
+               this.texture = new CubeTexture( undefined, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding );
 
-WebGLCubeRenderTarget.prototype = Object.create( WebGLRenderTarget.prototype );
-WebGLCubeRenderTarget.prototype.constructor = WebGLCubeRenderTarget;
+               this.texture._needsFlipEnvMap = false;
 
-WebGLCubeRenderTarget.prototype.isWebGLCubeRenderTarget = true;
+       }
 
-WebGLCubeRenderTarget.prototype.fromEquirectangularTexture = function ( renderer, texture ) {
+       fromEquirectangularTexture( renderer, texture ) {
 
-       this.texture.type = texture.type;
-       this.texture.format = RGBAFormat; // see #18859
-       this.texture.encoding = texture.encoding;
+               this.texture.type = texture.type;
+               this.texture.format = RGBAFormat; // see #18859
+               this.texture.encoding = texture.encoding;
 
-       this.texture.generateMipmaps = texture.generateMipmaps;
-       this.texture.minFilter = texture.minFilter;
-       this.texture.magFilter = texture.magFilter;
+               this.texture.generateMipmaps = texture.generateMipmaps;
+               this.texture.minFilter = texture.minFilter;
+               this.texture.magFilter = texture.magFilter;
 
-       const shader = {
+               const shader = {
 
-               uniforms: {
-                       tEquirect: { value: null },
-               },
+                       uniforms: {
+                               tEquirect: { value: null },
+                       },
 
-               vertexShader: /* glsl */`
+                       vertexShader: /* glsl */`
 
-                       varying vec3 vWorldDirection;
+                               varying vec3 vWorldDirection;
 
-                       vec3 transformDirection( in vec3 dir, in mat4 matrix ) {
+                               vec3 transformDirection( in vec3 dir, in mat4 matrix ) {
 
-                               return normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );
+                                       return normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );
 
-                       }
+                               }
 
-                       void main() {
+                               void main() {
 
-                               vWorldDirection = transformDirection( position, modelMatrix );
+                                       vWorldDirection = transformDirection( position, modelMatrix );
 
-                               #include <begin_vertex>
-                               #include <project_vertex>
+                                       #include <begin_vertex>
+                                       #include <project_vertex>
 
-                       }
-               `,
+                               }
+                       `,
 
-               fragmentShader: /* glsl */`
+                       fragmentShader: /* glsl */`
 
-                       uniform sampler2D tEquirect;
+                               uniform sampler2D tEquirect;
 
-                       varying vec3 vWorldDirection;
+                               varying vec3 vWorldDirection;
 
-                       #include <common>
+                               #include <common>
 
-                       void main() {
+                               void main() {
 
-                               vec3 direction = normalize( vWorldDirection );
+                                       vec3 direction = normalize( vWorldDirection );
 
-                               vec2 sampleUV = equirectUv( direction );
+                                       vec2 sampleUV = equirectUv( direction );
 
-                               gl_FragColor = texture2D( tEquirect, sampleUV );
+                                       gl_FragColor = texture2D( tEquirect, sampleUV );
 
-                       }
-               `
-       };
+                               }
+                       `
+               };
 
-       const geometry = new BoxBufferGeometry( 5, 5, 5 );
+               const geometry = new BoxGeometry( 5, 5, 5 );
 
-       const material = new ShaderMaterial( {
+               const material = new ShaderMaterial( {
 
-               name: 'CubemapFromEquirect',
+                       name: 'CubemapFromEquirect',
 
-               uniforms: cloneUniforms( shader.uniforms ),
-               vertexShader: shader.vertexShader,
-               fragmentShader: shader.fragmentShader,
-               side: BackSide,
-               blending: NoBlending
+                       uniforms: cloneUniforms( shader.uniforms ),
+                       vertexShader: shader.vertexShader,
+                       fragmentShader: shader.fragmentShader,
+                       side: BackSide,
+                       blending: NoBlending
 
-       } );
+               } );
 
-       material.uniforms.tEquirect.value = texture;
+               material.uniforms.tEquirect.value = texture;
 
-       const mesh = new Mesh( geometry, material );
+               const mesh = new Mesh( geometry, material );
 
-       const currentMinFilter = texture.minFilter;
+               const currentMinFilter = texture.minFilter;
 
-       // Avoid blurred poles
-       if ( texture.minFilter === LinearMipmapLinearFilter ) texture.minFilter = LinearFilter;
+               // Avoid blurred poles
+               if ( texture.minFilter === LinearMipmapLinearFilter ) texture.minFilter = LinearFilter;
 
-       const camera = new CubeCamera( 1, 10, this );
-       camera.update( renderer, mesh );
+               const camera = new CubeCamera( 1, 10, this );
+               camera.update( renderer, mesh );
 
-       texture.minFilter = currentMinFilter;
+               texture.minFilter = currentMinFilter;
 
-       mesh.geometry.dispose();
-       mesh.material.dispose();
+               mesh.geometry.dispose();
+               mesh.material.dispose();
 
-       return this;
+               return this;
 
-};
+       }
 
-WebGLCubeRenderTarget.prototype.clear = function ( renderer, color, depth, stencil ) {
+       clear( renderer, color, depth, stencil ) {
 
-       const currentRenderTarget = renderer.getRenderTarget();
+               const currentRenderTarget = renderer.getRenderTarget();
 
-       for ( let i = 0; i < 6; i ++ ) {
+               for ( let i = 0; i < 6; i ++ ) {
 
-               renderer.setRenderTarget( this, i );
+                       renderer.setRenderTarget( this, i );
 
-               renderer.clear( color, depth, stencil );
+                       renderer.clear( color, depth, stencil );
 
-       }
+               }
 
-       renderer.setRenderTarget( currentRenderTarget );
+               renderer.setRenderTarget( currentRenderTarget );
 
-};
+       }
+
+}
 
 function DataTexture( data, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding ) {
 
@@ -12898,12 +12524,12 @@ function WebGLAttributes( gl, capabilities ) {
 
 }
 
-class PlaneBufferGeometry extends BufferGeometry {
+class PlaneGeometry extends BufferGeometry {
 
        constructor( width = 1, height = 1, widthSegments = 1, heightSegments = 1 ) {
 
                super();
-               this.type = 'PlaneBufferGeometry';
+               this.type = 'PlaneGeometry';
 
                this.parameters = {
                        width: width,
@@ -13932,7 +13558,7 @@ function WebGLBackground( renderer, cubemaps, state, objects, premultipliedAlpha
                        if ( boxMesh === undefined ) {
 
                                boxMesh = new Mesh(
-                                       new BoxBufferGeometry( 1, 1, 1 ),
+                                       new BoxGeometry( 1, 1, 1 ),
                                        new ShaderMaterial( {
                                                name: 'BackgroundCubeMaterial',
                                                uniforms: cloneUniforms( ShaderLib.cube.uniforms ),
@@ -14000,7 +13626,7 @@ function WebGLBackground( renderer, cubemaps, state, objects, premultipliedAlpha
                        if ( planeMesh === undefined ) {
 
                                planeMesh = new Mesh(
-                                       new PlaneBufferGeometry( 2, 2 ),
+                                       new PlaneGeometry( 2, 2 ),
                                        new ShaderMaterial( {
                                                name: 'BackgroundMaterial',
                                                uniforms: cloneUniforms( ShaderLib.background.uniforms ),
@@ -15062,7 +14688,6 @@ function WebGLCubeMaps( renderer ) {
 
                                                const currentRenderList = renderer.getRenderList();
                                                const currentRenderTarget = renderer.getRenderTarget();
-                                               const currentRenderState = renderer.getRenderState();
 
                                                const renderTarget = new WebGLCubeRenderTarget( image.height / 2 );
                                                renderTarget.fromEquirectangularTexture( renderer, texture );
@@ -15070,7 +14695,6 @@ function WebGLCubeMaps( renderer ) {
 
                                                renderer.setRenderTarget( currentRenderTarget );
                                                renderer.setRenderList( currentRenderList );
-                                               renderer.setRenderState( currentRenderState );
 
                                                texture.addEventListener( 'dispose', onTextureDispose );
 
@@ -15128,56 +14752,88 @@ function WebGLExtensions( gl ) {
 
        const extensions = {};
 
-       return {
+       function getExtension( name ) {
 
-               has: function ( name ) {
+               if ( extensions[ name ] !== undefined ) {
 
-                       if ( extensions[ name ] !== undefined ) {
+                       return extensions[ name ];
 
-                               return extensions[ name ] !== null;
+               }
 
-                       }
+               let extension;
 
-                       let extension;
+               switch ( name ) {
 
-                       switch ( name ) {
+                       case 'WEBGL_depth_texture':
+                               extension = gl.getExtension( 'WEBGL_depth_texture' ) || gl.getExtension( 'MOZ_WEBGL_depth_texture' ) || gl.getExtension( 'WEBKIT_WEBGL_depth_texture' );
+                               break;
 
-                               case 'WEBGL_depth_texture':
-                                       extension = gl.getExtension( 'WEBGL_depth_texture' ) || gl.getExtension( 'MOZ_WEBGL_depth_texture' ) || gl.getExtension( 'WEBKIT_WEBGL_depth_texture' );
-                                       break;
+                       case 'EXT_texture_filter_anisotropic':
+                               extension = gl.getExtension( 'EXT_texture_filter_anisotropic' ) || gl.getExtension( 'MOZ_EXT_texture_filter_anisotropic' ) || gl.getExtension( 'WEBKIT_EXT_texture_filter_anisotropic' );
+                               break;
 
-                               case 'EXT_texture_filter_anisotropic':
-                                       extension = gl.getExtension( 'EXT_texture_filter_anisotropic' ) || gl.getExtension( 'MOZ_EXT_texture_filter_anisotropic' ) || gl.getExtension( 'WEBKIT_EXT_texture_filter_anisotropic' );
-                                       break;
+                       case 'WEBGL_compressed_texture_s3tc':
+                               extension = gl.getExtension( 'WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'MOZ_WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_s3tc' );
+                               break;
 
-                               case 'WEBGL_compressed_texture_s3tc':
-                                       extension = gl.getExtension( 'WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'MOZ_WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_s3tc' );
-                                       break;
+                       case 'WEBGL_compressed_texture_pvrtc':
+                               extension = gl.getExtension( 'WEBGL_compressed_texture_pvrtc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_pvrtc' );
+                               break;
 
-                               case 'WEBGL_compressed_texture_pvrtc':
-                                       extension = gl.getExtension( 'WEBGL_compressed_texture_pvrtc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_pvrtc' );
-                                       break;
+                       default:
+                               extension = gl.getExtension( name );
 
-                               default:
-                                       extension = gl.getExtension( name );
+               }
 
-                       }
+               extensions[ name ] = extension;
+
+               return extension;
+
+       }
+
+       return {
+
+               has: function ( name ) {
 
-                       extensions[ name ] = extension;
+                       return getExtension( name ) !== null;
 
-                       return extension !== null;
+               },
+
+               init: function ( capabilities ) {
+
+                       if ( capabilities.isWebGL2 ) {
+
+                               getExtension( 'EXT_color_buffer_float' );
+
+                       } else {
+
+                               getExtension( 'WEBGL_depth_texture' );
+                               getExtension( 'OES_texture_float' );
+                               getExtension( 'OES_texture_half_float' );
+                               getExtension( 'OES_texture_half_float_linear' );
+                               getExtension( 'OES_standard_derivatives' );
+                               getExtension( 'OES_element_index_uint' );
+                               getExtension( 'OES_vertex_array_object' );
+                               getExtension( 'ANGLE_instanced_arrays' );
+
+                       }
+
+                       getExtension( 'OES_texture_float_linear' );
+                       getExtension( 'EXT_color_buffer_half_float' );
 
                },
 
                get: function ( name ) {
 
-                       if ( ! this.has( name ) ) {
+                       const extension = getExtension( name );
+
+                       if ( extension === null ) {
 
                                console.warn( 'THREE.WebGLRenderer: ' + name + ' extension not supported.' );
 
                        }
 
-                       return extensions[ name ];
+                       return extension;
 
                }
 
@@ -15187,40 +14843,39 @@ function WebGLExtensions( gl ) {
 
 function WebGLGeometries( gl, attributes, info, bindingStates ) {
 
-       const geometries = new WeakMap();
+       const geometries = {};
        const wireframeAttributes = new WeakMap();
 
        function onGeometryDispose( event ) {
 
                const geometry = event.target;
-               const buffergeometry = geometries.get( geometry );
 
-               if ( buffergeometry.index !== null ) {
+               if ( geometry.index !== null ) {
 
-                       attributes.remove( buffergeometry.index );
+                       attributes.remove( geometry.index );
 
                }
 
-               for ( const name in buffergeometry.attributes ) {
+               for ( const name in geometry.attributes ) {
 
-                       attributes.remove( buffergeometry.attributes[ name ] );
+                       attributes.remove( geometry.attributes[ name ] );
 
                }
 
                geometry.removeEventListener( 'dispose', onGeometryDispose );
 
-               geometries.delete( geometry );
+               delete geometries[ geometry.id ];
 
-               const attribute = wireframeAttributes.get( buffergeometry );
+               const attribute = wireframeAttributes.get( geometry );
 
                if ( attribute ) {
 
                        attributes.remove( attribute );
-                       wireframeAttributes.delete( buffergeometry );
+                       wireframeAttributes.delete( geometry );
 
                }
 
-               bindingStates.releaseStatesOfGeometry( buffergeometry );
+               bindingStates.releaseStatesOfGeometry( geometry );
 
                if ( geometry.isInstancedBufferGeometry === true ) {
 
@@ -15236,33 +14891,15 @@ function WebGLGeometries( gl, attributes, info, bindingStates ) {
 
        function get( object, geometry ) {
 
-               let buffergeometry = geometries.get( geometry );
-
-               if ( buffergeometry ) return buffergeometry;
+               if ( geometries[ geometry.id ] === true ) return geometry;
 
                geometry.addEventListener( 'dispose', onGeometryDispose );
 
-               if ( geometry.isBufferGeometry ) {
-
-                       buffergeometry = geometry;
-
-               } else if ( geometry.isGeometry ) {
-
-                       if ( geometry._bufferGeometry === undefined ) {
-
-                               geometry._bufferGeometry = new BufferGeometry().setFromObject( object );
-
-                       }
-
-                       buffergeometry = geometry._bufferGeometry;
-
-               }
-
-               geometries.set( geometry, buffergeometry );
+               geometries[ geometry.id ] = true;
 
                info.memory.geometries ++;
 
-               return buffergeometry;
+               return geometry;
 
        }
 
@@ -15697,12 +15334,6 @@ function WebGLObjects( gl, geometries, attributes, info ) {
 
                if ( updateMap.get( buffergeometry ) !== frame ) {
 
-                       if ( geometry.isGeometry ) {
-
-                               buffergeometry.updateFromObject( object );
-
-                       }
-
                        geometries.update( buffergeometry );
 
                        updateMap.set( buffergeometry, frame );
@@ -15711,6 +15342,12 @@ function WebGLObjects( gl, geometries, attributes, info ) {
 
                if ( object.isInstancedMesh ) {
 
+                       if ( object.hasEventListener( 'dispose', onInstancedMeshDispose ) === false ) {
+
+                               object.addEventListener( 'dispose', onInstancedMeshDispose );
+
+                       }
+
                        attributes.update( object.instanceMatrix, 34962 );
 
                        if ( object.instanceColor !== null ) {
@@ -15731,6 +15368,18 @@ function WebGLObjects( gl, geometries, attributes, info ) {
 
        }
 
+       function onInstancedMeshDispose( event ) {
+
+               const instancedMesh = event.target;
+
+               instancedMesh.removeEventListener( 'dispose', onInstancedMeshDispose );
+
+               attributes.remove( instancedMesh.instanceMatrix );
+
+               if ( instancedMesh.instanceColor !== null ) attributes.remove( instancedMesh.instanceColor );
+
+       }
+
        return {
 
                update: update,
@@ -16539,7 +16188,7 @@ StructuredUniform.prototype.setValue = function ( gl, value, textures ) {
 
 // Parser - builds up the property tree from the path strings
 
-const RePathPart = /([\w\d_]+)(\])?(\[|\.)?/g;
+const RePathPart = /(\w+)(\])?(\[|\.)?/g;
 
 // extracts
 //     - the identifier (member name or array index)
@@ -16945,19 +16594,19 @@ function loopReplacer( match, start, end, snippet ) {
 
 function generatePrecision( parameters ) {
 
-       let precisionstring = "precision " + parameters.precision + " float;\nprecision " + parameters.precision + " int;";
+       let precisionstring = 'precision ' + parameters.precision + ' float;\nprecision ' + parameters.precision + ' int;';
 
-       if ( parameters.precision === "highp" ) {
+       if ( parameters.precision === 'highp' ) {
 
-               precisionstring += "\n#define HIGH_PRECISION";
+               precisionstring += '\n#define HIGH_PRECISION';
 
-       } else if ( parameters.precision === "mediump" ) {
+       } else if ( parameters.precision === 'mediump' ) {
 
-               precisionstring += "\n#define MEDIUM_PRECISION";
+               precisionstring += '\n#define MEDIUM_PRECISION';
 
-       } else if ( parameters.precision === "lowp" ) {
+       } else if ( parameters.precision === 'lowp' ) {
 
-               precisionstring += "\n#define LOW_PRECISION";
+               precisionstring += '\n#define LOW_PRECISION';
 
        }
 
@@ -17087,7 +16736,7 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) {
        const program = gl.createProgram();
 
        let prefixVertex, prefixFragment;
-       let versionString = parameters.glslVersion ? '#version ' + parameters.glslVersion + "\n" : '';
+       let versionString = parameters.glslVersion ? '#version ' + parameters.glslVersion + '\n' : '';
 
        if ( parameters.isRawShaderMaterial ) {
 
@@ -17566,19 +17215,19 @@ function WebGLPrograms( renderer, cubemaps, extensions, capabilities, bindingSta
        };
 
        const parameterNames = [
-               "precision", "isWebGL2", "supportsVertexTextures", "outputEncoding", "instancing", "instancingColor",
-               "map", "mapEncoding", "matcap", "matcapEncoding", "envMap", "envMapMode", "envMapEncoding", "envMapCubeUV",
-               "lightMap", "lightMapEncoding", "aoMap", "emissiveMap", "emissiveMapEncoding", "bumpMap", "normalMap", "objectSpaceNormalMap", "tangentSpaceNormalMap", "clearcoatMap", "clearcoatRoughnessMap", "clearcoatNormalMap", "displacementMap", "specularMap",
-               "roughnessMap", "metalnessMap", "gradientMap",
-               "alphaMap", "combine", "vertexColors", "vertexTangents", "vertexUvs", "uvsVertexOnly", "fog", "useFog", "fogExp2",
-               "flatShading", "sizeAttenuation", "logarithmicDepthBuffer", "skinning",
-               "maxBones", "useVertexTexture", "morphTargets", "morphNormals",
-               "maxMorphTargets", "maxMorphNormals", "premultipliedAlpha",
-               "numDirLights", "numPointLights", "numSpotLights", "numHemiLights", "numRectAreaLights",
-               "numDirLightShadows", "numPointLightShadows", "numSpotLightShadows",
-               "shadowMapEnabled", "shadowMapType", "toneMapping", 'physicallyCorrectLights',
-               "alphaTest", "doubleSided", "flipSided", "numClippingPlanes", "numClipIntersection", "depthPacking", "dithering",
-               "sheen", "transmissionMap"
+               'precision', 'isWebGL2', 'supportsVertexTextures', 'outputEncoding', 'instancing', 'instancingColor',
+               'map', 'mapEncoding', 'matcap', 'matcapEncoding', 'envMap', 'envMapMode', 'envMapEncoding', 'envMapCubeUV',
+               'lightMap', 'lightMapEncoding', 'aoMap', 'emissiveMap', 'emissiveMapEncoding', 'bumpMap', 'normalMap', 'objectSpaceNormalMap', 'tangentSpaceNormalMap', 'clearcoatMap', 'clearcoatRoughnessMap', 'clearcoatNormalMap', 'displacementMap', 'specularMap',
+               'roughnessMap', 'metalnessMap', 'gradientMap',
+               'alphaMap', 'combine', 'vertexColors', 'vertexTangents', 'vertexUvs', 'uvsVertexOnly', 'fog', 'useFog', 'fogExp2',
+               'flatShading', 'sizeAttenuation', 'logarithmicDepthBuffer', 'skinning',
+               'maxBones', 'useVertexTexture', 'morphTargets', 'morphNormals',
+               'maxMorphTargets', 'maxMorphNormals', 'premultipliedAlpha',
+               'numDirLights', 'numPointLights', 'numSpotLights', 'numHemiLights', 'numRectAreaLights',
+               'numDirLightShadows', 'numPointLightShadows', 'numSpotLightShadows',
+               'shadowMapEnabled', 'shadowMapType', 'toneMapping', 'physicallyCorrectLights',
+               'alphaTest', 'doubleSided', 'flipSided', 'numClippingPlanes', 'numClipIntersection', 'depthPacking', 'dithering',
+               'sheen', 'transmissionMap'
        ];
 
        function getMaxBones( object ) {
@@ -17621,19 +17270,19 @@ function WebGLPrograms( renderer, cubemaps, extensions, capabilities, bindingSta
 
                let encoding;
 
-               if ( ! map ) {
-
-                       encoding = LinearEncoding;
-
-               } else if ( map.isTexture ) {
+               if ( map && map.isTexture ) {
 
                        encoding = map.encoding;
 
-               } else if ( map.isWebGLRenderTarget ) {
+               } else if ( map && map.isWebGLRenderTarget ) {
 
-                       console.warn( "THREE.WebGLPrograms.getTextureEncodingFromMap: don't use render targets as textures. Use their .texture property instead." );
+                       console.warn( 'THREE.WebGLPrograms.getTextureEncodingFromMap: don\'t use render targets as textures. Use their .texture property instead.' );
                        encoding = map.texture.encoding;
 
+               } else {
+
+                       encoding = LinearEncoding;
+
                }
 
                return encoding;
@@ -18391,7 +18040,7 @@ function WebGLLights( extensions, capabilities ) {
        const matrix4 = new Matrix4();
        const matrix42 = new Matrix4();
 
-       function setup( lights, shadows, camera ) {
+       function setup( lights ) {
 
                let r = 0, g = 0, b = 0;
 
@@ -18407,8 +18056,6 @@ function WebGLLights( extensions, capabilities ) {
                let numPointShadows = 0;
                let numSpotShadows = 0;
 
-               const viewMatrix = camera.matrixWorldInverse;
-
                lights.sort( shadowCastingLightsFirst );
 
                for ( let i = 0, l = lights.length; i < l; i ++ ) {
@@ -18440,10 +18087,6 @@ function WebGLLights( extensions, capabilities ) {
                                const uniforms = cache.get( light );
 
                                uniforms.color.copy( light.color ).multiplyScalar( light.intensity );
-                               uniforms.direction.setFromMatrixPosition( light.matrixWorld );
-                               vector3.setFromMatrixPosition( light.target.matrixWorld );
-                               uniforms.direction.sub( vector3 );
-                               uniforms.direction.transformDirection( viewMatrix );
 
                                if ( light.castShadow ) {
 
@@ -18473,16 +18116,10 @@ function WebGLLights( extensions, capabilities ) {
                                const uniforms = cache.get( light );
 
                                uniforms.position.setFromMatrixPosition( light.matrixWorld );
-                               uniforms.position.applyMatrix4( viewMatrix );
 
                                uniforms.color.copy( color ).multiplyScalar( intensity );
                                uniforms.distance = distance;
 
-                               uniforms.direction.setFromMatrixPosition( light.matrixWorld );
-                               vector3.setFromMatrixPosition( light.target.matrixWorld );
-                               uniforms.direction.sub( vector3 );
-                               uniforms.direction.transformDirection( viewMatrix );
-
                                uniforms.coneCos = Math.cos( light.angle );
                                uniforms.penumbraCos = Math.cos( light.angle * ( 1 - light.penumbra ) );
                                uniforms.decay = light.decay;
@@ -18520,24 +18157,9 @@ function WebGLLights( extensions, capabilities ) {
                                // (b) intensity is the brightness of the light
                                uniforms.color.copy( color ).multiplyScalar( intensity );
 
-                               uniforms.position.setFromMatrixPosition( light.matrixWorld );
-                               uniforms.position.applyMatrix4( viewMatrix );
-
-                               // extract local rotation of light to derive width/height half vectors
-                               matrix42.identity();
-                               matrix4.copy( light.matrixWorld );
-                               matrix4.premultiply( viewMatrix );
-                               matrix42.extractRotation( matrix4 );
-
                                uniforms.halfWidth.set( light.width * 0.5, 0.0, 0.0 );
                                uniforms.halfHeight.set( 0.0, light.height * 0.5, 0.0 );
 
-                               uniforms.halfWidth.applyMatrix4( matrix42 );
-                               uniforms.halfHeight.applyMatrix4( matrix42 );
-
-                               // TODO (abelnation): RectAreaLight distance?
-                               // uniforms.distance = distance;
-
                                state.rectArea[ rectAreaLength ] = uniforms;
 
                                rectAreaLength ++;
@@ -18546,9 +18168,6 @@ function WebGLLights( extensions, capabilities ) {
 
                                const uniforms = cache.get( light );
 
-                               uniforms.position.setFromMatrixPosition( light.matrixWorld );
-                               uniforms.position.applyMatrix4( viewMatrix );
-
                                uniforms.color.copy( light.color ).multiplyScalar( light.intensity );
                                uniforms.distance = light.distance;
                                uniforms.decay = light.decay;
@@ -18582,10 +18201,6 @@ function WebGLLights( extensions, capabilities ) {
 
                                const uniforms = cache.get( light );
 
-                               uniforms.direction.setFromMatrixPosition( light.matrixWorld );
-                               uniforms.direction.transformDirection( viewMatrix );
-                               uniforms.direction.normalize();
-
                                uniforms.skyColor.copy( light.color ).multiplyScalar( intensity );
                                uniforms.groundColor.copy( light.groundColor ).multiplyScalar( intensity );
 
@@ -18677,8 +18292,94 @@ function WebGLLights( extensions, capabilities ) {
 
        }
 
+       function setupView( lights, camera ) {
+
+               let directionalLength = 0;
+               let pointLength = 0;
+               let spotLength = 0;
+               let rectAreaLength = 0;
+               let hemiLength = 0;
+
+               const viewMatrix = camera.matrixWorldInverse;
+
+               for ( let i = 0, l = lights.length; i < l; i ++ ) {
+
+                       const light = lights[ i ];
+
+                       if ( light.isDirectionalLight ) {
+
+                               const uniforms = state.directional[ directionalLength ];
+
+                               uniforms.direction.setFromMatrixPosition( light.matrixWorld );
+                               vector3.setFromMatrixPosition( light.target.matrixWorld );
+                               uniforms.direction.sub( vector3 );
+                               uniforms.direction.transformDirection( viewMatrix );
+
+                               directionalLength ++;
+
+                       } else if ( light.isSpotLight ) {
+
+                               const uniforms = state.spot[ spotLength ];
+
+                               uniforms.position.setFromMatrixPosition( light.matrixWorld );
+                               uniforms.position.applyMatrix4( viewMatrix );
+
+                               uniforms.direction.setFromMatrixPosition( light.matrixWorld );
+                               vector3.setFromMatrixPosition( light.target.matrixWorld );
+                               uniforms.direction.sub( vector3 );
+                               uniforms.direction.transformDirection( viewMatrix );
+
+                               spotLength ++;
+
+                       } else if ( light.isRectAreaLight ) {
+
+                               const uniforms = state.rectArea[ rectAreaLength ];
+
+                               uniforms.position.setFromMatrixPosition( light.matrixWorld );
+                               uniforms.position.applyMatrix4( viewMatrix );
+
+                               // extract local rotation of light to derive width/height half vectors
+                               matrix42.identity();
+                               matrix4.copy( light.matrixWorld );
+                               matrix4.premultiply( viewMatrix );
+                               matrix42.extractRotation( matrix4 );
+
+                               uniforms.halfWidth.set( light.width * 0.5, 0.0, 0.0 );
+                               uniforms.halfHeight.set( 0.0, light.height * 0.5, 0.0 );
+
+                               uniforms.halfWidth.applyMatrix4( matrix42 );
+                               uniforms.halfHeight.applyMatrix4( matrix42 );
+
+                               rectAreaLength ++;
+
+                       } else if ( light.isPointLight ) {
+
+                               const uniforms = state.point[ pointLength ];
+
+                               uniforms.position.setFromMatrixPosition( light.matrixWorld );
+                               uniforms.position.applyMatrix4( viewMatrix );
+
+                               pointLength ++;
+
+                       } else if ( light.isHemisphereLight ) {
+
+                               const uniforms = state.hemi[ hemiLength ];
+
+                               uniforms.direction.setFromMatrixPosition( light.matrixWorld );
+                               uniforms.direction.transformDirection( viewMatrix );
+                               uniforms.direction.normalize();
+
+                               hemiLength ++;
+
+                       }
+
+               }
+
+       }
+
        return {
                setup: setup,
+               setupView: setupView,
                state: state
        };
 
@@ -18710,9 +18411,15 @@ function WebGLRenderState( extensions, capabilities ) {
 
        }
 
-       function setupLights( camera ) {
+       function setupLights() {
 
-               lights.setup( lightsArray, shadowsArray, camera );
+               lights.setup( lightsArray );
+
+       }
+
+       function setupLightsView( camera ) {
+
+               lights.setupView( lightsArray, camera );
 
        }
 
@@ -18727,6 +18434,7 @@ function WebGLRenderState( extensions, capabilities ) {
                init: init,
                state: state,
                setupLights: setupLights,
+               setupLightsView: setupLightsView,
 
                pushLight: pushLight,
                pushShadow: pushShadow
@@ -18738,26 +18446,26 @@ function WebGLRenderStates( extensions, capabilities ) {
 
        let renderStates = new WeakMap();
 
-       function get( scene, camera ) {
+       function get( scene, renderCallDepth = 0 ) {
 
                let renderState;
 
                if ( renderStates.has( scene ) === false ) {
 
                        renderState = new WebGLRenderState( extensions, capabilities );
-                       renderStates.set( scene, new WeakMap() );
-                       renderStates.get( scene ).set( camera, renderState );
+                       renderStates.set( scene, [] );
+                       renderStates.get( scene ).push( renderState );
 
                } else {
 
-                       if ( renderStates.get( scene ).has( camera ) === false ) {
+                       if ( renderCallDepth >= renderStates.get( scene ).length ) {
 
                                renderState = new WebGLRenderState( extensions, capabilities );
-                               renderStates.get( scene ).set( camera, renderState );
+                               renderStates.get( scene ).push( renderState );
 
                        } else {
 
-                               renderState = renderStates.get( scene ).get( camera );
+                               renderState = renderStates.get( scene )[ renderCallDepth ];
 
                        }
 
@@ -18931,7 +18639,7 @@ MeshDistanceMaterial.prototype.copy = function ( source ) {
 
 };
 
-var vsm_frag = "uniform sampler2D shadow_pass;\nuniform vec2 resolution;\nuniform float radius;\n#include <packing>\nvoid main() {\n\tfloat mean = 0.0;\n\tfloat squared_mean = 0.0;\n\tfloat depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy ) / resolution ) );\n\tfor ( float i = -1.0; i < 1.0 ; i += SAMPLE_RATE) {\n\t\t#ifdef HORIZONAL_PASS\n\t\t\tvec2 distribution = unpackRGBATo2Half( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( i, 0.0 ) * radius ) / resolution ) );\n\t\t\tmean += distribution.x;\n\t\t\tsquared_mean += distribution.y * distribution.y + distribution.x * distribution.x;\n\t\t#else\n\t\t\tfloat depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( 0.0, i ) * radius ) / resolution ) );\n\t\t\tmean += depth;\n\t\t\tsquared_mean += depth * depth;\n\t\t#endif\n\t}\n\tmean = mean * HALF_SAMPLE_RATE;\n\tsquared_mean = squared_mean * HALF_SAMPLE_RATE;\n\tfloat std_dev = sqrt( squared_mean - mean * mean );\n\tgl_FragColor = pack2HalfToRGBA( vec2( mean, std_dev ) );\n}";
+var vsm_frag = "uniform sampler2D shadow_pass;\nuniform vec2 resolution;\nuniform float radius;\n#include <packing>\nvoid main() {\n\tfloat mean = 0.0;\n\tfloat squared_mean = 0.0;\n\tfloat depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy ) / resolution ) );\n\tfor ( float i = -1.0; i < 1.0 ; i += SAMPLE_RATE) {\n\t\t#ifdef HORIZONTAL_PASS\n\t\t\tvec2 distribution = unpackRGBATo2Half( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( i, 0.0 ) * radius ) / resolution ) );\n\t\t\tmean += distribution.x;\n\t\t\tsquared_mean += distribution.y * distribution.y + distribution.x * distribution.x;\n\t\t#else\n\t\t\tfloat depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( 0.0, i ) * radius ) / resolution ) );\n\t\t\tmean += depth;\n\t\t\tsquared_mean += depth * depth;\n\t\t#endif\n\t}\n\tmean = mean * HALF_SAMPLE_RATE;\n\tsquared_mean = squared_mean * HALF_SAMPLE_RATE;\n\tfloat std_dev = sqrt( squared_mean - mean * mean );\n\tgl_FragColor = pack2HalfToRGBA( vec2( mean, std_dev ) );\n}";
 
 var vsm_vert = "void main() {\n\tgl_Position = vec4( position, 1.0 );\n}";
 
@@ -18970,12 +18678,12 @@ function WebGLShadowMap( _renderer, _objects, maxTextureSize ) {
 
        } );
 
-       const shadowMaterialHorizonal = shadowMaterialVertical.clone();
-       shadowMaterialHorizonal.defines.HORIZONAL_PASS = 1;
+       const shadowMaterialHorizontal = shadowMaterialVertical.clone();
+       shadowMaterialHorizontal.defines.HORIZONTAL_PASS = 1;
 
        const fullScreenTri = new BufferGeometry();
        fullScreenTri.setAttribute(
-               "position",
+               'position',
                new BufferAttribute(
                        new Float32Array( [ - 1, - 1, 0.5, 3, - 1, 0.5, - 1, 3, 0.5 ] ),
                        3
@@ -19061,7 +18769,7 @@ function WebGLShadowMap( _renderer, _objects, maxTextureSize ) {
                                const pars = { minFilter: LinearFilter, magFilter: LinearFilter, format: RGBAFormat };
 
                                shadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars );
-                               shadow.map.texture.name = light.name + ".shadowMap";
+                               shadow.map.texture.name = light.name + '.shadowMap';
 
                                shadow.mapPass = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars );
 
@@ -19074,7 +18782,7 @@ function WebGLShadowMap( _renderer, _objects, maxTextureSize ) {
                                const pars = { minFilter: NearestFilter, magFilter: NearestFilter, format: RGBAFormat };
 
                                shadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars );
-                               shadow.map.texture.name = light.name + ".shadowMap";
+                               shadow.map.texture.name = light.name + '.shadowMap';
 
                                shadow.camera.updateProjectionMatrix();
 
@@ -19137,14 +18845,14 @@ function WebGLShadowMap( _renderer, _objects, maxTextureSize ) {
                _renderer.clear();
                _renderer.renderBufferDirect( camera, null, geometry, shadowMaterialVertical, fullScreenMesh, null );
 
-               // horizonal pass
+               // horizontal pass
 
-               shadowMaterialHorizonal.uniforms.shadow_pass.value = shadow.mapPass.texture;
-               shadowMaterialHorizonal.uniforms.resolution.value = shadow.mapSize;
-               shadowMaterialHorizonal.uniforms.radius.value = shadow.radius;
+               shadowMaterialHorizontal.uniforms.shadow_pass.value = shadow.mapPass.texture;
+               shadowMaterialHorizontal.uniforms.resolution.value = shadow.mapSize;
+               shadowMaterialHorizontal.uniforms.radius.value = shadow.radius;
                _renderer.setRenderTarget( shadow.map );
                _renderer.clear();
-               _renderer.renderBufferDirect( camera, null, geometry, shadowMaterialHorizonal, fullScreenMesh, null );
+               _renderer.renderBufferDirect( camera, null, geometry, shadowMaterialHorizontal, fullScreenMesh, null );
 
        }
 
@@ -19710,12 +19418,12 @@ function WebGLState( gl, extensions, capabilities ) {
 
        if ( glVersion.indexOf( 'WebGL' ) !== - 1 ) {
 
-               version = parseFloat( /^WebGL\ ([0-9])/.exec( glVersion )[ 1 ] );
+               version = parseFloat( /^WebGL (\d)/.exec( glVersion )[ 1 ] );
                lineWidthAvailable = ( version >= 1.0 );
 
        } else if ( glVersion.indexOf( 'OpenGL ES' ) !== - 1 ) {
 
-               version = parseFloat( /^OpenGL\ ES\ ([0-9])/.exec( glVersion )[ 1 ] );
+               version = parseFloat( /^OpenGL ES (\d)/.exec( glVersion )[ 1 ] );
                lineWidthAvailable = ( version >= 2.0 );
 
        }
@@ -20334,7 +20042,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
        try {
 
                useOffscreenCanvas = typeof OffscreenCanvas !== 'undefined'
-                       && ( new OffscreenCanvas( 1, 1 ).getContext( "2d" ) ) !== null;
+                       && ( new OffscreenCanvas( 1, 1 ).getContext( '2d' ) ) !== null;
 
        } catch ( err ) {
 
@@ -21022,6 +20730,8 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
                state.bindTexture( 34067, textureProperties.__webglTexture );
 
                _gl.pixelStorei( 37440, texture.flipY );
+               _gl.pixelStorei( 37441, texture.premultiplyAlpha );
+               _gl.pixelStorei( 3317, texture.unpackAlignment );
 
                const isCompressed = ( texture && ( texture.isCompressedTexture || texture.image[ 0 ].isCompressedTexture ) );
                const isDataTexture = ( texture.image[ 0 ] && texture.image[ 0 ].isDataTexture );
@@ -21530,7 +21240,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
 
                        if ( warnedTexture2D === false ) {
 
-                               console.warn( "THREE.WebGLTextures.safeSetTexture2D: don't use render targets as textures. Use their .texture property instead." );
+                               console.warn( 'THREE.WebGLTextures.safeSetTexture2D: don\'t use render targets as textures. Use their .texture property instead.' );
                                warnedTexture2D = true;
 
                        }
@@ -21549,7 +21259,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
 
                        if ( warnedTextureCube === false ) {
 
-                               console.warn( "THREE.WebGLTextures.safeSetTextureCube: don't use cube render targets as textures. Use their .texture property instead." );
+                               console.warn( 'THREE.WebGLTextures.safeSetTextureCube: don\'t use cube render targets as textures. Use their .texture property instead.' );
                                warnedTextureCube = true;
 
                        }
@@ -21826,25 +21536,9 @@ Object.assign( WebXRController.prototype, {
                        this._hand.matrixAutoUpdate = false;
                        this._hand.visible = false;
 
-                       this._hand.joints = [];
+                       this._hand.joints = {};
                        this._hand.inputState = { pinching: false };
 
-                       if ( window.XRHand ) {
-
-                               for ( let i = 0; i <= window.XRHand.LITTLE_PHALANX_TIP; i ++ ) {
-
-                                       // The transform of this joint will be updated with the joint pose on each frame
-                                       const joint = new Group();
-                                       joint.matrixAutoUpdate = false;
-                                       joint.visible = false;
-                                       this._hand.joints.push( joint );
-                                       // ??
-                                       this._hand.add( joint );
-
-                               }
-
-                       }
-
                }
 
                return this._hand;
@@ -21945,55 +21639,64 @@ Object.assign( WebXRController.prototype, {
 
                                handPose = true;
 
-                               for ( let i = 0; i <= window.XRHand.LITTLE_PHALANX_TIP; i ++ ) {
+                               for ( const inputjoint of inputSource.hand.values() ) {
+
+                                       // Update the joints groups with the XRJoint poses
+                                       const jointPose = frame.getJointPose( inputjoint, referenceSpace );
 
-                                       if ( inputSource.hand[ i ] ) {
+                                       if ( hand.joints[ inputjoint.jointName ] === undefined ) {
 
-                                               // Update the joints groups with the XRJoint poses
-                                               const jointPose = frame.getJointPose( inputSource.hand[ i ], referenceSpace );
-                                               const joint = hand.joints[ i ];
+                                               // The transform of this joint will be updated with the joint pose on each frame
+                                               const joint = new Group();
+                                               joint.matrixAutoUpdate = false;
+                                               joint.visible = false;
+                                               hand.joints[ inputjoint.jointName ] = joint;
+                                               // ??
+                                               hand.add( joint );
 
-                                               if ( jointPose !== null ) {
+                                       }
 
-                                                       joint.matrix.fromArray( jointPose.transform.matrix );
-                                                       joint.matrix.decompose( joint.position, joint.rotation, joint.scale );
-                                                       joint.jointRadius = jointPose.radius;
+                                       const joint = hand.joints[ inputjoint.jointName ];
 
-                                               }
+                                       if ( jointPose !== null ) {
+
+                                               joint.matrix.fromArray( jointPose.transform.matrix );
+                                               joint.matrix.decompose( joint.position, joint.rotation, joint.scale );
+                                               joint.jointRadius = jointPose.radius;
 
-                                               joint.visible = jointPose !== null;
+                                       }
 
-                                               // Custom events
+                                       joint.visible = jointPose !== null;
 
-                                               // Check pinch
-                                               const indexTip = hand.joints[ window.XRHand.INDEX_PHALANX_TIP ];
-                                               const thumbTip = hand.joints[ window.XRHand.THUMB_PHALANX_TIP ];
-                                               const distance = indexTip.position.distanceTo( thumbTip.position );
+                               }
 
-                                               const distanceToPinch = 0.02;
-                                               const threshold = 0.005;
+                               // Custom events
 
-                                               if ( hand.inputState.pinching && distance > distanceToPinch + threshold ) {
+                               // Check pinchz
+                               const indexTip = hand.joints[ 'index-finger-tip' ];
+                               const thumbTip = hand.joints[ 'thumb-tip' ];
+                               const distance = indexTip.position.distanceTo( thumbTip.position );
 
-                                                       hand.inputState.pinching = false;
-                                                       this.dispatchEvent( {
-                                                               type: "pinchend",
-                                                               handedness: inputSource.handedness,
-                                                               target: this
-                                                       } );
+                               const distanceToPinch = 0.02;
+                               const threshold = 0.005;
 
-                                               } else if ( ! hand.inputState.pinching && distance <= distanceToPinch - threshold ) {
+                               if ( hand.inputState.pinching && distance > distanceToPinch + threshold ) {
 
-                                                       hand.inputState.pinching = true;
-                                                       this.dispatchEvent( {
-                                                               type: "pinchstart",
-                                                               handedness: inputSource.handedness,
-                                                               target: this
-                                                       } );
+                                       hand.inputState.pinching = false;
+                                       this.dispatchEvent( {
+                                               type: 'pinchend',
+                                               handedness: inputSource.handedness,
+                                               target: this
+                                       } );
 
-                                               }
+                               } else if ( ! hand.inputState.pinching && distance <= distanceToPinch - threshold ) {
 
-                                       }
+                                       hand.inputState.pinching = true;
+                                       this.dispatchEvent( {
+                                               type: 'pinchstart',
+                                               handedness: inputSource.handedness,
+                                               target: this
+                                       } );
 
                                }
 
@@ -22163,6 +21866,9 @@ function WebXRManager( renderer, gl ) {
 
                inputSourcesMap.clear();
 
+               _currentDepthNear = null;
+               _currentDepthFar = null;
+
                //
 
                renderer.setFramebuffer( null );
@@ -22175,19 +21881,6 @@ function WebXRManager( renderer, gl ) {
 
        }
 
-       function onRequestReferenceSpace( value ) {
-
-               referenceSpace = value;
-
-               animation.setContext( session );
-               animation.start();
-
-               scope.isPresenting = true;
-
-               scope.dispatchEvent( { type: 'sessionstart' } );
-
-       }
-
        this.setFramebufferScaleFactor = function ( value ) {
 
                framebufferScaleFactor = value;
@@ -22224,7 +21917,7 @@ function WebXRManager( renderer, gl ) {
 
        };
 
-       this.setSession = function ( value ) {
+       this.setSession = async function ( value ) {
 
                session = value;
 
@@ -22237,12 +21930,13 @@ function WebXRManager( renderer, gl ) {
                        session.addEventListener( 'squeezestart', onSessionEvent );
                        session.addEventListener( 'squeezeend', onSessionEvent );
                        session.addEventListener( 'end', onSessionEnd );
+                       session.addEventListener( 'inputsourceschange', onInputSourcesChange );
 
                        const attributes = gl.getContextAttributes();
 
                        if ( attributes.xrCompatible !== true ) {
 
-                               gl.makeXRCompatible();
+                               await gl.makeXRCompatible();
 
                        }
 
@@ -22259,17 +21953,20 @@ function WebXRManager( renderer, gl ) {
 
                        session.updateRenderState( { baseLayer: baseLayer } );
 
-                       session.requestReferenceSpace( referenceSpaceType ).then( onRequestReferenceSpace );
+                       referenceSpace = await session.requestReferenceSpace( referenceSpaceType );
 
-                       //
+                       animation.setContext( session );
+                       animation.start();
 
-                       session.addEventListener( 'inputsourceschange', updateInputSources );
+                       scope.isPresenting = true;
+
+                       scope.dispatchEvent( { type: 'sessionstart' } );
 
                }
 
        };
 
-       function updateInputSources( event ) {
+       function onInputSourcesChange( event ) {
 
                const inputSources = session.inputSources;
 
@@ -22423,6 +22120,8 @@ function WebXRManager( renderer, gl ) {
                // update camera and its children
 
                camera.matrixWorld.copy( cameraVR.matrixWorld );
+               camera.matrix.copy( cameraVR.matrix );
+               camera.matrix.decompose( camera.position, camera.quaternion, camera.scale );
 
                const children = camera.children;
 
@@ -23256,6 +22955,11 @@ function WebGLRenderer( parameters ) {
        let currentRenderList = null;
        let currentRenderState = null;
 
+       // render() can be called from within a callback triggered by another render.
+       // We track this so that the nested render call gets its state isolated from the parent render call.
+
+       const renderStateStack = [];
+
        // public properties
 
        this.domElement = _canvas;
@@ -23322,7 +23026,6 @@ function WebGLRenderer( parameters ) {
        let _currentMaterialId = - 1;
 
        let _currentCamera = null;
-       let _currentArrayCamera = null;
 
        const _currentViewport = new Vector4();
        const _currentScissor = new Vector4();
@@ -23461,20 +23164,7 @@ function WebGLRenderer( parameters ) {
 
                capabilities = new WebGLCapabilities( _gl, extensions, parameters );
 
-               if ( capabilities.isWebGL2 === false ) {
-
-                       extensions.get( 'WEBGL_depth_texture' );
-                       extensions.get( 'OES_texture_float' );
-                       extensions.get( 'OES_texture_half_float' );
-                       extensions.get( 'OES_texture_half_float_linear' );
-                       extensions.get( 'OES_standard_derivatives' );
-                       extensions.get( 'OES_element_index_uint' );
-                       extensions.get( 'OES_vertex_array_object' );
-                       extensions.get( 'ANGLE_instanced_arrays' );
-
-               }
-
-               extensions.get( 'OES_texture_float_linear' );
+               extensions.init( capabilities );
 
                utils = new WebGLUtils( _gl, extensions, capabilities );
 
@@ -23722,9 +23412,17 @@ function WebGLRenderer( parameters ) {
 
        // Clearing
 
-       this.getClearColor = function () {
+       this.getClearColor = function ( target ) {
+
+               if ( target === undefined ) {
+
+                       console.warn( 'WebGLRenderer: .getClearColor() now requires a Color as an argument' );
+
+                       target = new Color();
+
+               }
 
-               return background.getClearColor();
+               return target.copy( background.getClearColor() );
 
        };
 
@@ -24068,7 +23766,7 @@ function WebGLRenderer( parameters ) {
 
        this.compile = function ( scene, camera ) {
 
-               currentRenderState = renderStates.get( scene, camera );
+               currentRenderState = renderStates.get( scene );
                currentRenderState.init();
 
                scene.traverseVisible( function ( object ) {
@@ -24087,7 +23785,7 @@ function WebGLRenderer( parameters ) {
 
                } );
 
-               currentRenderState.setupLights( camera );
+               currentRenderState.setupLights();
 
                const compiled = new WeakMap();
 
@@ -24202,9 +23900,11 @@ function WebGLRenderer( parameters ) {
                //
                if ( scene.isScene === true ) scene.onBeforeRender( _this, scene, camera, renderTarget || _currentRenderTarget );
 
-               currentRenderState = renderStates.get( scene, camera );
+               currentRenderState = renderStates.get( scene, renderStateStack.length );
                currentRenderState.init();
 
+               renderStateStack.push( currentRenderState );
+
                _projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
                _frustum.setFromProjectionMatrix( _projScreenMatrix );
 
@@ -24232,7 +23932,8 @@ function WebGLRenderer( parameters ) {
 
                shadowMap.render( shadowsArray, scene, camera );
 
-               currentRenderState.setupLights( camera );
+               currentRenderState.setupLights();
+               currentRenderState.setupLightsView( camera );
 
                if ( _clippingEnabled === true ) clipping.endShadows();
 
@@ -24286,8 +23987,18 @@ function WebGLRenderer( parameters ) {
 
                // _gl.finish();
 
+               renderStateStack.pop();
+               if ( renderStateStack.length > 0 ) {
+
+                       currentRenderState = renderStateStack[ renderStateStack.length - 1 ];
+
+               } else {
+
+                       currentRenderState = null;
+
+               }
+
                currentRenderList = null;
-               currentRenderState = null;
 
        };
 
@@ -24431,8 +24142,6 @@ function WebGLRenderer( parameters ) {
 
                        if ( camera.isArrayCamera ) {
 
-                               _currentArrayCamera = camera;
-
                                const cameras = camera.cameras;
 
                                for ( let j = 0, jl = cameras.length; j < jl; j ++ ) {
@@ -24443,7 +24152,7 @@ function WebGLRenderer( parameters ) {
 
                                                state.viewport( _currentViewport.copy( camera2.viewport ) );
 
-                                               currentRenderState.setupLights( camera2 );
+                                               currentRenderState.setupLightsView( camera2 );
 
                                                renderObject( object, scene, camera2, geometry, material, group );
 
@@ -24453,8 +24162,6 @@ function WebGLRenderer( parameters ) {
 
                        } else {
 
-                               _currentArrayCamera = null;
-
                                renderObject( object, scene, camera, geometry, material, group );
 
                        }
@@ -24466,7 +24173,6 @@ function WebGLRenderer( parameters ) {
        function renderObject( object, scene, camera, geometry, material, group ) {
 
                object.onBeforeRender( _this, scene, camera, geometry, material, group );
-               currentRenderState = renderStates.get( scene, _currentArrayCamera || camera );
 
                object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld );
                object.normalMatrix.getNormalMatrix( object.modelViewMatrix );
@@ -24488,7 +24194,6 @@ function WebGLRenderer( parameters ) {
                }
 
                object.onAfterRender( _this, scene, camera, geometry, material, group );
-               currentRenderState = renderStates.get( scene, _currentArrayCamera || camera );
 
        }
 
@@ -24509,6 +24214,12 @@ function WebGLRenderer( parameters ) {
                let program = materialProperties.program;
                let programChange = true;
 
+               // always update environment and fog - changing these trigger an initMaterial call, but it's possible that the program doesn't change
+
+               materialProperties.environment = material.isMeshStandardMaterial ? scene.environment : null;
+               materialProperties.fog = scene.fog;
+               materialProperties.envMap = cubemaps.get( material.envMap || materialProperties.environment );
+
                if ( program === undefined ) {
 
                        // new material
@@ -24525,11 +24236,7 @@ function WebGLRenderer( parameters ) {
 
                } else if ( parameters.shaderID !== undefined ) {
 
-                       // same glsl and uniform list, envMap still needs the update here to avoid a frame-late effect
-
-                       const environment = material.isMeshStandardMaterial ? scene.environment : null;
-                       materialProperties.envMap = cubemaps.get( material.envMap || environment );
-
+                       // same glsl and uniform list
                        return;
 
                } else {
@@ -24565,10 +24272,6 @@ function WebGLRenderer( parameters ) {
 
                }
 
-               materialProperties.environment = material.isMeshStandardMaterial ? scene.environment : null;
-               materialProperties.fog = scene.fog;
-               materialProperties.envMap = cubemaps.get( material.envMap || materialProperties.environment );
-
                // store the light setup it was created for
 
                materialProperties.needsLights = materialNeedsLights( material );
@@ -24947,18 +24650,6 @@ function WebGLRenderer( parameters ) {
 
        };
 
-       this.getRenderState = function () {
-
-               return currentRenderState;
-
-       };
-
-       this.setRenderState = function ( renderState ) {
-
-               currentRenderState = renderState;
-
-       };
-
        this.getRenderTarget = function () {
 
                return _currentRenderTarget;
@@ -25073,9 +24764,11 @@ function WebGLRenderer( parameters ) {
 
                                }
 
+                               const halfFloatSupportedByExt = ( textureType === HalfFloatType ) && ( extensions.has( 'EXT_color_buffer_half_float' ) || ( capabilities.isWebGL2 && extensions.has( 'EXT_color_buffer_float' ) ) );
+
                                if ( textureType !== UnsignedByteType && utils.convert( textureType ) !== _gl.getParameter( 35738 ) && // IE11, Edge and Chrome Mac < 52 (#9513)
-                                       ! ( textureType === FloatType && ( capabilities.isWebGL2 || extensions.get( 'OES_texture_float' ) || extensions.get( 'WEBGL_color_buffer_float' ) ) ) && // Chrome Mac >= 52 and Firefox
-                                       ! ( textureType === HalfFloatType && ( capabilities.isWebGL2 ? extensions.get( 'EXT_color_buffer_float' ) : extensions.get( 'EXT_color_buffer_half_float' ) ) ) ) {
+                                       ! ( textureType === FloatType && ( capabilities.isWebGL2 || extensions.has( 'OES_texture_float' ) || extensions.has( 'WEBGL_color_buffer_float' ) ) ) && // Chrome Mac >= 52 and Firefox
+                                       ! halfFloatSupportedByExt ) {
 
                                        console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.' );
                                        return;
@@ -25175,6 +24868,13 @@ function WebGLRenderer( parameters ) {
 
        };
 
+       this.resetState = function () {
+
+               state.reset();
+               bindingStates.reset();
+
+       };
+
        if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) {
 
                __THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'observe', { detail: this } ) ); // eslint-disable-line no-undef
@@ -26144,6 +25844,14 @@ LOD.prototype = Object.assign( Object.create( Object3D.prototype ), {
 
 } );
 
+const _basePosition = new Vector3();
+
+const _skinIndex = new Vector4();
+const _skinWeight = new Vector4();
+
+const _vector$7 = new Vector3();
+const _matrix$1 = new Matrix4();
+
 function SkinnedMesh( geometry, material ) {
 
        if ( geometry && geometry.isGeometry ) {
@@ -26258,49 +25966,37 @@ SkinnedMesh.prototype = Object.assign( Object.create( Mesh.prototype ), {
 
        },
 
-       boneTransform: ( function () {
-
-               const basePosition = new Vector3();
+       boneTransform: function ( index, target ) {
 
-               const skinIndex = new Vector4();
-               const skinWeight = new Vector4();
-
-               const vector = new Vector3();
-               const matrix = new Matrix4();
-
-               return function ( index, target ) {
-
-                       const skeleton = this.skeleton;
-                       const geometry = this.geometry;
-
-                       skinIndex.fromBufferAttribute( geometry.attributes.skinIndex, index );
-                       skinWeight.fromBufferAttribute( geometry.attributes.skinWeight, index );
+               const skeleton = this.skeleton;
+               const geometry = this.geometry;
 
-                       basePosition.fromBufferAttribute( geometry.attributes.position, index ).applyMatrix4( this.bindMatrix );
+               _skinIndex.fromBufferAttribute( geometry.attributes.skinIndex, index );
+               _skinWeight.fromBufferAttribute( geometry.attributes.skinWeight, index );
 
-                       target.set( 0, 0, 0 );
+               _basePosition.fromBufferAttribute( geometry.attributes.position, index ).applyMatrix4( this.bindMatrix );
 
-                       for ( let i = 0; i < 4; i ++ ) {
+               target.set( 0, 0, 0 );
 
-                               const weight = skinWeight.getComponent( i );
+               for ( let i = 0; i < 4; i ++ ) {
 
-                               if ( weight !== 0 ) {
+                       const weight = _skinWeight.getComponent( i );
 
-                                       const boneIndex = skinIndex.getComponent( i );
+                       if ( weight !== 0 ) {
 
-                                       matrix.multiplyMatrices( skeleton.bones[ boneIndex ].matrixWorld, skeleton.boneInverses[ boneIndex ] );
+                               const boneIndex = _skinIndex.getComponent( i );
 
-                                       target.addScaledVector( vector.copy( basePosition ).applyMatrix4( matrix ), weight );
+                               _matrix$1.multiplyMatrices( skeleton.bones[ boneIndex ].matrixWorld, skeleton.boneInverses[ boneIndex ] );
 
-                               }
+                               target.addScaledVector( _vector$7.copy( _basePosition ).applyMatrix4( _matrix$1 ), weight );
 
                        }
 
-                       return target.applyMatrix4( this.bindMatrixInverse );
+               }
 
-               };
+               return target.applyMatrix4( this.bindMatrixInverse );
 
-       }() )
+       }
 
 } );
 
@@ -26595,6 +26291,9 @@ InstancedMesh.prototype = Object.assign( Object.create( Mesh.prototype ), {
                Mesh.prototype.copy.call( this, source );
 
                this.instanceMatrix.copy( source.instanceMatrix );
+
+               if ( source.instanceColor !== null ) this.instanceColor = source.instanceColor.clone();
+
                this.count = source.count;
 
                return this;
@@ -26674,6 +26373,12 @@ InstancedMesh.prototype = Object.assign( Object.create( Mesh.prototype ), {
 
        updateMorphTargets: function () {
 
+       },
+
+       dispose: function () {
+
+               this.dispatchEvent( { type: 'dispose' } );
+
        }
 
 } );
@@ -26734,20 +26439,14 @@ const _inverseMatrix$1 = new Matrix4();
 const _ray$1 = new Ray();
 const _sphere$2 = new Sphere();
 
-function Line( geometry, material, mode ) {
-
-       if ( mode === 1 ) {
-
-               console.error( 'THREE.Line: parameter THREE.LinePieces no longer supported. Use THREE.LineSegments instead.' );
-
-       }
+function Line( geometry = new BufferGeometry(), material = new LineBasicMaterial() ) {
 
        Object3D.call( this );
 
        this.type = 'Line';
 
-       this.geometry = geometry !== undefined ? geometry : new BufferGeometry();
-       this.material = material !== undefined ? material : new LineBasicMaterial();
+       this.geometry = geometry;
+       this.material = material;
 
        this.updateMorphTargets();
 
@@ -26803,17 +26502,7 @@ Line.prototype = Object.assign( Object.create( Object3D.prototype ), {
 
                } else if ( geometry.isGeometry ) {
 
-                       const vertices = geometry.vertices;
-                       const lineDistances = geometry.lineDistances;
-
-                       lineDistances[ 0 ] = 0;
-
-                       for ( let i = 1, l = vertices.length; i < l; i ++ ) {
-
-                               lineDistances[ i ] = lineDistances[ i - 1 ];
-                               lineDistances[ i ] += vertices[ i - 1 ].distanceTo( vertices[ i ] );
-
-                       }
+                       console.error( 'THREE.Line.computeLineDistances() no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.' );
 
                }
 
@@ -26930,36 +26619,289 @@ Line.prototype = Object.assign( Object.create( Object3D.prototype ), {
 
                } else if ( geometry.isGeometry ) {
 
-                       const vertices = geometry.vertices;
-                       const nbVertices = vertices.length;
+                       console.error( 'THREE.Line.raycast() no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.' );
 
-                       for ( let i = 0; i < nbVertices - 1; i += step ) {
+               }
 
-                               const distSq = _ray$1.distanceSqToSegment( vertices[ i ], vertices[ i + 1 ], interRay, interSegment );
+       },
 
-                               if ( distSq > localThresholdSq ) continue;
+       updateMorphTargets: function () {
 
-                               interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation
+               const geometry = this.geometry;
 
-                               const distance = raycaster.ray.origin.distanceTo( interRay );
+               if ( geometry.isBufferGeometry ) {
 
-                               if ( distance < raycaster.near || distance > raycaster.far ) continue;
+                       const morphAttributes = geometry.morphAttributes;
+                       const keys = Object.keys( morphAttributes );
 
-                               intersects.push( {
+                       if ( keys.length > 0 ) {
 
-                                       distance: distance,
-                                       // What do we want? intersection point on the ray or on the segment??
-                                       // point: raycaster.ray.at( distance ),
-                                       point: interSegment.clone().applyMatrix4( this.matrixWorld ),
-                                       index: i,
-                                       face: null,
-                                       faceIndex: null,
-                                       object: this
+                               const morphAttribute = morphAttributes[ keys[ 0 ] ];
 
-                               } );
+                               if ( morphAttribute !== undefined ) {
+
+                                       this.morphTargetInfluences = [];
+                                       this.morphTargetDictionary = {};
+
+                                       for ( let m = 0, ml = morphAttribute.length; m < ml; m ++ ) {
+
+                                               const name = morphAttribute[ m ].name || String( m );
+
+                                               this.morphTargetInfluences.push( 0 );
+                                               this.morphTargetDictionary[ name ] = m;
+
+                                       }
+
+                               }
+
+                       }
+
+               } else {
+
+                       const morphTargets = geometry.morphTargets;
+
+                       if ( morphTargets !== undefined && morphTargets.length > 0 ) {
+
+                               console.error( 'THREE.Line.updateMorphTargets() does not support THREE.Geometry. Use THREE.BufferGeometry instead.' );
+
+                       }
+
+               }
+
+       }
+
+} );
+
+const _start$1 = new Vector3();
+const _end$1 = new Vector3();
+
+function LineSegments( geometry, material ) {
+
+       Line.call( this, geometry, material );
+
+       this.type = 'LineSegments';
+
+}
+
+LineSegments.prototype = Object.assign( Object.create( Line.prototype ), {
+
+       constructor: LineSegments,
+
+       isLineSegments: true,
+
+       computeLineDistances: function () {
+
+               const geometry = this.geometry;
+
+               if ( geometry.isBufferGeometry ) {
+
+                       // we assume non-indexed geometry
+
+                       if ( geometry.index === null ) {
+
+                               const positionAttribute = geometry.attributes.position;
+                               const lineDistances = [];
+
+                               for ( let i = 0, l = positionAttribute.count; i < l; i += 2 ) {
+
+                                       _start$1.fromBufferAttribute( positionAttribute, i );
+                                       _end$1.fromBufferAttribute( positionAttribute, i + 1 );
+
+                                       lineDistances[ i ] = ( i === 0 ) ? 0 : lineDistances[ i - 1 ];
+                                       lineDistances[ i + 1 ] = lineDistances[ i ] + _start$1.distanceTo( _end$1 );
+
+                               }
+
+                               geometry.setAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) );
+
+                       } else {
+
+                               console.warn( 'THREE.LineSegments.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' );
 
                        }
 
+               } else if ( geometry.isGeometry ) {
+
+                       console.error( 'THREE.LineSegments.computeLineDistances() no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.' );
+
+               }
+
+               return this;
+
+       }
+
+} );
+
+function LineLoop( geometry, material ) {
+
+       Line.call( this, geometry, material );
+
+       this.type = 'LineLoop';
+
+}
+
+LineLoop.prototype = Object.assign( Object.create( Line.prototype ), {
+
+       constructor: LineLoop,
+
+       isLineLoop: true,
+
+} );
+
+/**
+ * parameters = {
+ *  color: <hex>,
+ *  opacity: <float>,
+ *  map: new THREE.Texture( <Image> ),
+ *  alphaMap: new THREE.Texture( <Image> ),
+ *
+ *  size: <float>,
+ *  sizeAttenuation: <bool>
+ *
+ *  morphTargets: <bool>
+ * }
+ */
+
+function PointsMaterial( parameters ) {
+
+       Material.call( this );
+
+       this.type = 'PointsMaterial';
+
+       this.color = new Color( 0xffffff );
+
+       this.map = null;
+
+       this.alphaMap = null;
+
+       this.size = 1;
+       this.sizeAttenuation = true;
+
+       this.morphTargets = false;
+
+       this.setValues( parameters );
+
+}
+
+PointsMaterial.prototype = Object.create( Material.prototype );
+PointsMaterial.prototype.constructor = PointsMaterial;
+
+PointsMaterial.prototype.isPointsMaterial = true;
+
+PointsMaterial.prototype.copy = function ( source ) {
+
+       Material.prototype.copy.call( this, source );
+
+       this.color.copy( source.color );
+
+       this.map = source.map;
+
+       this.alphaMap = source.alphaMap;
+
+       this.size = source.size;
+       this.sizeAttenuation = source.sizeAttenuation;
+
+       this.morphTargets = source.morphTargets;
+
+       return this;
+
+};
+
+const _inverseMatrix$2 = new Matrix4();
+const _ray$2 = new Ray();
+const _sphere$3 = new Sphere();
+const _position$1 = new Vector3();
+
+function Points( geometry = new BufferGeometry(), material = new PointsMaterial() ) {
+
+       Object3D.call( this );
+
+       this.type = 'Points';
+
+       this.geometry = geometry;
+       this.material = material;
+
+       this.updateMorphTargets();
+
+}
+
+Points.prototype = Object.assign( Object.create( Object3D.prototype ), {
+
+       constructor: Points,
+
+       isPoints: true,
+
+       copy: function ( source ) {
+
+               Object3D.prototype.copy.call( this, source );
+
+               this.material = source.material;
+               this.geometry = source.geometry;
+
+               return this;
+
+       },
+
+       raycast: function ( raycaster, intersects ) {
+
+               const geometry = this.geometry;
+               const matrixWorld = this.matrixWorld;
+               const threshold = raycaster.params.Points.threshold;
+
+               // Checking boundingSphere distance to ray
+
+               if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
+
+               _sphere$3.copy( geometry.boundingSphere );
+               _sphere$3.applyMatrix4( matrixWorld );
+               _sphere$3.radius += threshold;
+
+               if ( raycaster.ray.intersectsSphere( _sphere$3 ) === false ) return;
+
+               //
+
+               _inverseMatrix$2.copy( matrixWorld ).invert();
+               _ray$2.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$2 );
+
+               const localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 );
+               const localThresholdSq = localThreshold * localThreshold;
+
+               if ( geometry.isBufferGeometry ) {
+
+                       const index = geometry.index;
+                       const attributes = geometry.attributes;
+                       const positionAttribute = attributes.position;
+
+                       if ( index !== null ) {
+
+                               const indices = index.array;
+
+                               for ( let i = 0, il = indices.length; i < il; i ++ ) {
+
+                                       const a = indices[ i ];
+
+                                       _position$1.fromBufferAttribute( positionAttribute, a );
+
+                                       testPoint( _position$1, a, localThresholdSq, matrixWorld, raycaster, intersects, this );
+
+                               }
+
+                       } else {
+
+                               for ( let i = 0, l = positionAttribute.count; i < l; i ++ ) {
+
+                                       _position$1.fromBufferAttribute( positionAttribute, i );
+
+                                       testPoint( _position$1, i, localThresholdSq, matrixWorld, raycaster, intersects, this );
+
+                               }
+
+                       }
+
+               } else {
+
+                       console.error( 'THREE.Points.raycast() no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.' );
+
                }
 
        },
@@ -27001,1858 +26943,173 @@ Line.prototype = Object.assign( Object.create( Object3D.prototype ), {
 
                        if ( morphTargets !== undefined && morphTargets.length > 0 ) {
 
-                               console.error( 'THREE.Line.updateMorphTargets() does not support THREE.Geometry. Use THREE.BufferGeometry instead.' );
-
-                       }
-
-               }
-
-       }
-
-} );
-
-const _start$1 = new Vector3();
-const _end$1 = new Vector3();
-
-function LineSegments( geometry, material ) {
-
-       Line.call( this, geometry, material );
-
-       this.type = 'LineSegments';
-
-}
-
-LineSegments.prototype = Object.assign( Object.create( Line.prototype ), {
-
-       constructor: LineSegments,
-
-       isLineSegments: true,
-
-       computeLineDistances: function () {
-
-               const geometry = this.geometry;
-
-               if ( geometry.isBufferGeometry ) {
-
-                       // we assume non-indexed geometry
-
-                       if ( geometry.index === null ) {
-
-                               const positionAttribute = geometry.attributes.position;
-                               const lineDistances = [];
-
-                               for ( let i = 0, l = positionAttribute.count; i < l; i += 2 ) {
-
-                                       _start$1.fromBufferAttribute( positionAttribute, i );
-                                       _end$1.fromBufferAttribute( positionAttribute, i + 1 );
-
-                                       lineDistances[ i ] = ( i === 0 ) ? 0 : lineDistances[ i - 1 ];
-                                       lineDistances[ i + 1 ] = lineDistances[ i ] + _start$1.distanceTo( _end$1 );
-
-                               }
-
-                               geometry.setAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) );
-
-                       } else {
-
-                               console.warn( 'THREE.LineSegments.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' );
-
-                       }
-
-               } else if ( geometry.isGeometry ) {
-
-                       const vertices = geometry.vertices;
-                       const lineDistances = geometry.lineDistances;
-
-                       for ( let i = 0, l = vertices.length; i < l; i += 2 ) {
-
-                               _start$1.copy( vertices[ i ] );
-                               _end$1.copy( vertices[ i + 1 ] );
-
-                               lineDistances[ i ] = ( i === 0 ) ? 0 : lineDistances[ i - 1 ];
-                               lineDistances[ i + 1 ] = lineDistances[ i ] + _start$1.distanceTo( _end$1 );
-
-                       }
-
-               }
-
-               return this;
-
-       }
-
-} );
-
-function LineLoop( geometry, material ) {
-
-       Line.call( this, geometry, material );
-
-       this.type = 'LineLoop';
-
-}
-
-LineLoop.prototype = Object.assign( Object.create( Line.prototype ), {
-
-       constructor: LineLoop,
-
-       isLineLoop: true,
-
-} );
-
-/**
- * parameters = {
- *  color: <hex>,
- *  opacity: <float>,
- *  map: new THREE.Texture( <Image> ),
- *  alphaMap: new THREE.Texture( <Image> ),
- *
- *  size: <float>,
- *  sizeAttenuation: <bool>
- *
- *  morphTargets: <bool>
- * }
- */
-
-function PointsMaterial( parameters ) {
-
-       Material.call( this );
-
-       this.type = 'PointsMaterial';
-
-       this.color = new Color( 0xffffff );
-
-       this.map = null;
-
-       this.alphaMap = null;
-
-       this.size = 1;
-       this.sizeAttenuation = true;
-
-       this.morphTargets = false;
-
-       this.setValues( parameters );
-
-}
-
-PointsMaterial.prototype = Object.create( Material.prototype );
-PointsMaterial.prototype.constructor = PointsMaterial;
-
-PointsMaterial.prototype.isPointsMaterial = true;
-
-PointsMaterial.prototype.copy = function ( source ) {
-
-       Material.prototype.copy.call( this, source );
-
-       this.color.copy( source.color );
-
-       this.map = source.map;
-
-       this.alphaMap = source.alphaMap;
-
-       this.size = source.size;
-       this.sizeAttenuation = source.sizeAttenuation;
-
-       this.morphTargets = source.morphTargets;
-
-       return this;
-
-};
-
-const _inverseMatrix$2 = new Matrix4();
-const _ray$2 = new Ray();
-const _sphere$3 = new Sphere();
-const _position$1 = new Vector3();
-
-function Points( geometry, material ) {
-
-       Object3D.call( this );
-
-       this.type = 'Points';
-
-       this.geometry = geometry !== undefined ? geometry : new BufferGeometry();
-       this.material = material !== undefined ? material : new PointsMaterial();
-
-       this.updateMorphTargets();
-
-}
-
-Points.prototype = Object.assign( Object.create( Object3D.prototype ), {
-
-       constructor: Points,
-
-       isPoints: true,
-
-       copy: function ( source ) {
-
-               Object3D.prototype.copy.call( this, source );
-
-               this.material = source.material;
-               this.geometry = source.geometry;
-
-               return this;
-
-       },
-
-       raycast: function ( raycaster, intersects ) {
-
-               const geometry = this.geometry;
-               const matrixWorld = this.matrixWorld;
-               const threshold = raycaster.params.Points.threshold;
-
-               // Checking boundingSphere distance to ray
-
-               if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
-
-               _sphere$3.copy( geometry.boundingSphere );
-               _sphere$3.applyMatrix4( matrixWorld );
-               _sphere$3.radius += threshold;
-
-               if ( raycaster.ray.intersectsSphere( _sphere$3 ) === false ) return;
-
-               //
-
-               _inverseMatrix$2.copy( matrixWorld ).invert();
-               _ray$2.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$2 );
-
-               const localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 );
-               const localThresholdSq = localThreshold * localThreshold;
-
-               if ( geometry.isBufferGeometry ) {
-
-                       const index = geometry.index;
-                       const attributes = geometry.attributes;
-                       const positionAttribute = attributes.position;
-
-                       if ( index !== null ) {
-
-                               const indices = index.array;
-
-                               for ( let i = 0, il = indices.length; i < il; i ++ ) {
-
-                                       const a = indices[ i ];
-
-                                       _position$1.fromBufferAttribute( positionAttribute, a );
-
-                                       testPoint( _position$1, a, localThresholdSq, matrixWorld, raycaster, intersects, this );
-
-                               }
-
-                       } else {
-
-                               for ( let i = 0, l = positionAttribute.count; i < l; i ++ ) {
-
-                                       _position$1.fromBufferAttribute( positionAttribute, i );
-
-                                       testPoint( _position$1, i, localThresholdSq, matrixWorld, raycaster, intersects, this );
-
-                               }
-
-                       }
-
-               } else {
-
-                       const vertices = geometry.vertices;
-
-                       for ( let i = 0, l = vertices.length; i < l; i ++ ) {
-
-                               testPoint( vertices[ i ], i, localThresholdSq, matrixWorld, raycaster, intersects, this );
-
-                       }
-
-               }
-
-       },
-
-       updateMorphTargets: function () {
-
-               const geometry = this.geometry;
-
-               if ( geometry.isBufferGeometry ) {
-
-                       const morphAttributes = geometry.morphAttributes;
-                       const keys = Object.keys( morphAttributes );
-
-                       if ( keys.length > 0 ) {
-
-                               const morphAttribute = morphAttributes[ keys[ 0 ] ];
-
-                               if ( morphAttribute !== undefined ) {
-
-                                       this.morphTargetInfluences = [];
-                                       this.morphTargetDictionary = {};
-
-                                       for ( let m = 0, ml = morphAttribute.length; m < ml; m ++ ) {
-
-                                               const name = morphAttribute[ m ].name || String( m );
-
-                                               this.morphTargetInfluences.push( 0 );
-                                               this.morphTargetDictionary[ name ] = m;
-
-                                       }
-
-                               }
-
-                       }
-
-               } else {
-
-                       const morphTargets = geometry.morphTargets;
-
-                       if ( morphTargets !== undefined && morphTargets.length > 0 ) {
-
-                               console.error( 'THREE.Points.updateMorphTargets() does not support THREE.Geometry. Use THREE.BufferGeometry instead.' );
-
-                       }
-
-               }
-
-       }
-
-} );
-
-function testPoint( point, index, localThresholdSq, matrixWorld, raycaster, intersects, object ) {
-
-       const rayPointDistanceSq = _ray$2.distanceSqToPoint( point );
-
-       if ( rayPointDistanceSq < localThresholdSq ) {
-
-               const intersectPoint = new Vector3();
-
-               _ray$2.closestPointToPoint( point, intersectPoint );
-               intersectPoint.applyMatrix4( matrixWorld );
-
-               const distance = raycaster.ray.origin.distanceTo( intersectPoint );
-
-               if ( distance < raycaster.near || distance > raycaster.far ) return;
-
-               intersects.push( {
-
-                       distance: distance,
-                       distanceToRay: Math.sqrt( rayPointDistanceSq ),
-                       point: intersectPoint,
-                       index: index,
-                       face: null,
-                       object: object
-
-               } );
-
-       }
-
-}
-
-function VideoTexture( video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {
-
-       Texture.call( this, video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
-
-       this.format = format !== undefined ? format : RGBFormat;
-
-       this.minFilter = minFilter !== undefined ? minFilter : LinearFilter;
-       this.magFilter = magFilter !== undefined ? magFilter : LinearFilter;
-
-       this.generateMipmaps = false;
-
-       const scope = this;
-
-       function updateVideo() {
-
-               scope.needsUpdate = true;
-               video.requestVideoFrameCallback( updateVideo );
-
-       }
-
-       if ( 'requestVideoFrameCallback' in video ) {
-
-               video.requestVideoFrameCallback( updateVideo );
-
-       }
-
-}
-
-VideoTexture.prototype = Object.assign( Object.create( Texture.prototype ), {
-
-       constructor: VideoTexture,
-
-       clone: function () {
-
-               return new this.constructor( this.image ).copy( this );
-
-       },
-
-       isVideoTexture: true,
-
-       update: function () {
-
-               const video = this.image;
-               const hasVideoFrameCallback = 'requestVideoFrameCallback' in video;
-
-               if ( hasVideoFrameCallback === false && video.readyState >= video.HAVE_CURRENT_DATA ) {
-
-                       this.needsUpdate = true;
-
-               }
-
-       }
-
-} );
-
-function CompressedTexture( mipmaps, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding ) {
-
-       Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding );
-
-       this.image = { width: width, height: height };
-       this.mipmaps = mipmaps;
-
-       // no flipping for cube textures
-       // (also flipping doesn't work for compressed textures )
-
-       this.flipY = false;
-
-       // can't generate mipmaps for compressed textures
-       // mips must be embedded in DDS files
-
-       this.generateMipmaps = false;
-
-}
-
-CompressedTexture.prototype = Object.create( Texture.prototype );
-CompressedTexture.prototype.constructor = CompressedTexture;
-
-CompressedTexture.prototype.isCompressedTexture = true;
-
-function CanvasTexture( canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {
-
-       Texture.call( this, canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
-
-       this.needsUpdate = true;
-
-}
-
-CanvasTexture.prototype = Object.create( Texture.prototype );
-CanvasTexture.prototype.constructor = CanvasTexture;
-CanvasTexture.prototype.isCanvasTexture = true;
-
-function DepthTexture( width, height, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, format ) {
-
-       format = format !== undefined ? format : DepthFormat;
-
-       if ( format !== DepthFormat && format !== DepthStencilFormat ) {
-
-               throw new Error( 'DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat' );
-
-       }
-
-       if ( type === undefined && format === DepthFormat ) type = UnsignedShortType;
-       if ( type === undefined && format === DepthStencilFormat ) type = UnsignedInt248Type;
-
-       Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
-
-       this.image = { width: width, height: height };
-
-       this.magFilter = magFilter !== undefined ? magFilter : NearestFilter;
-       this.minFilter = minFilter !== undefined ? minFilter : NearestFilter;
-
-       this.flipY = false;
-       this.generateMipmaps = false;
-
-}
-
-DepthTexture.prototype = Object.create( Texture.prototype );
-DepthTexture.prototype.constructor = DepthTexture;
-DepthTexture.prototype.isDepthTexture = true;
-
-let _geometryId = 0; // Geometry uses even numbers as Id
-const _m1$3 = new Matrix4();
-const _obj$1 = new Object3D();
-const _offset$1 = new Vector3();
-
-function Geometry() {
-
-       Object.defineProperty( this, 'id', { value: _geometryId += 2 } );
-
-       this.uuid = MathUtils.generateUUID();
-
-       this.name = '';
-       this.type = 'Geometry';
-
-       this.vertices = [];
-       this.colors = [];
-       this.faces = [];
-       this.faceVertexUvs = [[]];
-
-       this.morphTargets = [];
-       this.morphNormals = [];
-
-       this.skinWeights = [];
-       this.skinIndices = [];
-
-       this.lineDistances = [];
-
-       this.boundingBox = null;
-       this.boundingSphere = null;
-
-       // update flags
-
-       this.elementsNeedUpdate = false;
-       this.verticesNeedUpdate = false;
-       this.uvsNeedUpdate = false;
-       this.normalsNeedUpdate = false;
-       this.colorsNeedUpdate = false;
-       this.lineDistancesNeedUpdate = false;
-       this.groupsNeedUpdate = false;
-
-}
-
-Geometry.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
-
-       constructor: Geometry,
-
-       isGeometry: true,
-
-       applyMatrix4: function ( matrix ) {
-
-               const normalMatrix = new Matrix3().getNormalMatrix( matrix );
-
-               for ( let i = 0, il = this.vertices.length; i < il; i ++ ) {
-
-                       const vertex = this.vertices[ i ];
-                       vertex.applyMatrix4( matrix );
-
-               }
-
-               for ( let i = 0, il = this.faces.length; i < il; i ++ ) {
-
-                       const face = this.faces[ i ];
-                       face.normal.applyMatrix3( normalMatrix ).normalize();
-
-                       for ( let j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) {
-
-                               face.vertexNormals[ j ].applyMatrix3( normalMatrix ).normalize();
-
-                       }
-
-               }
-
-               if ( this.boundingBox !== null ) {
-
-                       this.computeBoundingBox();
-
-               }
-
-               if ( this.boundingSphere !== null ) {
-
-                       this.computeBoundingSphere();
-
-               }
-
-               this.verticesNeedUpdate = true;
-               this.normalsNeedUpdate = true;
-
-               return this;
-
-       },
-
-       rotateX: function ( angle ) {
-
-               // rotate geometry around world x-axis
-
-               _m1$3.makeRotationX( angle );
-
-               this.applyMatrix4( _m1$3 );
-
-               return this;
-
-       },
-
-       rotateY: function ( angle ) {
-
-               // rotate geometry around world y-axis
-
-               _m1$3.makeRotationY( angle );
-
-               this.applyMatrix4( _m1$3 );
-
-               return this;
-
-       },
-
-       rotateZ: function ( angle ) {
-
-               // rotate geometry around world z-axis
-
-               _m1$3.makeRotationZ( angle );
-
-               this.applyMatrix4( _m1$3 );
-
-               return this;
-
-       },
-
-       translate: function ( x, y, z ) {
-
-               // translate geometry
-
-               _m1$3.makeTranslation( x, y, z );
-
-               this.applyMatrix4( _m1$3 );
-
-               return this;
-
-       },
-
-       scale: function ( x, y, z ) {
-
-               // scale geometry
-
-               _m1$3.makeScale( x, y, z );
-
-               this.applyMatrix4( _m1$3 );
-
-               return this;
-
-       },
-
-       lookAt: function ( vector ) {
-
-               _obj$1.lookAt( vector );
-
-               _obj$1.updateMatrix();
-
-               this.applyMatrix4( _obj$1.matrix );
-
-               return this;
-
-       },
-
-       fromBufferGeometry: function ( geometry ) {
-
-               const scope = this;
-
-               const index = geometry.index !== null ? geometry.index : undefined;
-               const attributes = geometry.attributes;
-
-               if ( attributes.position === undefined ) {
-
-                       console.error( 'THREE.Geometry.fromBufferGeometry(): Position attribute required for conversion.' );
-                       return this;
-
-               }
-
-               const position = attributes.position;
-               const normal = attributes.normal;
-               const color = attributes.color;
-               const uv = attributes.uv;
-               const uv2 = attributes.uv2;
-
-               if ( uv2 !== undefined ) this.faceVertexUvs[ 1 ] = [];
-
-               for ( let i = 0; i < position.count; i ++ ) {
-
-                       scope.vertices.push( new Vector3().fromBufferAttribute( position, i ) );
-
-                       if ( color !== undefined ) {
-
-                               scope.colors.push( new Color().fromBufferAttribute( color, i ) );
-
-                       }
-
-               }
-
-               function addFace( a, b, c, materialIndex ) {
-
-                       const vertexColors = ( color === undefined ) ? [] : [
-                               scope.colors[ a ].clone(),
-                               scope.colors[ b ].clone(),
-                               scope.colors[ c ].clone()
-                       ];
-
-                       const vertexNormals = ( normal === undefined ) ? [] : [
-                               new Vector3().fromBufferAttribute( normal, a ),
-                               new Vector3().fromBufferAttribute( normal, b ),
-                               new Vector3().fromBufferAttribute( normal, c )
-                       ];
-
-                       const face = new Face3( a, b, c, vertexNormals, vertexColors, materialIndex );
-
-                       scope.faces.push( face );
-
-                       if ( uv !== undefined ) {
-
-                               scope.faceVertexUvs[ 0 ].push( [
-                                       new Vector2().fromBufferAttribute( uv, a ),
-                                       new Vector2().fromBufferAttribute( uv, b ),
-                                       new Vector2().fromBufferAttribute( uv, c )
-                               ] );
-
-                       }
-
-                       if ( uv2 !== undefined ) {
-
-                               scope.faceVertexUvs[ 1 ].push( [
-                                       new Vector2().fromBufferAttribute( uv2, a ),
-                                       new Vector2().fromBufferAttribute( uv2, b ),
-                                       new Vector2().fromBufferAttribute( uv2, c )
-                               ] );
-
-                       }
-
-               }
-
-               const groups = geometry.groups;
-
-               if ( groups.length > 0 ) {
-
-                       for ( let i = 0; i < groups.length; i ++ ) {
-
-                               const group = groups[ i ];
-
-                               const start = group.start;
-                               const count = group.count;
-
-                               for ( let j = start, jl = start + count; j < jl; j += 3 ) {
-
-                                       if ( index !== undefined ) {
-
-                                               addFace( index.getX( j ), index.getX( j + 1 ), index.getX( j + 2 ), group.materialIndex );
-
-                                       } else {
-
-                                               addFace( j, j + 1, j + 2, group.materialIndex );
-
-                                       }
-
-                               }
-
-                       }
-
-               } else {
-
-                       if ( index !== undefined ) {
-
-                               for ( let i = 0; i < index.count; i += 3 ) {
-
-                                       addFace( index.getX( i ), index.getX( i + 1 ), index.getX( i + 2 ) );
-
-                               }
-
-                       } else {
-
-                               for ( let i = 0; i < position.count; i += 3 ) {
-
-                                       addFace( i, i + 1, i + 2 );
-
-                               }
-
-                       }
-
-               }
-
-               this.computeFaceNormals();
-
-               if ( geometry.boundingBox !== null ) {
-
-                       this.boundingBox = geometry.boundingBox.clone();
-
-               }
-
-               if ( geometry.boundingSphere !== null ) {
-
-                       this.boundingSphere = geometry.boundingSphere.clone();
-
-               }
-
-               return this;
-
-       },
-
-       center: function () {
-
-               this.computeBoundingBox();
-
-               this.boundingBox.getCenter( _offset$1 ).negate();
-
-               this.translate( _offset$1.x, _offset$1.y, _offset$1.z );
-
-               return this;
-
-       },
-
-       normalize: function () {
-
-               this.computeBoundingSphere();
-
-               const center = this.boundingSphere.center;
-               const radius = this.boundingSphere.radius;
-
-               const s = radius === 0 ? 1 : 1.0 / radius;
-
-               const matrix = new Matrix4();
-               matrix.set(
-                       s, 0, 0, - s * center.x,
-                       0, s, 0, - s * center.y,
-                       0, 0, s, - s * center.z,
-                       0, 0, 0, 1
-               );
-
-               this.applyMatrix4( matrix );
-
-               return this;
-
-       },
-
-       computeFaceNormals: function () {
-
-               const cb = new Vector3(), ab = new Vector3();
-
-               for ( let f = 0, fl = this.faces.length; f < fl; f ++ ) {
-
-                       const face = this.faces[ f ];
-
-                       const vA = this.vertices[ face.a ];
-                       const vB = this.vertices[ face.b ];
-                       const vC = this.vertices[ face.c ];
-
-                       cb.subVectors( vC, vB );
-                       ab.subVectors( vA, vB );
-                       cb.cross( ab );
-
-                       cb.normalize();
-
-                       face.normal.copy( cb );
-
-               }
-
-       },
-
-       computeVertexNormals: function ( areaWeighted = true ) {
-
-               const vertices = new Array( this.vertices.length );
-
-               for ( let v = 0, vl = this.vertices.length; v < vl; v ++ ) {
-
-                       vertices[ v ] = new Vector3();
-
-               }
-
-               if ( areaWeighted ) {
-
-                       // vertex normals weighted by triangle areas
-                       // http://www.iquilezles.org/www/articles/normals/normals.htm
-
-                       const cb = new Vector3(), ab = new Vector3();
-
-                       for ( let f = 0, fl = this.faces.length; f < fl; f ++ ) {
-
-                               const face = this.faces[ f ];
-
-                               const vA = this.vertices[ face.a ];
-                               const vB = this.vertices[ face.b ];
-                               const vC = this.vertices[ face.c ];
-
-                               cb.subVectors( vC, vB );
-                               ab.subVectors( vA, vB );
-                               cb.cross( ab );
-
-                               vertices[ face.a ].add( cb );
-                               vertices[ face.b ].add( cb );
-                               vertices[ face.c ].add( cb );
-
-                       }
-
-               } else {
-
-                       this.computeFaceNormals();
-
-                       for ( let f = 0, fl = this.faces.length; f < fl; f ++ ) {
-
-                               const face = this.faces[ f ];
-
-                               vertices[ face.a ].add( face.normal );
-                               vertices[ face.b ].add( face.normal );
-                               vertices[ face.c ].add( face.normal );
-
-                       }
-
-               }
-
-               for ( let v = 0, vl = this.vertices.length; v < vl; v ++ ) {
-
-                       vertices[ v ].normalize();
-
-               }
-
-               for ( let f = 0, fl = this.faces.length; f < fl; f ++ ) {
-
-                       const face = this.faces[ f ];
-
-                       const vertexNormals = face.vertexNormals;
-
-                       if ( vertexNormals.length === 3 ) {
-
-                               vertexNormals[ 0 ].copy( vertices[ face.a ] );
-                               vertexNormals[ 1 ].copy( vertices[ face.b ] );
-                               vertexNormals[ 2 ].copy( vertices[ face.c ] );
-
-                       } else {
-
-                               vertexNormals[ 0 ] = vertices[ face.a ].clone();
-                               vertexNormals[ 1 ] = vertices[ face.b ].clone();
-                               vertexNormals[ 2 ] = vertices[ face.c ].clone();
-
-                       }
-
-               }
-
-               if ( this.faces.length > 0 ) {
-
-                       this.normalsNeedUpdate = true;
-
-               }
-
-       },
-
-       computeFlatVertexNormals: function () {
-
-               this.computeFaceNormals();
-
-               for ( let f = 0, fl = this.faces.length; f < fl; f ++ ) {
-
-                       const face = this.faces[ f ];
-
-                       const vertexNormals = face.vertexNormals;
-
-                       if ( vertexNormals.length === 3 ) {
-
-                               vertexNormals[ 0 ].copy( face.normal );
-                               vertexNormals[ 1 ].copy( face.normal );
-                               vertexNormals[ 2 ].copy( face.normal );
-
-                       } else {
-
-                               vertexNormals[ 0 ] = face.normal.clone();
-                               vertexNormals[ 1 ] = face.normal.clone();
-                               vertexNormals[ 2 ] = face.normal.clone();
-
-                       }
-
-               }
-
-               if ( this.faces.length > 0 ) {
-
-                       this.normalsNeedUpdate = true;
-
-               }
-
-       },
-
-       computeMorphNormals: function () {
-
-               // save original normals
-               // - create temp variables on first access
-               //   otherwise just copy (for faster repeated calls)
-
-               for ( let f = 0, fl = this.faces.length; f < fl; f ++ ) {
-
-                       const face = this.faces[ f ];
-
-                       if ( ! face.__originalFaceNormal ) {
-
-                               face.__originalFaceNormal = face.normal.clone();
-
-                       } else {
-
-                               face.__originalFaceNormal.copy( face.normal );
-
-                       }
-
-                       if ( ! face.__originalVertexNormals ) face.__originalVertexNormals = [];
-
-                       for ( let i = 0, il = face.vertexNormals.length; i < il; i ++ ) {
-
-                               if ( ! face.__originalVertexNormals[ i ] ) {
-
-                                       face.__originalVertexNormals[ i ] = face.vertexNormals[ i ].clone();
-
-                               } else {
-
-                                       face.__originalVertexNormals[ i ].copy( face.vertexNormals[ i ] );
-
-                               }
-
-                       }
-
-               }
-
-               // use temp geometry to compute face and vertex normals for each morph
-
-               const tmpGeo = new Geometry();
-               tmpGeo.faces = this.faces;
-
-               for ( let i = 0, il = this.morphTargets.length; i < il; i ++ ) {
-
-                       // create on first access
-
-                       if ( ! this.morphNormals[ i ] ) {
-
-                               this.morphNormals[ i ] = {};
-                               this.morphNormals[ i ].faceNormals = [];
-                               this.morphNormals[ i ].vertexNormals = [];
-
-                               const dstNormalsFace = this.morphNormals[ i ].faceNormals;
-                               const dstNormalsVertex = this.morphNormals[ i ].vertexNormals;
-
-                               for ( let f = 0, fl = this.faces.length; f < fl; f ++ ) {
-
-                                       const faceNormal = new Vector3();
-                                       const vertexNormals = { a: new Vector3(), b: new Vector3(), c: new Vector3() };
-
-                                       dstNormalsFace.push( faceNormal );
-                                       dstNormalsVertex.push( vertexNormals );
-
-                               }
-
-                       }
-
-                       const morphNormals = this.morphNormals[ i ];
-
-                       // set vertices to morph target
-
-                       tmpGeo.vertices = this.morphTargets[ i ].vertices;
-
-                       // compute morph normals
-
-                       tmpGeo.computeFaceNormals();
-                       tmpGeo.computeVertexNormals();
-
-                       // store morph normals
-
-                       for ( let f = 0, fl = this.faces.length; f < fl; f ++ ) {
-
-                               const face = this.faces[ f ];
-
-                               const faceNormal = morphNormals.faceNormals[ f ];
-                               const vertexNormals = morphNormals.vertexNormals[ f ];
-
-                               faceNormal.copy( face.normal );
-
-                               vertexNormals.a.copy( face.vertexNormals[ 0 ] );
-                               vertexNormals.b.copy( face.vertexNormals[ 1 ] );
-                               vertexNormals.c.copy( face.vertexNormals[ 2 ] );
-
-                       }
-
-               }
-
-               // restore original normals
-
-               for ( let f = 0, fl = this.faces.length; f < fl; f ++ ) {
-
-                       const face = this.faces[ f ];
-
-                       face.normal = face.__originalFaceNormal;
-                       face.vertexNormals = face.__originalVertexNormals;
-
-               }
-
-       },
-
-       computeBoundingBox: function () {
-
-               if ( this.boundingBox === null ) {
-
-                       this.boundingBox = new Box3();
-
-               }
-
-               this.boundingBox.setFromPoints( this.vertices );
-
-       },
-
-       computeBoundingSphere: function () {
-
-               if ( this.boundingSphere === null ) {
-
-                       this.boundingSphere = new Sphere();
-
-               }
-
-               this.boundingSphere.setFromPoints( this.vertices );
-
-       },
-
-       merge: function ( geometry, matrix, materialIndexOffset = 0 ) {
-
-               if ( ! ( geometry && geometry.isGeometry ) ) {
-
-                       console.error( 'THREE.Geometry.merge(): geometry not an instance of THREE.Geometry.', geometry );
-                       return;
-
-               }
-
-               let normalMatrix;
-               const vertexOffset = this.vertices.length,
-                       vertices1 = this.vertices,
-                       vertices2 = geometry.vertices,
-                       faces1 = this.faces,
-                       faces2 = geometry.faces,
-                       colors1 = this.colors,
-                       colors2 = geometry.colors;
-
-               if ( matrix !== undefined ) {
-
-                       normalMatrix = new Matrix3().getNormalMatrix( matrix );
-
-               }
-
-               // vertices
-
-               for ( let i = 0, il = vertices2.length; i < il; i ++ ) {
-
-                       const vertex = vertices2[ i ];
-
-                       const vertexCopy = vertex.clone();
-
-                       if ( matrix !== undefined ) vertexCopy.applyMatrix4( matrix );
-
-                       vertices1.push( vertexCopy );
-
-               }
-
-               // colors
-
-               for ( let i = 0, il = colors2.length; i < il; i ++ ) {
-
-                       colors1.push( colors2[ i ].clone() );
-
-               }
-
-               // faces
-
-               for ( let i = 0, il = faces2.length; i < il; i ++ ) {
-
-                       const face = faces2[ i ];
-                       let normal, color;
-                       const faceVertexNormals = face.vertexNormals,
-                               faceVertexColors = face.vertexColors;
-
-                       const faceCopy = new Face3( face.a + vertexOffset, face.b + vertexOffset, face.c + vertexOffset );
-                       faceCopy.normal.copy( face.normal );
-
-                       if ( normalMatrix !== undefined ) {
-
-                               faceCopy.normal.applyMatrix3( normalMatrix ).normalize();
-
-                       }
-
-                       for ( let j = 0, jl = faceVertexNormals.length; j < jl; j ++ ) {
-
-                               normal = faceVertexNormals[ j ].clone();
-
-                               if ( normalMatrix !== undefined ) {
-
-                                       normal.applyMatrix3( normalMatrix ).normalize();
-
-                               }
-
-                               faceCopy.vertexNormals.push( normal );
-
-                       }
-
-                       faceCopy.color.copy( face.color );
-
-                       for ( let j = 0, jl = faceVertexColors.length; j < jl; j ++ ) {
-
-                               color = faceVertexColors[ j ];
-                               faceCopy.vertexColors.push( color.clone() );
-
-                       }
-
-                       faceCopy.materialIndex = face.materialIndex + materialIndexOffset;
-
-                       faces1.push( faceCopy );
-
-               }
-
-               // uvs
-
-               for ( let i = 0, il = geometry.faceVertexUvs.length; i < il; i ++ ) {
-
-                       const faceVertexUvs2 = geometry.faceVertexUvs[ i ];
-
-                       if ( this.faceVertexUvs[ i ] === undefined ) this.faceVertexUvs[ i ] = [];
-
-                       for ( let j = 0, jl = faceVertexUvs2.length; j < jl; j ++ ) {
-
-                               const uvs2 = faceVertexUvs2[ j ], uvsCopy = [];
-
-                               for ( let k = 0, kl = uvs2.length; k < kl; k ++ ) {
-
-                                       uvsCopy.push( uvs2[ k ].clone() );
-
-                               }
-
-                               this.faceVertexUvs[ i ].push( uvsCopy );
-
-                       }
-
-               }
-
-       },
-
-       mergeMesh: function ( mesh ) {
-
-               if ( ! ( mesh && mesh.isMesh ) ) {
-
-                       console.error( 'THREE.Geometry.mergeMesh(): mesh not an instance of THREE.Mesh.', mesh );
-                       return;
-
-               }
-
-               if ( mesh.matrixAutoUpdate ) mesh.updateMatrix();
-
-               this.merge( mesh.geometry, mesh.matrix );
-
-       },
-
-       /*
-        * Checks for duplicate vertices with hashmap.
-        * Duplicated vertices are removed
-        * and faces' vertices are updated.
-        */
-
-       mergeVertices: function ( precisionPoints = 4 ) {
-
-               const verticesMap = {}; // Hashmap for looking up vertices by position coordinates (and making sure they are unique)
-               const unique = [], changes = [];
-
-               const precision = Math.pow( 10, precisionPoints );
-
-               for ( let i = 0, il = this.vertices.length; i < il; i ++ ) {
-
-                       const v = this.vertices[ i ];
-                       const key = Math.round( v.x * precision ) + '_' + Math.round( v.y * precision ) + '_' + Math.round( v.z * precision );
-
-                       if ( verticesMap[ key ] === undefined ) {
-
-                               verticesMap[ key ] = i;
-                               unique.push( this.vertices[ i ] );
-                               changes[ i ] = unique.length - 1;
-
-                       } else {
-
-                               //console.log('Duplicate vertex found. ', i, ' could be using ', verticesMap[key]);
-                               changes[ i ] = changes[ verticesMap[ key ] ];
-
-                       }
-
-               }
-
-
-               // if faces are completely degenerate after merging vertices, we
-               // have to remove them from the geometry.
-               const faceIndicesToRemove = [];
-
-               for ( let i = 0, il = this.faces.length; i < il; i ++ ) {
-
-                       const face = this.faces[ i ];
-
-                       face.a = changes[ face.a ];
-                       face.b = changes[ face.b ];
-                       face.c = changes[ face.c ];
-
-                       const indices = [ face.a, face.b, face.c ];
-
-                       // if any duplicate vertices are found in a Face3
-                       // we have to remove the face as nothing can be saved
-                       for ( let n = 0; n < 3; n ++ ) {
-
-                               if ( indices[ n ] === indices[ ( n + 1 ) % 3 ] ) {
-
-                                       faceIndicesToRemove.push( i );
-                                       break;
-
-                               }
-
-                       }
-
-               }
-
-               for ( let i = faceIndicesToRemove.length - 1; i >= 0; i -- ) {
-
-                       const idx = faceIndicesToRemove[ i ];
-
-                       this.faces.splice( idx, 1 );
-
-                       for ( let j = 0, jl = this.faceVertexUvs.length; j < jl; j ++ ) {
-
-                               this.faceVertexUvs[ j ].splice( idx, 1 );
-
-                       }
-
-               }
-
-               // Use unique set of vertices
-
-               const diff = this.vertices.length - unique.length;
-               this.vertices = unique;
-               return diff;
-
-       },
-
-       setFromPoints: function ( points ) {
-
-               this.vertices = [];
-
-               for ( let i = 0, l = points.length; i < l; i ++ ) {
-
-                       const point = points[ i ];
-                       this.vertices.push( new Vector3( point.x, point.y, point.z || 0 ) );
-
-               }
-
-               return this;
-
-       },
-
-       sortFacesByMaterialIndex: function () {
-
-               const faces = this.faces;
-               const length = faces.length;
-
-               // tag faces
-
-               for ( let i = 0; i < length; i ++ ) {
-
-                       faces[ i ]._id = i;
-
-               }
-
-               // sort faces
-
-               function materialIndexSort( a, b ) {
-
-                       return a.materialIndex - b.materialIndex;
-
-               }
-
-               faces.sort( materialIndexSort );
-
-               // sort uvs
-
-               const uvs1 = this.faceVertexUvs[ 0 ];
-               const uvs2 = this.faceVertexUvs[ 1 ];
-
-               let newUvs1, newUvs2;
-
-               if ( uvs1 && uvs1.length === length ) newUvs1 = [];
-               if ( uvs2 && uvs2.length === length ) newUvs2 = [];
-
-               for ( let i = 0; i < length; i ++ ) {
-
-                       const id = faces[ i ]._id;
-
-                       if ( newUvs1 ) newUvs1.push( uvs1[ id ] );
-                       if ( newUvs2 ) newUvs2.push( uvs2[ id ] );
-
-               }
-
-               if ( newUvs1 ) this.faceVertexUvs[ 0 ] = newUvs1;
-               if ( newUvs2 ) this.faceVertexUvs[ 1 ] = newUvs2;
-
-       },
-
-       toJSON: function () {
-
-               const data = {
-                       metadata: {
-                               version: 4.5,
-                               type: 'Geometry',
-                               generator: 'Geometry.toJSON'
-                       }
-               };
-
-               // standard Geometry serialization
-
-               data.uuid = this.uuid;
-               data.type = this.type;
-               if ( this.name !== '' ) data.name = this.name;
-
-               if ( this.parameters !== undefined ) {
-
-                       const parameters = this.parameters;
-
-                       for ( const key in parameters ) {
-
-                               if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ];
-
-                       }
-
-                       return data;
-
-               }
-
-               const vertices = [];
-
-               for ( let i = 0; i < this.vertices.length; i ++ ) {
-
-                       const vertex = this.vertices[ i ];
-                       vertices.push( vertex.x, vertex.y, vertex.z );
-
-               }
-
-               const faces = [];
-               const normals = [];
-               const normalsHash = {};
-               const colors = [];
-               const colorsHash = {};
-               const uvs = [];
-               const uvsHash = {};
-
-               for ( let i = 0; i < this.faces.length; i ++ ) {
-
-                       const face = this.faces[ i ];
-
-                       const hasMaterial = true;
-                       const hasFaceUv = false; // deprecated
-                       const hasFaceVertexUv = this.faceVertexUvs[ 0 ][ i ] !== undefined;
-                       const hasFaceNormal = face.normal.length() > 0;
-                       const hasFaceVertexNormal = face.vertexNormals.length > 0;
-                       const hasFaceColor = face.color.r !== 1 || face.color.g !== 1 || face.color.b !== 1;
-                       const hasFaceVertexColor = face.vertexColors.length > 0;
-
-                       let faceType = 0;
-
-                       faceType = setBit( faceType, 0, 0 ); // isQuad
-                       faceType = setBit( faceType, 1, hasMaterial );
-                       faceType = setBit( faceType, 2, hasFaceUv );
-                       faceType = setBit( faceType, 3, hasFaceVertexUv );
-                       faceType = setBit( faceType, 4, hasFaceNormal );
-                       faceType = setBit( faceType, 5, hasFaceVertexNormal );
-                       faceType = setBit( faceType, 6, hasFaceColor );
-                       faceType = setBit( faceType, 7, hasFaceVertexColor );
-
-                       faces.push( faceType );
-                       faces.push( face.a, face.b, face.c );
-                       faces.push( face.materialIndex );
-
-                       if ( hasFaceVertexUv ) {
-
-                               const faceVertexUvs = this.faceVertexUvs[ 0 ][ i ];
-
-                               faces.push(
-                                       getUvIndex( faceVertexUvs[ 0 ] ),
-                                       getUvIndex( faceVertexUvs[ 1 ] ),
-                                       getUvIndex( faceVertexUvs[ 2 ] )
-                               );
-
-                       }
-
-                       if ( hasFaceNormal ) {
-
-                               faces.push( getNormalIndex( face.normal ) );
-
-                       }
-
-                       if ( hasFaceVertexNormal ) {
-
-                               const vertexNormals = face.vertexNormals;
-
-                               faces.push(
-                                       getNormalIndex( vertexNormals[ 0 ] ),
-                                       getNormalIndex( vertexNormals[ 1 ] ),
-                                       getNormalIndex( vertexNormals[ 2 ] )
-                               );
-
-                       }
-
-                       if ( hasFaceColor ) {
-
-                               faces.push( getColorIndex( face.color ) );
-
-                       }
-
-                       if ( hasFaceVertexColor ) {
-
-                               const vertexColors = face.vertexColors;
-
-                               faces.push(
-                                       getColorIndex( vertexColors[ 0 ] ),
-                                       getColorIndex( vertexColors[ 1 ] ),
-                                       getColorIndex( vertexColors[ 2 ] )
-                               );
+                               console.error( 'THREE.Points.updateMorphTargets() does not support THREE.Geometry. Use THREE.BufferGeometry instead.' );
 
                        }
 
                }
 
-               function setBit( value, position, enabled ) {
-
-                       return enabled ? value | ( 1 << position ) : value & ( ~ ( 1 << position ) );
-
-               }
+       }
 
-               function getNormalIndex( normal ) {
+} );
 
-                       const hash = normal.x.toString() + normal.y.toString() + normal.z.toString();
+function testPoint( point, index, localThresholdSq, matrixWorld, raycaster, intersects, object ) {
 
-                       if ( normalsHash[ hash ] !== undefined ) {
+       const rayPointDistanceSq = _ray$2.distanceSqToPoint( point );
 
-                               return normalsHash[ hash ];
+       if ( rayPointDistanceSq < localThresholdSq ) {
 
-                       }
+               const intersectPoint = new Vector3();
 
-                       normalsHash[ hash ] = normals.length / 3;
-                       normals.push( normal.x, normal.y, normal.z );
+               _ray$2.closestPointToPoint( point, intersectPoint );
+               intersectPoint.applyMatrix4( matrixWorld );
 
-                       return normalsHash[ hash ];
+               const distance = raycaster.ray.origin.distanceTo( intersectPoint );
 
-               }
+               if ( distance < raycaster.near || distance > raycaster.far ) return;
 
-               function getColorIndex( color ) {
+               intersects.push( {
 
-                       const hash = color.r.toString() + color.g.toString() + color.b.toString();
+                       distance: distance,
+                       distanceToRay: Math.sqrt( rayPointDistanceSq ),
+                       point: intersectPoint,
+                       index: index,
+                       face: null,
+                       object: object
 
-                       if ( colorsHash[ hash ] !== undefined ) {
+               } );
 
-                               return colorsHash[ hash ];
+       }
 
-                       }
+}
 
-                       colorsHash[ hash ] = colors.length;
-                       colors.push( color.getHex() );
+function VideoTexture( video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {
 
-                       return colorsHash[ hash ];
+       Texture.call( this, video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
 
-               }
+       this.format = format !== undefined ? format : RGBFormat;
 
-               function getUvIndex( uv ) {
+       this.minFilter = minFilter !== undefined ? minFilter : LinearFilter;
+       this.magFilter = magFilter !== undefined ? magFilter : LinearFilter;
 
-                       const hash = uv.x.toString() + uv.y.toString();
+       this.generateMipmaps = false;
 
-                       if ( uvsHash[ hash ] !== undefined ) {
+       const scope = this;
 
-                               return uvsHash[ hash ];
+       function updateVideo() {
 
-                       }
+               scope.needsUpdate = true;
+               video.requestVideoFrameCallback( updateVideo );
 
-                       uvsHash[ hash ] = uvs.length / 2;
-                       uvs.push( uv.x, uv.y );
+       }
 
-                       return uvsHash[ hash ];
+       if ( 'requestVideoFrameCallback' in video ) {
 
-               }
+               video.requestVideoFrameCallback( updateVideo );
 
-               data.data = {};
+       }
 
-               data.data.vertices = vertices;
-               data.data.normals = normals;
-               if ( colors.length > 0 ) data.data.colors = colors;
-               if ( uvs.length > 0 ) data.data.uvs = [ uvs ]; // temporal backward compatibility
-               data.data.faces = faces;
+}
 
-               return data;
+VideoTexture.prototype = Object.assign( Object.create( Texture.prototype ), {
 
-       },
+       constructor: VideoTexture,
 
        clone: function () {
 
-               /*
-                // Handle primitives
-
-                const parameters = this.parameters;
-
-                if ( parameters !== undefined ) {
-
-                const values = [];
-
-                for ( const key in parameters ) {
-
-                values.push( parameters[ key ] );
-
-                }
-
-                const geometry = Object.create( this.constructor.prototype );
-                this.constructor.apply( geometry, values );
-                return geometry;
-
-                }
-
-                return new this.constructor().copy( this );
-                */
-
-               return new Geometry().copy( this );
+               return new this.constructor( this.image ).copy( this );
 
        },
 
-       copy: function ( source ) {
-
-               // reset
-
-               this.vertices = [];
-               this.colors = [];
-               this.faces = [];
-               this.faceVertexUvs = [[]];
-               this.morphTargets = [];
-               this.morphNormals = [];
-               this.skinWeights = [];
-               this.skinIndices = [];
-               this.lineDistances = [];
-               this.boundingBox = null;
-               this.boundingSphere = null;
-
-               // name
-
-               this.name = source.name;
-
-               // vertices
-
-               const vertices = source.vertices;
-
-               for ( let i = 0, il = vertices.length; i < il; i ++ ) {
-
-                       this.vertices.push( vertices[ i ].clone() );
-
-               }
-
-               // colors
-
-               const colors = source.colors;
-
-               for ( let i = 0, il = colors.length; i < il; i ++ ) {
-
-                       this.colors.push( colors[ i ].clone() );
-
-               }
-
-               // faces
-
-               const faces = source.faces;
-
-               for ( let i = 0, il = faces.length; i < il; i ++ ) {
-
-                       this.faces.push( faces[ i ].clone() );
-
-               }
-
-               // face vertex uvs
-
-               for ( let i = 0, il = source.faceVertexUvs.length; i < il; i ++ ) {
-
-                       const faceVertexUvs = source.faceVertexUvs[ i ];
-
-                       if ( this.faceVertexUvs[ i ] === undefined ) {
-
-                               this.faceVertexUvs[ i ] = [];
-
-                       }
-
-                       for ( let j = 0, jl = faceVertexUvs.length; j < jl; j ++ ) {
-
-                               const uvs = faceVertexUvs[ j ], uvsCopy = [];
-
-                               for ( let k = 0, kl = uvs.length; k < kl; k ++ ) {
-
-                                       const uv = uvs[ k ];
-
-                                       uvsCopy.push( uv.clone() );
-
-                               }
-
-                               this.faceVertexUvs[ i ].push( uvsCopy );
-
-                       }
-
-               }
-
-               // morph targets
-
-               const morphTargets = source.morphTargets;
-
-               for ( let i = 0, il = morphTargets.length; i < il; i ++ ) {
-
-                       const morphTarget = {};
-                       morphTarget.name = morphTargets[ i ].name;
-
-                       // vertices
-
-                       if ( morphTargets[ i ].vertices !== undefined ) {
-
-                               morphTarget.vertices = [];
-
-                               for ( let j = 0, jl = morphTargets[ i ].vertices.length; j < jl; j ++ ) {
-
-                                       morphTarget.vertices.push( morphTargets[ i ].vertices[ j ].clone() );
-
-                               }
-
-                       }
-
-                       // normals
-
-                       if ( morphTargets[ i ].normals !== undefined ) {
-
-                               morphTarget.normals = [];
-
-                               for ( let j = 0, jl = morphTargets[ i ].normals.length; j < jl; j ++ ) {
-
-                                       morphTarget.normals.push( morphTargets[ i ].normals[ j ].clone() );
-
-                               }
-
-                       }
-
-                       this.morphTargets.push( morphTarget );
-
-               }
-
-               // morph normals
-
-               const morphNormals = source.morphNormals;
-
-               for ( let i = 0, il = morphNormals.length; i < il; i ++ ) {
-
-                       const morphNormal = {};
-
-                       // vertex normals
-
-                       if ( morphNormals[ i ].vertexNormals !== undefined ) {
-
-                               morphNormal.vertexNormals = [];
-
-                               for ( let j = 0, jl = morphNormals[ i ].vertexNormals.length; j < jl; j ++ ) {
-
-                                       const srcVertexNormal = morphNormals[ i ].vertexNormals[ j ];
-                                       const destVertexNormal = {};
-
-                                       destVertexNormal.a = srcVertexNormal.a.clone();
-                                       destVertexNormal.b = srcVertexNormal.b.clone();
-                                       destVertexNormal.c = srcVertexNormal.c.clone();
-
-                                       morphNormal.vertexNormals.push( destVertexNormal );
-
-                               }
-
-                       }
-
-                       // face normals
-
-                       if ( morphNormals[ i ].faceNormals !== undefined ) {
-
-                               morphNormal.faceNormals = [];
-
-                               for ( let j = 0, jl = morphNormals[ i ].faceNormals.length; j < jl; j ++ ) {
-
-                                       morphNormal.faceNormals.push( morphNormals[ i ].faceNormals[ j ].clone() );
-
-                               }
-
-                       }
-
-                       this.morphNormals.push( morphNormal );
-
-               }
-
-               // skin weights
-
-               const skinWeights = source.skinWeights;
-
-               for ( let i = 0, il = skinWeights.length; i < il; i ++ ) {
-
-                       this.skinWeights.push( skinWeights[ i ].clone() );
-
-               }
+       isVideoTexture: true,
 
-               // skin indices
+       update: function () {
 
-               const skinIndices = source.skinIndices;
+               const video = this.image;
+               const hasVideoFrameCallback = 'requestVideoFrameCallback' in video;
 
-               for ( let i = 0, il = skinIndices.length; i < il; i ++ ) {
+               if ( hasVideoFrameCallback === false && video.readyState >= video.HAVE_CURRENT_DATA ) {
 
-                       this.skinIndices.push( skinIndices[ i ].clone() );
+                       this.needsUpdate = true;
 
                }
 
-               // line distances
+       }
 
-               const lineDistances = source.lineDistances;
+} );
 
-               for ( let i = 0, il = lineDistances.length; i < il; i ++ ) {
+function CompressedTexture( mipmaps, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding ) {
 
-                       this.lineDistances.push( lineDistances[ i ] );
+       Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding );
 
-               }
+       this.image = { width: width, height: height };
+       this.mipmaps = mipmaps;
 
-               // bounding box
+       // no flipping for cube textures
+       // (also flipping doesn't work for compressed textures )
 
-               const boundingBox = source.boundingBox;
+       this.flipY = false;
 
-               if ( boundingBox !== null ) {
+       // can't generate mipmaps for compressed textures
+       // mips must be embedded in DDS files
 
-                       this.boundingBox = boundingBox.clone();
+       this.generateMipmaps = false;
 
-               }
+}
 
-               // bounding sphere
+CompressedTexture.prototype = Object.create( Texture.prototype );
+CompressedTexture.prototype.constructor = CompressedTexture;
 
-               const boundingSphere = source.boundingSphere;
+CompressedTexture.prototype.isCompressedTexture = true;
 
-               if ( boundingSphere !== null ) {
+function CanvasTexture( canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {
 
-                       this.boundingSphere = boundingSphere.clone();
+       Texture.call( this, canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
 
-               }
+       this.needsUpdate = true;
 
-               // update flags
+}
 
-               this.elementsNeedUpdate = source.elementsNeedUpdate;
-               this.verticesNeedUpdate = source.verticesNeedUpdate;
-               this.uvsNeedUpdate = source.uvsNeedUpdate;
-               this.normalsNeedUpdate = source.normalsNeedUpdate;
-               this.colorsNeedUpdate = source.colorsNeedUpdate;
-               this.lineDistancesNeedUpdate = source.lineDistancesNeedUpdate;
-               this.groupsNeedUpdate = source.groupsNeedUpdate;
+CanvasTexture.prototype = Object.create( Texture.prototype );
+CanvasTexture.prototype.constructor = CanvasTexture;
+CanvasTexture.prototype.isCanvasTexture = true;
 
-               return this;
+function DepthTexture( width, height, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, format ) {
 
-       },
+       format = format !== undefined ? format : DepthFormat;
 
-       dispose: function () {
+       if ( format !== DepthFormat && format !== DepthStencilFormat ) {
 
-               this.dispatchEvent( { type: 'dispose' } );
+               throw new Error( 'DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat' );
 
        }
 
-} );
-
-class BoxGeometry extends Geometry {
-
-       constructor( width, height, depth, widthSegments, heightSegments, depthSegments ) {
-
-               super();
+       if ( type === undefined && format === DepthFormat ) type = UnsignedShortType;
+       if ( type === undefined && format === DepthStencilFormat ) type = UnsignedInt248Type;
 
-               this.type = 'BoxGeometry';
+       Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
 
-               this.parameters = {
-                       width: width,
-                       height: height,
-                       depth: depth,
-                       widthSegments: widthSegments,
-                       heightSegments: heightSegments,
-                       depthSegments: depthSegments
-               };
+       this.image = { width: width, height: height };
 
-               this.fromBufferGeometry( new BoxBufferGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) );
-               this.mergeVertices();
+       this.magFilter = magFilter !== undefined ? magFilter : NearestFilter;
+       this.minFilter = minFilter !== undefined ? minFilter : NearestFilter;
 
-       }
+       this.flipY = false;
+       this.generateMipmaps = false;
 
 }
 
-class CircleBufferGeometry extends BufferGeometry {
+DepthTexture.prototype = Object.create( Texture.prototype );
+DepthTexture.prototype.constructor = DepthTexture;
+DepthTexture.prototype.isDepthTexture = true;
+
+class CircleGeometry extends BufferGeometry {
 
        constructor( radius = 1, segments = 8, thetaStart = 0, thetaLength = Math.PI * 2 ) {
 
                super();
 
-               this.type = 'CircleBufferGeometry';
+               this.type = 'CircleGeometry';
 
                this.parameters = {
                        radius: radius,
@@ -28924,33 +27181,12 @@ class CircleBufferGeometry extends BufferGeometry {
 
 }
 
-class CircleGeometry extends Geometry {
-
-       constructor( radius, segments, thetaStart, thetaLength ) {
-
-               super();
-               this.type = 'CircleGeometry';
-
-               this.parameters = {
-                       radius: radius,
-                       segments: segments,
-                       thetaStart: thetaStart,
-                       thetaLength: thetaLength
-               };
-
-               this.fromBufferGeometry( new CircleBufferGeometry( radius, segments, thetaStart, thetaLength ) );
-               this.mergeVertices();
-
-       }
-
-}
-
-class CylinderBufferGeometry extends BufferGeometry {
+class CylinderGeometry extends BufferGeometry {
 
        constructor( radiusTop = 1, radiusBottom = 1, height = 1, radialSegments = 8, heightSegments = 1, openEnded = false, thetaStart = 0, thetaLength = Math.PI * 2 ) {
 
                super();
-               this.type = 'CylinderBufferGeometry';
+               this.type = 'CylinderGeometry';
 
                this.parameters = {
                        radiusTop: radiusTop,
@@ -29207,59 +27443,13 @@ class CylinderBufferGeometry extends BufferGeometry {
 
 }
 
-class CylinderGeometry extends Geometry {
-
-       constructor( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) {
-
-               super();
-               this.type = 'CylinderGeometry';
-
-               this.parameters = {
-                       radiusTop: radiusTop,
-                       radiusBottom: radiusBottom,
-                       height: height,
-                       radialSegments: radialSegments,
-                       heightSegments: heightSegments,
-                       openEnded: openEnded,
-                       thetaStart: thetaStart,
-                       thetaLength: thetaLength
-               };
-
-               this.fromBufferGeometry( new CylinderBufferGeometry( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) );
-               this.mergeVertices();
-
-       }
-
-}
-
 class ConeGeometry extends CylinderGeometry {
 
-       constructor( radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) {
-
-               super( 0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength );
-               this.type = 'ConeGeometry';
-
-               this.parameters = {
-                       radius: radius,
-                       height: height,
-                       radialSegments: radialSegments,
-                       heightSegments: heightSegments,
-                       openEnded: openEnded,
-                       thetaStart: thetaStart,
-                       thetaLength: thetaLength
-               };
-
-       }
-
-}
-
-class ConeBufferGeometry extends CylinderBufferGeometry {
-
        constructor( radius = 1, height = 1, radialSegments = 8, heightSegments = 1, openEnded = false, thetaStart = 0, thetaLength = Math.PI * 2 ) {
 
                super( 0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength );
 
-               this.type = 'ConeBufferGeometry';
+               this.type = 'ConeGeometry';
 
                this.parameters = {
                        radius: radius,
@@ -29275,13 +27465,13 @@ class ConeBufferGeometry extends CylinderBufferGeometry {
 
 }
 
-class PolyhedronBufferGeometry extends BufferGeometry {
+class PolyhedronGeometry extends BufferGeometry {
 
        constructor( vertices, indices, radius = 1, detail = 0 ) {
 
                super();
 
-               this.type = 'PolyhedronBufferGeometry';
+               this.type = 'PolyhedronGeometry';
 
                this.parameters = {
                        vertices: vertices,
@@ -29572,7 +27762,7 @@ class PolyhedronBufferGeometry extends BufferGeometry {
 
 }
 
-class DodecahedronBufferGeometry extends PolyhedronBufferGeometry {
+class DodecahedronGeometry extends PolyhedronGeometry {
 
        constructor( radius = 1, detail = 0 ) {
 
@@ -29617,22 +27807,6 @@ class DodecahedronBufferGeometry extends PolyhedronBufferGeometry {
 
                super( vertices, indices, radius, detail );
 
-               this.type = 'DodecahedronBufferGeometry';
-
-               this.parameters = {
-                       radius: radius,
-                       detail: detail
-               };
-
-       }
-
-}
-
-class DodecahedronGeometry extends Geometry {
-
-       constructor( radius, detail ) {
-
-               super();
                this.type = 'DodecahedronGeometry';
 
                this.parameters = {
@@ -29640,9 +27814,6 @@ class DodecahedronGeometry extends Geometry {
                        detail: detail
                };
 
-               this.fromBufferGeometry( new DodecahedronBufferGeometry( radius, detail ) );
-               this.mergeVertices();
-
        }
 
 }
@@ -29666,9 +27837,10 @@ class EdgesGeometry extends BufferGeometry {
 
                thresholdAngle = ( thresholdAngle !== undefined ) ? thresholdAngle : 1;
 
-               if ( geometry.isGeometry ) {
+               if ( geometry.isGeometry === true ) {
 
-                       geometry = new BufferGeometry().fromGeometry( geometry );
+                       console.error( 'THREE.EdgesGeometry no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.' );
+                       return;
 
                }
 
@@ -30686,13 +28858,13 @@ function addContour( vertices, contour ) {
  * }
  */
 
-class ExtrudeBufferGeometry extends BufferGeometry {
+class ExtrudeGeometry extends BufferGeometry {
 
        constructor( shapes, options ) {
 
                super();
 
-               this.type = 'ExtrudeBufferGeometry';
+               this.type = 'ExtrudeGeometry';
 
                this.parameters = {
                        shapes: shapes,
@@ -30835,7 +29007,7 @@ class ExtrudeBufferGeometry extends BufferGeometry {
 
                        function scalePt2( pt, vec, size ) {
 
-                               if ( ! vec ) console.error( "THREE.ExtrudeGeometry: vec does not exist" );
+                               if ( ! vec ) console.error( 'THREE.ExtrudeGeometry: vec does not exist' );
 
                                return vec.clone().multiplyScalar( size ).add( pt );
 
@@ -31441,86 +29613,7 @@ function toJSON( shapes, options, data ) {
 
 }
 
-/**
- * Creates extruded geometry from a path shape.
- *
- * parameters = {
- *
- *  curveSegments: <int>, // number of points on the curves
- *  steps: <int>, // number of points for z-side extrusions / used for subdividing segments of extrude spline too
- *  depth: <float>, // Depth to extrude the shape
- *
- *  bevelEnabled: <bool>, // turn on bevel
- *  bevelThickness: <float>, // how deep into the original shape bevel goes
- *  bevelSize: <float>, // how far from shape outline (including bevelOffset) is bevel
- *  bevelOffset: <float>, // how far from shape outline does bevel start
- *  bevelSegments: <int>, // number of bevel layers
- *
- *  extrudePath: <THREE.Curve> // curve to extrude shape along
- *
- *  UVGenerator: <Object> // object that provides UV generator functions
- *
- * }
- */
-
-class ExtrudeGeometry extends Geometry {
-
-       constructor( shapes, options ) {
-
-               super();
-
-               this.type = 'ExtrudeGeometry';
-
-               this.parameters = {
-                       shapes: shapes,
-                       options: options
-               };
-
-               this.fromBufferGeometry( new ExtrudeBufferGeometry( shapes, options ) );
-               this.mergeVertices();
-
-       }
-
-       toJSON() {
-
-               const data = super.toJSON();
-
-               const shapes = this.parameters.shapes;
-               const options = this.parameters.options;
-
-               return toJSON$1( shapes, options, data );
-
-       }
-
-}
-
-function toJSON$1( shapes, options, data ) {
-
-       data.shapes = [];
-
-       if ( Array.isArray( shapes ) ) {
-
-               for ( let i = 0, l = shapes.length; i < l; i ++ ) {
-
-                       const shape = shapes[ i ];
-
-                       data.shapes.push( shape.uuid );
-
-               }
-
-       } else {
-
-               data.shapes.push( shapes.uuid );
-
-       }
-
-       if ( options.extrudePath !== undefined ) data.options.extrudePath = options.extrudePath.toJSON();
-
-       return data;
-
-}
-
-class IcosahedronBufferGeometry extends PolyhedronBufferGeometry {
+class IcosahedronGeometry extends PolyhedronGeometry {
 
        constructor( radius = 1, detail = 0 ) {
 
@@ -31541,23 +29634,6 @@ class IcosahedronBufferGeometry extends PolyhedronBufferGeometry {
 
                super( vertices, indices, radius, detail );
 
-               this.type = 'IcosahedronBufferGeometry';
-
-               this.parameters = {
-                       radius: radius,
-                       detail: detail
-               };
-
-       }
-
-}
-
-class IcosahedronGeometry extends Geometry {
-
-       constructor( radius, detail ) {
-
-               super();
-
                this.type = 'IcosahedronGeometry';
 
                this.parameters = {
@@ -31565,20 +29641,17 @@ class IcosahedronGeometry extends Geometry {
                        detail: detail
                };
 
-               this.fromBufferGeometry( new IcosahedronBufferGeometry( radius, detail ) );
-               this.mergeVertices();
-
        }
 
 }
 
-class LatheBufferGeometry extends BufferGeometry {
+class LatheGeometry extends BufferGeometry {
 
        constructor( points, segments = 12, phiStart = 0, phiLength = Math.PI * 2 ) {
 
                super();
 
-               this.type = 'LatheBufferGeometry';
+               this.type = 'LatheGeometry';
 
                this.parameters = {
                        points: points,
@@ -31714,29 +29787,7 @@ class LatheBufferGeometry extends BufferGeometry {
 
 }
 
-class LatheGeometry extends Geometry {
-
-       constructor( points, segments, phiStart, phiLength ) {
-
-               super();
-
-               this.type = 'LatheGeometry';
-
-               this.parameters = {
-                       points: points,
-                       segments: segments,
-                       phiStart: phiStart,
-                       phiLength: phiLength
-               };
-
-               this.fromBufferGeometry( new LatheBufferGeometry( points, segments, phiStart, phiLength ) );
-               this.mergeVertices();
-
-       }
-
-}
-
-class OctahedronBufferGeometry extends PolyhedronBufferGeometry {
+class OctahedronGeometry extends PolyhedronGeometry {
 
        constructor( radius = 1, detail = 0 ) {
 
@@ -31753,23 +29804,6 @@ class OctahedronBufferGeometry extends PolyhedronBufferGeometry {
 
                super( vertices, indices, radius, detail );
 
-               this.type = 'OctahedronBufferGeometry';
-
-               this.parameters = {
-                       radius: radius,
-                       detail: detail
-               };
-
-       }
-
-}
-
-class OctahedronGeometry extends Geometry {
-
-       constructor( radius, detail ) {
-
-               super();
-
                this.type = 'OctahedronGeometry';
 
                this.parameters = {
@@ -31777,9 +29811,6 @@ class OctahedronGeometry extends Geometry {
                        detail: detail
                };
 
-               this.fromBufferGeometry( new OctahedronBufferGeometry( radius, detail ) );
-               this.mergeVertices();
-
        }
 
 }
@@ -31789,11 +29820,11 @@ class OctahedronGeometry extends Geometry {
  * based on the brilliant article by @prideout https://prideout.net/blog/old/blog/index.html@p=44.html
  */
 
-function ParametricBufferGeometry( func, slices, stacks ) {
+function ParametricGeometry( func, slices, stacks ) {
 
        BufferGeometry.call( this );
 
-       this.type = 'ParametricBufferGeometry';
+       this.type = 'ParametricGeometry';
 
        this.parameters = {
                func: func,
@@ -31908,85 +29939,16 @@ function ParametricBufferGeometry( func, slices, stacks ) {
 
 }
 
-ParametricBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
-ParametricBufferGeometry.prototype.constructor = ParametricBufferGeometry;
-
-/**
- * Parametric Surfaces Geometry
- * based on the brilliant article by @prideout https://prideout.net/blog/old/blog/index.html@p=44.html
- */
-
-function ParametricGeometry( func, slices, stacks ) {
-
-       Geometry.call( this );
-
-       this.type = 'ParametricGeometry';
-
-       this.parameters = {
-               func: func,
-               slices: slices,
-               stacks: stacks
-       };
-
-       this.fromBufferGeometry( new ParametricBufferGeometry( func, slices, stacks ) );
-       this.mergeVertices();
-
-}
-
-ParametricGeometry.prototype = Object.create( Geometry.prototype );
+ParametricGeometry.prototype = Object.create( BufferGeometry.prototype );
 ParametricGeometry.prototype.constructor = ParametricGeometry;
 
-class PlaneGeometry extends Geometry {
-
-       constructor( width, height, widthSegments, heightSegments ) {
-
-               super();
-
-               this.type = 'PlaneGeometry';
-
-               this.parameters = {
-                       width: width,
-                       height: height,
-                       widthSegments: widthSegments,
-                       heightSegments: heightSegments
-               };
-
-               this.fromBufferGeometry( new PlaneBufferGeometry( width, height, widthSegments, heightSegments ) );
-               this.mergeVertices();
-
-       }
-
-}
-
-class PolyhedronGeometry extends Geometry {
-
-       constructor( vertices, indices, radius, detail ) {
-
-               super();
-
-               this.type = 'PolyhedronGeometry';
-
-               this.parameters = {
-                       vertices: vertices,
-                       indices: indices,
-                       radius: radius,
-                       detail: detail
-               };
-
-               this.fromBufferGeometry( new PolyhedronBufferGeometry( vertices, indices, radius, detail ) );
-               this.mergeVertices();
-
-       }
-
-}
-
-class RingBufferGeometry extends BufferGeometry {
+class RingGeometry extends BufferGeometry {
 
        constructor( innerRadius = 0.5, outerRadius = 1, thetaSegments = 8, phiSegments = 1, thetaStart = 0, thetaLength = Math.PI * 2 ) {
 
                super();
 
-               this.type = 'RingBufferGeometry';
+               this.type = 'RingGeometry';
 
                this.parameters = {
                        innerRadius: innerRadius,
@@ -32085,36 +30047,12 @@ class RingBufferGeometry extends BufferGeometry {
 
 }
 
-class RingGeometry extends Geometry {
-
-       constructor( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) {
-
-               super();
-
-               this.type = 'RingGeometry';
-
-               this.parameters = {
-                       innerRadius: innerRadius,
-                       outerRadius: outerRadius,
-                       thetaSegments: thetaSegments,
-                       phiSegments: phiSegments,
-                       thetaStart: thetaStart,
-                       thetaLength: thetaLength
-               };
-
-               this.fromBufferGeometry( new RingBufferGeometry( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) );
-               this.mergeVertices();
-
-       }
-
-}
-
-class ShapeBufferGeometry extends BufferGeometry {
+class ShapeGeometry extends BufferGeometry {
 
        constructor( shapes, curveSegments = 12 ) {
 
                super();
-               this.type = 'ShapeBufferGeometry';
+               this.type = 'ShapeGeometry';
 
                this.parameters = {
                        shapes: shapes,
@@ -32240,13 +30178,13 @@ class ShapeBufferGeometry extends BufferGeometry {
 
                const shapes = this.parameters.shapes;
 
-               return toJSON$2( shapes, data );
+               return toJSON$1( shapes, data );
 
        }
 
 }
 
-function toJSON$2( shapes, data ) {
+function toJSON$1( shapes, data ) {
 
        data.shapes = [];
 
@@ -32270,73 +30208,12 @@ function toJSON$2( shapes, data ) {
 
 }
 
-class ShapeGeometry extends Geometry {
-
-       constructor( shapes, curveSegments ) {
-
-               super();
-               this.type = 'ShapeGeometry';
-
-               if ( typeof curveSegments === 'object' ) {
-
-                       console.warn( 'THREE.ShapeGeometry: Options parameter has been removed.' );
-
-                       curveSegments = curveSegments.curveSegments;
-
-               }
-
-               this.parameters = {
-                       shapes: shapes,
-                       curveSegments: curveSegments
-               };
-
-               this.fromBufferGeometry( new ShapeBufferGeometry( shapes, curveSegments ) );
-               this.mergeVertices();
-
-       }
-
-       toJSON() {
-
-               const data = Geometry.prototype.toJSON.call( this );
-
-               const shapes = this.parameters.shapes;
-
-               return toJSON$3( shapes, data );
-
-       }
-
-}
-
-function toJSON$3( shapes, data ) {
-
-       data.shapes = [];
-
-       if ( Array.isArray( shapes ) ) {
-
-               for ( let i = 0, l = shapes.length; i < l; i ++ ) {
-
-                       const shape = shapes[ i ];
-
-                       data.shapes.push( shape.uuid );
-
-               }
-
-       } else {
-
-               data.shapes.push( shapes.uuid );
-
-       }
-
-       return data;
-
-}
-
-class SphereBufferGeometry extends BufferGeometry {
+class SphereGeometry extends BufferGeometry {
 
        constructor( radius = 1, widthSegments = 8, heightSegments = 6, phiStart = 0, phiLength = Math.PI * 2, thetaStart = 0, thetaLength = Math.PI ) {
 
                super();
-               this.type = 'SphereBufferGeometry';
+               this.type = 'SphereGeometry';
 
                this.parameters = {
                        radius: radius,
@@ -32446,31 +30323,7 @@ class SphereBufferGeometry extends BufferGeometry {
 
 }
 
-class SphereGeometry extends Geometry {
-
-       constructor( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) {
-
-               super();
-               this.type = 'SphereGeometry';
-
-               this.parameters = {
-                       radius: radius,
-                       widthSegments: widthSegments,
-                       heightSegments: heightSegments,
-                       phiStart: phiStart,
-                       phiLength: phiLength,
-                       thetaStart: thetaStart,
-                       thetaLength: thetaLength
-               };
-
-               this.fromBufferGeometry( new SphereBufferGeometry( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) );
-               this.mergeVertices();
-
-       }
-
-}
-
-class TetrahedronBufferGeometry extends PolyhedronBufferGeometry {
+class TetrahedronGeometry extends PolyhedronGeometry {
 
        constructor( radius = 1, detail = 0 ) {
 
@@ -32484,22 +30337,6 @@ class TetrahedronBufferGeometry extends PolyhedronBufferGeometry {
 
                super( vertices, indices, radius, detail );
 
-               this.type = 'TetrahedronBufferGeometry';
-
-               this.parameters = {
-                       radius: radius,
-                       detail: detail
-               };
-
-       }
-
-}
-
-class TetrahedronGeometry extends Geometry {
-
-       constructor( radius, detail ) {
-
-               super();
                this.type = 'TetrahedronGeometry';
 
                this.parameters = {
@@ -32507,9 +30344,6 @@ class TetrahedronGeometry extends Geometry {
                        detail: detail
                };
 
-               this.fromBufferGeometry( new TetrahedronBufferGeometry( radius, detail ) );
-               this.mergeVertices();
-
        }
 
 }
@@ -32531,7 +30365,7 @@ class TetrahedronGeometry extends Geometry {
  * }
  */
 
-class TextBufferGeometry extends ExtrudeBufferGeometry {
+class TextGeometry extends ExtrudeGeometry {
 
        constructor( text, parameters = {} ) {
 
@@ -32558,54 +30392,18 @@ class TextBufferGeometry extends ExtrudeBufferGeometry {
 
                super( shapes, parameters );
 
-               this.type = 'TextBufferGeometry';
-
-       }
-
-}
-
-/**
- * Text = 3D Text
- *
- * parameters = {
- *  font: <THREE.Font>, // font
- *
- *  size: <float>, // size of the text
- *  height: <float>, // thickness to extrude text
- *  curveSegments: <int>, // number of points on the curves
- *
- *  bevelEnabled: <bool>, // turn on bevel
- *  bevelThickness: <float>, // how deep into text bevel goes
- *  bevelSize: <float>, // how far from text outline (including bevelOffset) is bevel
- *  bevelOffset: <float> // how far from text outline does bevel start
- * }
- */
-
-class TextGeometry extends Geometry {
-
-       constructor( text, parameters ) {
-
-               super();
                this.type = 'TextGeometry';
 
-               this.parameters = {
-                       text: text,
-                       parameters: parameters
-               };
-
-               this.fromBufferGeometry( new TextBufferGeometry( text, parameters ) );
-               this.mergeVertices();
-
        }
 
 }
 
-class TorusBufferGeometry extends BufferGeometry {
+class TorusGeometry extends BufferGeometry {
 
        constructor( radius = 1, tube = 0.4, radialSegments = 8, tubularSegments = 6, arc = Math.PI * 2 ) {
 
                super();
-               this.type = 'TorusBufferGeometry';
+               this.type = 'TorusGeometry';
 
                this.parameters = {
                        radius: radius,
@@ -32698,34 +30496,12 @@ class TorusBufferGeometry extends BufferGeometry {
 
 }
 
-class TorusGeometry extends Geometry {
-
-       constructor( radius, tube, radialSegments, tubularSegments, arc ) {
-
-               super();
-               this.type = 'TorusGeometry';
-
-               this.parameters = {
-                       radius: radius,
-                       tube: tube,
-                       radialSegments: radialSegments,
-                       tubularSegments: tubularSegments,
-                       arc: arc
-               };
-
-               this.fromBufferGeometry( new TorusBufferGeometry( radius, tube, radialSegments, tubularSegments, arc ) );
-               this.mergeVertices();
-
-       }
-
-}
-
-class TorusKnotBufferGeometry extends BufferGeometry {
+class TorusKnotGeometry extends BufferGeometry {
 
        constructor( radius = 1, tube = 0.4, tubularSegments = 64, radialSegments = 8, p = 2, q = 3 ) {
 
                super();
-               this.type = 'TorusKnotBufferGeometry';
+               this.type = 'TorusKnotGeometry';
 
                this.parameters = {
                        radius: radius,
@@ -32865,37 +30641,12 @@ class TorusKnotBufferGeometry extends BufferGeometry {
 
 }
 
-class TorusKnotGeometry extends Geometry {
-
-       constructor( radius, tube, tubularSegments, radialSegments, p, q, heightScale ) {
-
-               super();
-               this.type = 'TorusKnotGeometry';
-
-               this.parameters = {
-                       radius: radius,
-                       tube: tube,
-                       tubularSegments: tubularSegments,
-                       radialSegments: radialSegments,
-                       p: p,
-                       q: q
-               };
-
-               if ( heightScale !== undefined ) console.warn( 'THREE.TorusKnotGeometry: heightScale has been deprecated. Use .scale( x, y, z ) instead.' );
-
-               this.fromBufferGeometry( new TorusKnotBufferGeometry( radius, tube, tubularSegments, radialSegments, p, q ) );
-               this.mergeVertices();
-
-       }
-
-}
-
-class TubeBufferGeometry extends BufferGeometry {
+class TubeGeometry extends BufferGeometry {
 
        constructor( path, tubularSegments = 64, radius = 1, radialSegments = 8, closed = false ) {
 
                super();
-               this.type = 'TubeBufferGeometry';
+               this.type = 'TubeGeometry';
 
                this.parameters = {
                        path: path,
@@ -33059,80 +30810,69 @@ class TubeBufferGeometry extends BufferGeometry {
 
 }
 
-class TubeGeometry extends Geometry {
+class WireframeGeometry extends BufferGeometry {
 
-       constructor( path, tubularSegments, radius, radialSegments, closed, taper ) {
+       constructor( geometry ) {
 
                super();
-               this.type = 'TubeGeometry';
-
-               this.parameters = {
-                       path: path,
-                       tubularSegments: tubularSegments,
-                       radius: radius,
-                       radialSegments: radialSegments,
-                       closed: closed
-               };
-
-               if ( taper !== undefined ) console.warn( 'THREE.TubeGeometry: taper has been removed.' );
+               this.type = 'WireframeGeometry';
 
-               const bufferGeometry = new TubeBufferGeometry( path, tubularSegments, radius, radialSegments, closed );
+               if ( geometry.isGeometry === true ) {
 
-               // expose internals
+                       console.error( 'THREE.WireframeGeometry no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.' );
+                       return;
 
-               this.tangents = bufferGeometry.tangents;
-               this.normals = bufferGeometry.normals;
-               this.binormals = bufferGeometry.binormals;
+               }
 
-               // create geometry
+               // buffer
 
-               this.fromBufferGeometry( bufferGeometry );
-               this.mergeVertices();
+               const vertices = [];
 
-       }
+               // helper variables
 
-}
+               const edge = [ 0, 0 ], edges = {};
 
-class WireframeGeometry extends BufferGeometry {
+               const vertex = new Vector3();
 
-       constructor( geometry ) {
+               if ( geometry.index !== null ) {
 
-               super();
-               this.type = 'WireframeGeometry';
+                       // indexed BufferGeometry
 
-               // buffer
+                       const position = geometry.attributes.position;
+                       const indices = geometry.index;
+                       let groups = geometry.groups;
 
-               const vertices = [];
+                       if ( groups.length === 0 ) {
 
-               // helper variables
+                               groups = [ { start: 0, count: indices.count, materialIndex: 0 } ];
 
-               const edge = [ 0, 0 ], edges = {};
-               const keys = [ 'a', 'b', 'c' ];
+                       }
 
-               // different logic for Geometry and BufferGeometry
+                       // create a data structure that contains all eges without duplicates
 
-               if ( geometry && geometry.isGeometry ) {
+                       for ( let o = 0, ol = groups.length; o < ol; ++ o ) {
 
-                       // create a data structure that contains all edges without duplicates
+                               const group = groups[ o ];
 
-                       const faces = geometry.faces;
+                               const start = group.start;
+                               const count = group.count;
 
-                       for ( let i = 0, l = faces.length; i < l; i ++ ) {
+                               for ( let i = start, l = ( start + count ); i < l; i += 3 ) {
 
-                               const face = faces[ i ];
+                                       for ( let j = 0; j < 3; j ++ ) {
 
-                               for ( let j = 0; j < 3; j ++ ) {
+                                               const edge1 = indices.getX( i + j );
+                                               const edge2 = indices.getX( i + ( j + 1 ) % 3 );
+                                               edge[ 0 ] = Math.min( edge1, edge2 ); // sorting prevents duplicates
+                                               edge[ 1 ] = Math.max( edge1, edge2 );
 
-                                       const edge1 = face[ keys[ j ] ];
-                                       const edge2 = face[ keys[ ( j + 1 ) % 3 ] ];
-                                       edge[ 0 ] = Math.min( edge1, edge2 ); // sorting prevents duplicates
-                                       edge[ 1 ] = Math.max( edge1, edge2 );
+                                               const key = edge[ 0 ] + ',' + edge[ 1 ];
 
-                                       const key = edge[ 0 ] + ',' + edge[ 1 ];
+                                               if ( edges[ key ] === undefined ) {
 
-                                       if ( edges[ key ] === undefined ) {
+                                                       edges[ key ] = { index1: edge[ 0 ], index2: edge[ 1 ] };
 
-                                               edges[ key ] = { index1: edge[ 0 ], index2: edge[ 1 ] };
+                                               }
 
                                        }
 
@@ -33146,103 +30886,37 @@ class WireframeGeometry extends BufferGeometry {
 
                                const e = edges[ key ];
 
-                               let vertex = geometry.vertices[ e.index1 ];
+                               vertex.fromBufferAttribute( position, e.index1 );
                                vertices.push( vertex.x, vertex.y, vertex.z );
 
-                               vertex = geometry.vertices[ e.index2 ];
+                               vertex.fromBufferAttribute( position, e.index2 );
                                vertices.push( vertex.x, vertex.y, vertex.z );
 
                        }
 
-               } else if ( geometry && geometry.isBufferGeometry ) {
-
-                       const vertex = new Vector3();
-
-                       if ( geometry.index !== null ) {
-
-                               // indexed BufferGeometry
-
-                               const position = geometry.attributes.position;
-                               const indices = geometry.index;
-                               let groups = geometry.groups;
-
-                               if ( groups.length === 0 ) {
-
-                                       groups = [ { start: 0, count: indices.count, materialIndex: 0 } ];
-
-                               }
-
-                               // create a data structure that contains all eges without duplicates
-
-                               for ( let o = 0, ol = groups.length; o < ol; ++ o ) {
-
-                                       const group = groups[ o ];
-
-                                       const start = group.start;
-                                       const count = group.count;
-
-                                       for ( let i = start, l = ( start + count ); i < l; i += 3 ) {
-
-                                               for ( let j = 0; j < 3; j ++ ) {
-
-                                                       const edge1 = indices.getX( i + j );
-                                                       const edge2 = indices.getX( i + ( j + 1 ) % 3 );
-                                                       edge[ 0 ] = Math.min( edge1, edge2 ); // sorting prevents duplicates
-                                                       edge[ 1 ] = Math.max( edge1, edge2 );
-
-                                                       const key = edge[ 0 ] + ',' + edge[ 1 ];
-
-                                                       if ( edges[ key ] === undefined ) {
-
-                                                               edges[ key ] = { index1: edge[ 0 ], index2: edge[ 1 ] };
-
-                                                       }
-
-                                               }
+               } else {
 
-                                       }
+                       // non-indexed BufferGeometry
 
-                               }
+                       const position = geometry.attributes.position;
 
-                               // generate vertices
+                       for ( let i = 0, l = ( position.count / 3 ); i < l; i ++ ) {
 
-                               for ( const key in edges ) {
+                               for ( let j = 0; j < 3; j ++ ) {
 
-                                       const e = edges[ key ];
+                                       // three edges per triangle, an edge is represented as (index1, index2)
+                                       // e.g. the first triangle has the following edges: (0,1),(1,2),(2,0)
 
-                                       vertex.fromBufferAttribute( position, e.index1 );
+                                       const index1 = 3 * i + j;
+                                       vertex.fromBufferAttribute( position, index1 );
                                        vertices.push( vertex.x, vertex.y, vertex.z );
 
-                                       vertex.fromBufferAttribute( position, e.index2 );
+                                       const index2 = 3 * i + ( ( j + 1 ) % 3 );
+                                       vertex.fromBufferAttribute( position, index2 );
                                        vertices.push( vertex.x, vertex.y, vertex.z );
 
                                }
 
-                       } else {
-
-                               // non-indexed BufferGeometry
-
-                               const position = geometry.attributes.position;
-
-                               for ( let i = 0, l = ( position.count / 3 ); i < l; i ++ ) {
-
-                                       for ( let j = 0; j < 3; j ++ ) {
-
-                                               // three edges per triangle, an edge is represented as (index1, index2)
-                                               // e.g. the first triangle has the following edges: (0,1),(1,2),(2,0)
-
-                                               const index1 = 3 * i + j;
-                                               vertex.fromBufferAttribute( position, index1 );
-                                               vertices.push( vertex.x, vertex.y, vertex.z );
-
-                                               const index2 = 3 * i + ( ( j + 1 ) % 3 );
-                                               vertex.fromBufferAttribute( position, index2 );
-                                               vertices.push( vertex.x, vertex.y, vertex.z );
-
-                                       }
-
-                               }
-
                        }
 
                }
@@ -33258,46 +30932,46 @@ class WireframeGeometry extends BufferGeometry {
 var Geometries = /*#__PURE__*/Object.freeze({
        __proto__: null,
        BoxGeometry: BoxGeometry,
-       BoxBufferGeometry: BoxBufferGeometry,
+       BoxBufferGeometry: BoxGeometry,
        CircleGeometry: CircleGeometry,
-       CircleBufferGeometry: CircleBufferGeometry,
+       CircleBufferGeometry: CircleGeometry,
        ConeGeometry: ConeGeometry,
-       ConeBufferGeometry: ConeBufferGeometry,
+       ConeBufferGeometry: ConeGeometry,
        CylinderGeometry: CylinderGeometry,
-       CylinderBufferGeometry: CylinderBufferGeometry,
+       CylinderBufferGeometry: CylinderGeometry,
        DodecahedronGeometry: DodecahedronGeometry,
-       DodecahedronBufferGeometry: DodecahedronBufferGeometry,
+       DodecahedronBufferGeometry: DodecahedronGeometry,
        EdgesGeometry: EdgesGeometry,
        ExtrudeGeometry: ExtrudeGeometry,
-       ExtrudeBufferGeometry: ExtrudeBufferGeometry,
+       ExtrudeBufferGeometry: ExtrudeGeometry,
        IcosahedronGeometry: IcosahedronGeometry,
-       IcosahedronBufferGeometry: IcosahedronBufferGeometry,
+       IcosahedronBufferGeometry: IcosahedronGeometry,
        LatheGeometry: LatheGeometry,
-       LatheBufferGeometry: LatheBufferGeometry,
+       LatheBufferGeometry: LatheGeometry,
        OctahedronGeometry: OctahedronGeometry,
-       OctahedronBufferGeometry: OctahedronBufferGeometry,
+       OctahedronBufferGeometry: OctahedronGeometry,
        ParametricGeometry: ParametricGeometry,
-       ParametricBufferGeometry: ParametricBufferGeometry,
+       ParametricBufferGeometry: ParametricGeometry,
        PlaneGeometry: PlaneGeometry,
-       PlaneBufferGeometry: PlaneBufferGeometry,
+       PlaneBufferGeometry: PlaneGeometry,
        PolyhedronGeometry: PolyhedronGeometry,
-       PolyhedronBufferGeometry: PolyhedronBufferGeometry,
+       PolyhedronBufferGeometry: PolyhedronGeometry,
        RingGeometry: RingGeometry,
-       RingBufferGeometry: RingBufferGeometry,
+       RingBufferGeometry: RingGeometry,
        ShapeGeometry: ShapeGeometry,
-       ShapeBufferGeometry: ShapeBufferGeometry,
+       ShapeBufferGeometry: ShapeGeometry,
        SphereGeometry: SphereGeometry,
-       SphereBufferGeometry: SphereBufferGeometry,
+       SphereBufferGeometry: SphereGeometry,
        TetrahedronGeometry: TetrahedronGeometry,
-       TetrahedronBufferGeometry: TetrahedronBufferGeometry,
+       TetrahedronBufferGeometry: TetrahedronGeometry,
        TextGeometry: TextGeometry,
-       TextBufferGeometry: TextBufferGeometry,
+       TextBufferGeometry: TextGeometry,
        TorusGeometry: TorusGeometry,
-       TorusBufferGeometry: TorusBufferGeometry,
+       TorusBufferGeometry: TorusGeometry,
        TorusKnotGeometry: TorusKnotGeometry,
-       TorusKnotBufferGeometry: TorusKnotBufferGeometry,
+       TorusKnotBufferGeometry: TorusKnotGeometry,
        TubeGeometry: TubeGeometry,
-       TubeBufferGeometry: TubeBufferGeometry,
+       TubeBufferGeometry: TubeGeometry,
        WireframeGeometry: WireframeGeometry
 });
 
@@ -35233,8 +32907,8 @@ Object.assign( KeyframeTrack.prototype, {
 
                if ( factoryMethod === undefined ) {
 
-                       const message = "unsupported interpolation for " +
-                               this.ValueTypeName + " keyframe track named " + this.name;
+                       const message = 'unsupported interpolation for ' +
+                               this.ValueTypeName + ' keyframe track named ' + this.name;
 
                        if ( this.createInterpolant === undefined ) {
 
@@ -35471,7 +33145,7 @@ Object.assign( KeyframeTrack.prototype, {
 
                        // remove adjacent keyframes scheduled at the same time
 
-                       if ( time !== timeNext && ( i !== 1 || time !== time[ 0 ] ) ) {
+                       if ( time !== timeNext && ( i !== 1 || time !== times[ 0 ] ) ) {
 
                                if ( ! smoothInterpolation ) {
 
@@ -35765,12 +33439,12 @@ VectorKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prot
 
 } );
 
-function AnimationClip( name, duration, tracks, blendMode ) {
+function AnimationClip( name, duration = - 1, tracks, blendMode = NormalAnimationBlendMode ) {
 
        this.name = name;
        this.tracks = tracks;
-       this.duration = ( duration !== undefined ) ? duration : - 1;
-       this.blendMode = ( blendMode !== undefined ) ? blendMode : NormalAnimationBlendMode;
+       this.duration = duration;
+       this.blendMode = blendMode;
 
        this.uuid = MathUtils.generateUUID();
 
@@ -36852,7 +34526,6 @@ CompressedTextureLoader.prototype = Object.assign( Object.create( Loader.prototy
                const images = [];
 
                const texture = new CompressedTexture();
-               texture.image = images;
 
                const loader = new FileLoader( this.manager );
                loader.setPath( this.path );
@@ -36879,9 +34552,9 @@ CompressedTextureLoader.prototype = Object.assign( Object.create( Loader.prototy
 
                                if ( loaded === 6 ) {
 
-                                       if ( texDatas.mipmapCount === 1 )
-                                               texture.minFilter = LinearFilter;
+                                       if ( texDatas.mipmapCount === 1 ) texture.minFilter = LinearFilter;
 
+                                       texture.image = images;
                                        texture.format = texDatas.format;
                                        texture.needsUpdate = true;
 
@@ -36928,6 +34601,8 @@ CompressedTextureLoader.prototype = Object.assign( Object.create( Loader.prototy
 
                                        }
 
+                                       texture.image = images;
+
                                } else {
 
                                        texture.image.width = texDatas.width;
@@ -37144,6 +34819,18 @@ DataTextureLoader.prototype = Object.assign( Object.create( Loader.prototype ),
 
                        texture.anisotropy = texData.anisotropy !== undefined ? texData.anisotropy : 1;
 
+                       if ( texData.encoding !== undefined ) {
+
+                               texture.encoding = texData.encoding;
+
+                       }
+
+                       if ( texData.flipY !== undefined ) {
+
+                               texture.flipY = texData.flipY;
+
+                       }
+
                        if ( texData.format !== undefined ) {
 
                                texture.format = texData.format;
@@ -39652,7 +37339,7 @@ PointLight.prototype = Object.assign( Object.create( Light.prototype ), {
 
 } );
 
-function OrthographicCamera( left, right, top, bottom, near, far ) {
+function OrthographicCamera( left = - 1, right = 1, top = 1, bottom = - 1, near = 0.1, far = 2000 ) {
 
        Camera.call( this );
 
@@ -39661,13 +37348,13 @@ function OrthographicCamera( left, right, top, bottom, near, far ) {
        this.zoom = 1;
        this.view = null;
 
-       this.left = ( left !== undefined ) ? left : - 1;
-       this.right = ( right !== undefined ) ? right : 1;
-       this.top = ( top !== undefined ) ? top : 1;
-       this.bottom = ( bottom !== undefined ) ? bottom : - 1;
+       this.left = left;
+       this.right = right;
+       this.top = top;
+       this.bottom = bottom;
 
-       this.near = ( near !== undefined ) ? near : 0.1;
-       this.far = ( far !== undefined ) ? far : 2000;
+       this.near = near;
+       this.far = far;
 
        this.updateProjectionMatrix();
 
@@ -40995,7 +38682,6 @@ class ObjectLoader extends Loader {
 
                                        case 'BoxGeometry':
                                        case 'BoxBufferGeometry':
-                                       case 'CubeGeometry': // backwards compatible
 
                                                geometry = new Geometries[ data.type ](
                                                        data.width,
@@ -41732,7 +39418,7 @@ class ObjectLoader extends Loader {
 
                        case 'Line':
 
-                               object = new Line( getGeometry( data.geometry ), getMaterial( data.material ), data.mode );
+                               object = new Line( getGeometry( data.geometry ), getMaterial( data.material ) );
 
                                break;
 
@@ -42315,19 +40001,19 @@ Object.assign( ShapePath.prototype, {
 
 } );
 
-function Font( data ) {
+class Font {
 
-       this.type = 'Font';
+       constructor( data ) {
 
-       this.data = data;
+               Object.defineProperty( this, 'isFont', { value: true } );
 
-}
+               this.type = 'Font';
 
-Object.assign( Font.prototype, {
+               this.data = data;
 
-       isFont: true,
+       }
 
-       generateShapes: function ( text, size = 100 ) {
+       generateShapes( text, size = 100 ) {
 
                const shapes = [];
                const paths = createPaths( text, size, this.data );
@@ -42342,7 +40028,7 @@ Object.assign( Font.prototype, {
 
        }
 
-} );
+}
 
 function createPaths( text, size, data ) {
 
@@ -44019,7 +41705,7 @@ Object.assign( PropertyBinding, {
 
        findNode: function ( root, nodeName ) {
 
-               if ( ! nodeName || nodeName === "" || nodeName === "." || nodeName === - 1 || nodeName === root.name || nodeName === root.uuid ) {
+               if ( ! nodeName || nodeName === '' || nodeName === '.' || nodeName === - 1 || nodeName === root.name || nodeName === root.uuid ) {
 
                        return root;
 
@@ -44422,7 +42108,7 @@ Object.assign( PropertyBinding.prototype, { // prototype, continued
 
                        // access a sub element of the property array (only primitives are supported right now)
 
-                       if ( propertyName === "morphTargetInfluences" ) {
+                       if ( propertyName === 'morphTargetInfluences' ) {
 
                                // potential optimization, skip this if propertyIndex is already an integer, and convert the integer string to a true integer.
 
@@ -46551,13 +44237,13 @@ Object.assign( Raycaster.prototype, {
 
        setFromCamera: function ( coords, camera ) {
 
-               if ( ( camera && camera.isPerspectiveCamera ) ) {
+               if ( camera && camera.isPerspectiveCamera ) {
 
                        this.ray.origin.setFromMatrixPosition( camera.matrixWorld );
                        this.ray.direction.set( coords.x, coords.y, 0.5 ).unproject( camera ).sub( this.ray.origin ).normalize();
                        this.camera = camera;
 
-               } else if ( ( camera && camera.isOrthographicCamera ) ) {
+               } else if ( camera && camera.isOrthographicCamera ) {
 
                        this.ray.origin.set( coords.x, coords.y, ( camera.near + camera.far ) / ( camera.near - camera.far ) ).unproject( camera ); // set origin in plane of camera
                        this.ray.direction.set( 0, 0, - 1 ).transformDirection( camera.matrixWorld );
@@ -46565,7 +44251,7 @@ Object.assign( Raycaster.prototype, {
 
                } else {
 
-                       console.error( 'THREE.Raycaster: Unsupported camera type.' );
+                       console.error( 'THREE.Raycaster: Unsupported camera type: ' + camera.type );
 
                }
 
@@ -46751,7 +44437,7 @@ class Cylindrical {
 
 }
 
-const _vector$7 = /*@__PURE__*/ new Vector2();
+const _vector$8 = /*@__PURE__*/ new Vector2();
 
 class Box2 {
 
@@ -46789,7 +44475,7 @@ class Box2 {
 
        setFromCenterAndSize( center, size ) {
 
-               const halfSize = _vector$7.copy( size ).multiplyScalar( 0.5 );
+               const halfSize = _vector$8.copy( size ).multiplyScalar( 0.5 );
                this.min.copy( center ).sub( halfSize );
                this.max.copy( center ).add( halfSize );
 
@@ -46939,7 +44625,7 @@ class Box2 {
 
        distanceToPoint( point ) {
 
-               const clampedPoint = _vector$7.copy( point ).clamp( this.min, this.max );
+               const clampedPoint = _vector$8.copy( point ).clamp( this.min, this.max );
                return clampedPoint.sub( point ).length();
 
        }
@@ -47144,7 +44830,7 @@ ImmediateRenderObject.prototype.constructor = ImmediateRenderObject;
 
 ImmediateRenderObject.prototype.isImmediateRenderObject = true;
 
-const _vector$8 = /*@__PURE__*/ new Vector3();
+const _vector$9 = /*@__PURE__*/ new Vector3();
 
 class SpotLightHelper extends Object3D {
 
@@ -47208,9 +44894,9 @@ class SpotLightHelper extends Object3D {
 
                this.cone.scale.set( coneWidth, coneWidth, coneLength );
 
-               _vector$8.setFromMatrixPosition( this.light.target.matrixWorld );
+               _vector$9.setFromMatrixPosition( this.light.target.matrixWorld );
 
-               this.cone.lookAt( _vector$8 );
+               this.cone.lookAt( _vector$9 );
 
                if ( this.color !== undefined ) {
 
@@ -47226,7 +44912,7 @@ class SpotLightHelper extends Object3D {
 
 }
 
-const _vector$9 = /*@__PURE__*/ new Vector3();
+const _vector$a = /*@__PURE__*/ new Vector3();
 const _boneMatrix = /*@__PURE__*/ new Matrix4();
 const _matrixWorldInv = /*@__PURE__*/ new Matrix4();
 
@@ -47294,12 +44980,12 @@ class SkeletonHelper extends LineSegments {
                        if ( bone.parent && bone.parent.isBone ) {
 
                                _boneMatrix.multiplyMatrices( _matrixWorldInv, bone.matrixWorld );
-                               _vector$9.setFromMatrixPosition( _boneMatrix );
-                               position.setXYZ( j, _vector$9.x, _vector$9.y, _vector$9.z );
+                               _vector$a.setFromMatrixPosition( _boneMatrix );
+                               position.setXYZ( j, _vector$a.x, _vector$a.y, _vector$a.z );
 
                                _boneMatrix.multiplyMatrices( _matrixWorldInv, bone.parent.matrixWorld );
-                               _vector$9.setFromMatrixPosition( _boneMatrix );
-                               position.setXYZ( j + 1, _vector$9.x, _vector$9.y, _vector$9.z );
+                               _vector$a.setFromMatrixPosition( _boneMatrix );
+                               position.setXYZ( j + 1, _vector$a.x, _vector$a.y, _vector$a.z );
 
                                j += 2;
 
@@ -47340,7 +45026,7 @@ class PointLightHelper extends Mesh {
 
        constructor( light, sphereSize, color ) {
 
-               const geometry = new SphereBufferGeometry( sphereSize, 4, 2 );
+               const geometry = new SphereGeometry( sphereSize, 4, 2 );
                const material = new MeshBasicMaterial( { wireframe: true, fog: false, toneMapped: false } );
 
                super( geometry, material );
@@ -47421,7 +45107,7 @@ class PointLightHelper extends Mesh {
 
 }
 
-const _vector$a = /*@__PURE__*/ new Vector3();
+const _vector$b = /*@__PURE__*/ new Vector3();
 const _color1 = /*@__PURE__*/ new Color();
 const _color2 = /*@__PURE__*/ new Color();
 
@@ -47438,7 +45124,7 @@ class HemisphereLightHelper extends Object3D {
 
                this.color = color;
 
-               const geometry = new OctahedronBufferGeometry( size );
+               const geometry = new OctahedronGeometry( size );
                geometry.rotateY( Math.PI * 0.5 );
 
                this.material = new MeshBasicMaterial( { wireframe: true, fog: false, toneMapped: false } );
@@ -47489,7 +45175,7 @@ class HemisphereLightHelper extends Object3D {
 
                }
 
-               mesh.lookAt( _vector$a.setFromMatrixPosition( this.light.matrixWorld ).negate() );
+               mesh.lookAt( _vector$b.setFromMatrixPosition( this.light.matrixWorld ).negate() );
 
        }
 
@@ -47692,7 +45378,7 @@ class DirectionalLightHelper extends Object3D {
 
 }
 
-const _vector$b = /*@__PURE__*/ new Vector3();
+const _vector$c = /*@__PURE__*/ new Vector3();
 const _camera = /*@__PURE__*/ new Camera();
 
 /**
@@ -47868,7 +45554,7 @@ class CameraHelper extends LineSegments {
 
 function setPoint( point, pointMap, geometry, camera, x, y, z ) {
 
-       _vector$b.set( x, y, z ).unproject( camera );
+       _vector$c.set( x, y, z ).unproject( camera );
 
        const points = pointMap[ point ];
 
@@ -47878,7 +45564,7 @@ function setPoint( point, pointMap, geometry, camera, x, y, z ) {
 
                for ( let i = 0, l = points.length; i < l; i ++ ) {
 
-                       position.setXYZ( points[ i ], _vector$b.x, _vector$b.y, _vector$b.z );
+                       position.setXYZ( points[ i ], _vector$c.x, _vector$c.y, _vector$c.z );
 
                }
 
@@ -48099,7 +45785,7 @@ class ArrowHelper extends Object3D {
                        _lineGeometry = new BufferGeometry();
                        _lineGeometry.setAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 1, 0 ], 3 ) );
 
-                       _coneGeometry = new CylinderBufferGeometry( 0, 0.5, 1, 5, 1 );
+                       _coneGeometry = new CylinderGeometry( 0, 0.5, 1, 5, 1 );
                        _coneGeometry.translate( 0, - 0.5, 0 );
 
                }
@@ -48291,8 +45977,16 @@ const ENCODINGS = {
        [ GammaEncoding ]: 6
 };
 
+const backgroundMaterial = new MeshBasicMaterial( {
+       side: BackSide,
+       depthWrite: false,
+       depthTest: false,
+} );
+const backgroundBox = new Mesh( new BoxGeometry(), backgroundMaterial );
+
 const _flatCamera = /*@__PURE__*/ new OrthographicCamera();
 const { _lodPlanes, _sizeLods, _sigmas } = /*@__PURE__*/ _createPlanes();
+const _clearColor = /*@__PURE__*/ new Color();
 let _oldTarget = null;
 
 // Golden Ratio
@@ -48325,6 +46019,17 @@ const _axisDirections = [
  * interpolate diffuse lighting while limiting sampling computation.
  */
 
+function convertLinearToRGBE( color ) {
+
+       const maxComponent = Math.max( color.r, color.g, color.b );
+       const fExp = Math.min( Math.max( Math.ceil( Math.log2( maxComponent ) ), - 128.0 ), 127.0 );
+       color.multiplyScalar( Math.pow( 2.0, - fExp ) );
+
+       const alpha = ( fExp + 128.0 ) / 255.0;
+       return alpha;
+
+}
+
 class PMREMGenerator {
 
        constructor( renderer ) {
@@ -48496,28 +46201,41 @@ class PMREMGenerator {
                const forwardSign = [ 1, 1, 1, - 1, - 1, - 1 ];
                const renderer = this._renderer;
 
+               const originalAutoClear = renderer.autoClear;
                const outputEncoding = renderer.outputEncoding;
                const toneMapping = renderer.toneMapping;
-               const clearColor = renderer.getClearColor();
-               const clearAlpha = renderer.getClearAlpha();
+               renderer.getClearColor( _clearColor );
 
                renderer.toneMapping = NoToneMapping;
                renderer.outputEncoding = LinearEncoding;
+               renderer.autoClear = false;
+
+               let useSolidColor = false;
+               const background = scene.background;
+               if ( background ) {
 
-               let background = scene.background;
-               if ( background && background.isColor ) {
+                       if ( background.isColor ) {
 
-                       background.convertSRGBToLinear();
-                       // Convert linear to RGBE
-                       const maxComponent = Math.max( background.r, background.g, background.b );
-                       const fExp = Math.min( Math.max( Math.ceil( Math.log2( maxComponent ) ), - 128.0 ), 127.0 );
-                       background = background.multiplyScalar( Math.pow( 2.0, - fExp ) );
-                       const alpha = ( fExp + 128.0 ) / 255.0;
-                       renderer.setClearColor( background, alpha );
-                       scene.background = null;
+                               backgroundMaterial.color.copy( background ).convertSRGBToLinear();
+                               scene.background = null;
+
+                               const alpha = convertLinearToRGBE( backgroundMaterial.color );
+                               backgroundMaterial.opacity = alpha;
+                               useSolidColor = true;
+
+                       }
+
+               } else {
+
+                       backgroundMaterial.color.copy( _clearColor ).convertSRGBToLinear();
+
+                       const alpha = convertLinearToRGBE( backgroundMaterial.color );
+                       backgroundMaterial.opacity = alpha;
+                       useSolidColor = true;
 
                }
 
+
                for ( let i = 0; i < 6; i ++ ) {
 
                        const col = i % 3;
@@ -48541,13 +46259,20 @@ class PMREMGenerator {
                        _setViewport( cubeUVRenderTarget,
                                col * SIZE_MAX, i > 2 ? SIZE_MAX : 0, SIZE_MAX, SIZE_MAX );
                        renderer.setRenderTarget( cubeUVRenderTarget );
+
+                       if ( useSolidColor ) {
+
+                               renderer.render( backgroundBox, cubeCamera );
+
+                       }
+
                        renderer.render( scene, cubeCamera );
 
                }
 
                renderer.toneMapping = toneMapping;
                renderer.outputEncoding = outputEncoding;
-               renderer.setClearColor( clearColor, clearAlpha );
+               renderer.autoClear = originalAutoClear;
 
        }
 
@@ -49367,51 +47092,6 @@ Curve.create = function ( construct, getPoint ) {
 
 //
 
-Object.assign( CurvePath.prototype, {
-
-       createPointsGeometry: function ( divisions ) {
-
-               console.warn( 'THREE.CurvePath: .createPointsGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.' );
-
-               // generate geometry from path points (for Line or Points objects)
-
-               const pts = this.getPoints( divisions );
-               return this.createGeometry( pts );
-
-       },
-
-       createSpacedPointsGeometry: function ( divisions ) {
-
-               console.warn( 'THREE.CurvePath: .createSpacedPointsGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.' );
-
-               // generate geometry from equidistant sampling along the path
-
-               const pts = this.getSpacedPoints( divisions );
-               return this.createGeometry( pts );
-
-       },
-
-       createGeometry: function ( points ) {
-
-               console.warn( 'THREE.CurvePath: .createGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.' );
-
-               const geometry = new Geometry();
-
-               for ( let i = 0, l = points.length; i < l; i ++ ) {
-
-                       const point = points[ i ];
-                       geometry.vertices.push( new Vector3( point.x, point.y, point.z || 0 ) );
-
-               }
-
-               return geometry;
-
-       }
-
-} );
-
-//
-
 Object.assign( Path.prototype, {
 
        fromPoints: function ( points ) {
@@ -49686,7 +47366,7 @@ Object.assign( Matrix3.prototype, {
 
        flattenToArrayOffset: function ( array, offset ) {
 
-               console.warn( "THREE.Matrix3: .flattenToArrayOffset() has been deprecated. Use .toArray() instead." );
+               console.warn( 'THREE.Matrix3: .flattenToArrayOffset() has been deprecated. Use .toArray() instead.' );
                return this.toArray( array, offset );
 
        },
@@ -49731,7 +47411,7 @@ Object.assign( Matrix4.prototype, {
        },
        flattenToArrayOffset: function ( array, offset ) {
 
-               console.warn( "THREE.Matrix4: .flattenToArrayOffset() has been deprecated. Use .toArray() instead." );
+               console.warn( 'THREE.Matrix4: .flattenToArrayOffset() has been deprecated. Use .toArray() instead.' );
                return this.toArray( array, offset );
 
        },
@@ -50053,27 +47733,6 @@ Object.assign( Vector4.prototype, {
 
 //
 
-Object.assign( Geometry.prototype, {
-
-       computeTangents: function () {
-
-               console.error( 'THREE.Geometry: .computeTangents() has been removed.' );
-
-       },
-       computeLineDistances: function () {
-
-               console.error( 'THREE.Geometry: .computeLineDistances() has been removed. Use THREE.Line.computeLineDistances() instead.' );
-
-       },
-       applyMatrix: function ( matrix ) {
-
-               console.warn( 'THREE.Geometry: .applyMatrix() has been renamed to .applyMatrix4().' );
-               return this.applyMatrix4( matrix );
-
-       }
-
-} );
-
 Object.assign( Object3D.prototype, {
 
        getChildByName: function ( name ) {
@@ -50221,8 +47880,8 @@ Object.defineProperty( Curve.prototype, '__arcLengthDivisions', {
 
 PerspectiveCamera.prototype.setLens = function ( focalLength, filmGauge ) {
 
-       console.warn( "THREE.PerspectiveCamera.setLens is deprecated. " +
-                       "Use .setFocalLength and .filmGauge for a photographic setup." );
+       console.warn( 'THREE.PerspectiveCamera.setLens is deprecated. ' +
+                       'Use .setFocalLength and .filmGauge for a photographic setup.' );
 
        if ( filmGauge !== undefined ) this.filmGauge = filmGauge;
        this.setFocalLength( focalLength );
@@ -50433,11 +48092,6 @@ Object.assign( BufferGeometry.prototype, {
                console.warn( 'THREE.BufferGeometry: .clearDrawCalls() is now .clearGroups().' );
                this.clearGroups();
 
-       },
-       computeTangents: function () {
-
-               console.warn( 'THREE.BufferGeometry: .computeTangents() has been removed.' );
-
        },
        computeOffsets: function () {
 
@@ -50555,23 +48209,23 @@ Object.assign( InterleavedBuffer.prototype, {
 
 //
 
-Object.assign( ExtrudeBufferGeometry.prototype, {
+Object.assign( ExtrudeGeometry.prototype, {
 
        getArrays: function () {
 
-               console.error( 'THREE.ExtrudeBufferGeometry: .getArrays() has been removed.' );
+               console.error( 'THREE.ExtrudeGeometry: .getArrays() has been removed.' );
 
        },
 
        addShapeList: function () {
 
-               console.error( 'THREE.ExtrudeBufferGeometry: .addShapeList() has been removed.' );
+               console.error( 'THREE.ExtrudeGeometry: .addShapeList() has been removed.' );
 
        },
 
        addShape: function () {
 
-               console.error( 'THREE.ExtrudeBufferGeometry: .addShape() has been removed.' );
+               console.error( 'THREE.ExtrudeGeometry: .addShape() has been removed.' );
 
        }
 
@@ -51369,4 +49023,18 @@ if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) {
 
 }
 
-export { ACESFilmicToneMapping, AddEquation, AddOperation, AdditiveAnimationBlendMode, AdditiveBlending, AlphaFormat, AlwaysDepth, AlwaysStencilFunc, AmbientLight, AmbientLightProbe, AnimationClip, AnimationLoader, AnimationMixer, AnimationObjectGroup, AnimationUtils, ArcCurve, ArrayCamera, ArrowHelper, Audio, AudioAnalyser, AudioContext, AudioListener, AudioLoader, AxesHelper, AxisHelper, BackSide, BasicDepthPacking, BasicShadowMap, BinaryTextureLoader, Bone, BooleanKeyframeTrack, BoundingBoxHelper, Box2, Box3, Box3Helper, BoxBufferGeometry, BoxGeometry, BoxHelper, BufferAttribute, BufferGeometry, BufferGeometryLoader, ByteType, Cache, Camera, CameraHelper, CanvasRenderer, CanvasTexture, CatmullRomCurve3, CineonToneMapping, CircleBufferGeometry, CircleGeometry, ClampToEdgeWrapping, Clock, ClosedSplineCurve3, Color, ColorKeyframeTrack, CompressedTexture, CompressedTextureLoader, ConeBufferGeometry, ConeGeometry, CubeCamera, BoxGeometry as CubeGeometry, CubeReflectionMapping, CubeRefractionMapping, CubeTexture, CubeTextureLoader, CubeUVReflectionMapping, CubeUVRefractionMapping, CubicBezierCurve, CubicBezierCurve3, CubicInterpolant, CullFaceBack, CullFaceFront, CullFaceFrontBack, CullFaceNone, Curve, CurvePath, CustomBlending, CustomToneMapping, CylinderBufferGeometry, CylinderGeometry, Cylindrical, DataTexture, DataTexture2DArray, DataTexture3D, DataTextureLoader, DataUtils, DecrementStencilOp, DecrementWrapStencilOp, DefaultLoadingManager, DepthFormat, DepthStencilFormat, DepthTexture, DirectionalLight, DirectionalLightHelper, DiscreteInterpolant, DodecahedronBufferGeometry, DodecahedronGeometry, DoubleSide, DstAlphaFactor, DstColorFactor, DynamicBufferAttribute, DynamicCopyUsage, DynamicDrawUsage, DynamicReadUsage, EdgesGeometry, EdgesHelper, EllipseCurve, EqualDepth, EqualStencilFunc, EquirectangularReflectionMapping, EquirectangularRefractionMapping, Euler, EventDispatcher, ExtrudeBufferGeometry, ExtrudeGeometry, Face3, Face4, FaceColors, FileLoader, FlatShading, Float16BufferAttribute, Float32Attribute, Float32BufferAttribute, Float64Attribute, Float64BufferAttribute, FloatType, Fog, FogExp2, Font, FontLoader, FrontSide, Frustum, GLBufferAttribute, GLSL1, GLSL3, GammaEncoding, Geometry, GeometryUtils, GreaterDepth, GreaterEqualDepth, GreaterEqualStencilFunc, GreaterStencilFunc, GridHelper, Group, HalfFloatType, HemisphereLight, HemisphereLightHelper, HemisphereLightProbe, IcosahedronBufferGeometry, IcosahedronGeometry, ImageBitmapLoader, ImageLoader, ImageUtils, ImmediateRenderObject, IncrementStencilOp, IncrementWrapStencilOp, InstancedBufferAttribute, InstancedBufferGeometry, InstancedInterleavedBuffer, InstancedMesh, Int16Attribute, Int16BufferAttribute, Int32Attribute, Int32BufferAttribute, Int8Attribute, Int8BufferAttribute, IntType, InterleavedBuffer, InterleavedBufferAttribute, Interpolant, InterpolateDiscrete, InterpolateLinear, InterpolateSmooth, InvertStencilOp, JSONLoader, KeepStencilOp, KeyframeTrack, LOD, LatheBufferGeometry, LatheGeometry, Layers, LensFlare, LessDepth, LessEqualDepth, LessEqualStencilFunc, LessStencilFunc, Light, LightProbe, Line, Line3, LineBasicMaterial, LineCurve, LineCurve3, LineDashedMaterial, LineLoop, LinePieces, LineSegments, LineStrip, LinearEncoding, LinearFilter, LinearInterpolant, LinearMipMapLinearFilter, LinearMipMapNearestFilter, LinearMipmapLinearFilter, LinearMipmapNearestFilter, LinearToneMapping, Loader, LoaderUtils, LoadingManager, LogLuvEncoding, LoopOnce, LoopPingPong, LoopRepeat, LuminanceAlphaFormat, LuminanceFormat, MOUSE, Material, MaterialLoader, MathUtils as Math, MathUtils, Matrix3, Matrix4, MaxEquation, Mesh, MeshBasicMaterial, MeshDepthMaterial, MeshDistanceMaterial, MeshFaceMaterial, MeshLambertMaterial, MeshMatcapMaterial, MeshNormalMaterial, MeshPhongMaterial, MeshPhysicalMaterial, MeshStandardMaterial, MeshToonMaterial, MinEquation, MirroredRepeatWrapping, MixOperation, MultiMaterial, MultiplyBlending, MultiplyOperation, NearestFilter, NearestMipMapLinearFilter, NearestMipMapNearestFilter, NearestMipmapLinearFilter, NearestMipmapNearestFilter, NeverDepth, NeverStencilFunc, NoBlending, NoColors, NoToneMapping, NormalAnimationBlendMode, NormalBlending, NotEqualDepth, NotEqualStencilFunc, NumberKeyframeTrack, Object3D, ObjectLoader, ObjectSpaceNormalMap, OctahedronBufferGeometry, OctahedronGeometry, OneFactor, OneMinusDstAlphaFactor, OneMinusDstColorFactor, OneMinusSrcAlphaFactor, OneMinusSrcColorFactor, OrthographicCamera, PCFShadowMap, PCFSoftShadowMap, PMREMGenerator, ParametricBufferGeometry, ParametricGeometry, Particle, ParticleBasicMaterial, ParticleSystem, ParticleSystemMaterial, Path, PerspectiveCamera, Plane, PlaneBufferGeometry, PlaneGeometry, PlaneHelper, PointCloud, PointCloudMaterial, PointLight, PointLightHelper, Points, PointsMaterial, PolarGridHelper, PolyhedronBufferGeometry, PolyhedronGeometry, PositionalAudio, PropertyBinding, PropertyMixer, QuadraticBezierCurve, QuadraticBezierCurve3, Quaternion, QuaternionKeyframeTrack, QuaternionLinearInterpolant, REVISION, RGBADepthPacking, RGBAFormat, RGBAIntegerFormat, RGBA_ASTC_10x10_Format, RGBA_ASTC_10x5_Format, RGBA_ASTC_10x6_Format, RGBA_ASTC_10x8_Format, RGBA_ASTC_12x10_Format, RGBA_ASTC_12x12_Format, RGBA_ASTC_4x4_Format, RGBA_ASTC_5x4_Format, RGBA_ASTC_5x5_Format, RGBA_ASTC_6x5_Format, RGBA_ASTC_6x6_Format, RGBA_ASTC_8x5_Format, RGBA_ASTC_8x6_Format, RGBA_ASTC_8x8_Format, RGBA_BPTC_Format, RGBA_ETC2_EAC_Format, RGBA_PVRTC_2BPPV1_Format, RGBA_PVRTC_4BPPV1_Format, RGBA_S3TC_DXT1_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT5_Format, RGBDEncoding, RGBEEncoding, RGBEFormat, RGBFormat, RGBIntegerFormat, RGBM16Encoding, RGBM7Encoding, RGB_ETC1_Format, RGB_ETC2_Format, RGB_PVRTC_2BPPV1_Format, RGB_PVRTC_4BPPV1_Format, RGB_S3TC_DXT1_Format, RGFormat, RGIntegerFormat, RawShaderMaterial, Ray, Raycaster, RectAreaLight, RedFormat, RedIntegerFormat, ReinhardToneMapping, RepeatWrapping, ReplaceStencilOp, ReverseSubtractEquation, RingBufferGeometry, RingGeometry, SRGB8_ALPHA8_ASTC_10x10_Format, SRGB8_ALPHA8_ASTC_10x5_Format, SRGB8_ALPHA8_ASTC_10x6_Format, SRGB8_ALPHA8_ASTC_10x8_Format, SRGB8_ALPHA8_ASTC_12x10_Format, SRGB8_ALPHA8_ASTC_12x12_Format, SRGB8_ALPHA8_ASTC_4x4_Format, SRGB8_ALPHA8_ASTC_5x4_Format, SRGB8_ALPHA8_ASTC_5x5_Format, SRGB8_ALPHA8_ASTC_6x5_Format, SRGB8_ALPHA8_ASTC_6x6_Format, SRGB8_ALPHA8_ASTC_8x5_Format, SRGB8_ALPHA8_ASTC_8x6_Format, SRGB8_ALPHA8_ASTC_8x8_Format, Scene, SceneUtils, ShaderChunk, ShaderLib, ShaderMaterial, ShadowMaterial, Shape, ShapeBufferGeometry, ShapeGeometry, ShapePath, ShapeUtils, ShortType, Skeleton, SkeletonHelper, SkinnedMesh, SmoothShading, Sphere, SphereBufferGeometry, SphereGeometry, Spherical, SphericalHarmonics3, Spline, SplineCurve, SplineCurve3, SpotLight, SpotLightHelper, Sprite, SpriteMaterial, SrcAlphaFactor, SrcAlphaSaturateFactor, SrcColorFactor, StaticCopyUsage, StaticDrawUsage, StaticReadUsage, StereoCamera, StreamCopyUsage, StreamDrawUsage, StreamReadUsage, StringKeyframeTrack, SubtractEquation, SubtractiveBlending, TOUCH, TangentSpaceNormalMap, TetrahedronBufferGeometry, TetrahedronGeometry, TextBufferGeometry, TextGeometry, Texture, TextureLoader, TorusBufferGeometry, TorusGeometry, TorusKnotBufferGeometry, TorusKnotGeometry, Triangle, TriangleFanDrawMode, TriangleStripDrawMode, TrianglesDrawMode, TubeBufferGeometry, TubeGeometry, UVMapping, Uint16Attribute, Uint16BufferAttribute, Uint32Attribute, Uint32BufferAttribute, Uint8Attribute, Uint8BufferAttribute, Uint8ClampedAttribute, Uint8ClampedBufferAttribute, Uniform, UniformsLib, UniformsUtils, UnsignedByteType, UnsignedInt248Type, UnsignedIntType, UnsignedShort4444Type, UnsignedShort5551Type, UnsignedShort565Type, UnsignedShortType, VSMShadowMap, Vector2, Vector3, Vector4, VectorKeyframeTrack, Vertex, VertexColors, VideoTexture, WebGL1Renderer, WebGLCubeRenderTarget, WebGLMultisampleRenderTarget, WebGLRenderTarget, WebGLRenderTargetCube, WebGLRenderer, WebGLUtils, WireframeGeometry, WireframeHelper, WrapAroundEnding, XHRLoader, ZeroCurvatureEnding, ZeroFactor, ZeroSlopeEnding, ZeroStencilOp, sRGBEncoding };
+if ( typeof window !== 'undefined' ) {
+
+       if ( window.__THREE__ ) {
+
+               console.warn( 'WARNING: Multiple instances of Three.js being imported.' );
+
+       } else {
+
+               window.__THREE__ = REVISION;
+
+       }
+
+}
+
+export { ACESFilmicToneMapping, AddEquation, AddOperation, AdditiveAnimationBlendMode, AdditiveBlending, AlphaFormat, AlwaysDepth, AlwaysStencilFunc, AmbientLight, AmbientLightProbe, AnimationClip, AnimationLoader, AnimationMixer, AnimationObjectGroup, AnimationUtils, ArcCurve, ArrayCamera, ArrowHelper, Audio, AudioAnalyser, AudioContext, AudioListener, AudioLoader, AxesHelper, AxisHelper, BackSide, BasicDepthPacking, BasicShadowMap, BinaryTextureLoader, Bone, BooleanKeyframeTrack, BoundingBoxHelper, Box2, Box3, Box3Helper, BoxGeometry as BoxBufferGeometry, BoxGeometry, BoxHelper, BufferAttribute, BufferGeometry, BufferGeometryLoader, ByteType, Cache, Camera, CameraHelper, CanvasRenderer, CanvasTexture, CatmullRomCurve3, CineonToneMapping, CircleGeometry as CircleBufferGeometry, CircleGeometry, ClampToEdgeWrapping, Clock, ClosedSplineCurve3, Color, ColorKeyframeTrack, CompressedTexture, CompressedTextureLoader, ConeGeometry as ConeBufferGeometry, ConeGeometry, CubeCamera, CubeReflectionMapping, CubeRefractionMapping, CubeTexture, CubeTextureLoader, CubeUVReflectionMapping, CubeUVRefractionMapping, CubicBezierCurve, CubicBezierCurve3, CubicInterpolant, CullFaceBack, CullFaceFront, CullFaceFrontBack, CullFaceNone, Curve, CurvePath, CustomBlending, CustomToneMapping, CylinderGeometry as CylinderBufferGeometry, CylinderGeometry, Cylindrical, DataTexture, DataTexture2DArray, DataTexture3D, DataTextureLoader, DataUtils, DecrementStencilOp, DecrementWrapStencilOp, DefaultLoadingManager, DepthFormat, DepthStencilFormat, DepthTexture, DirectionalLight, DirectionalLightHelper, DiscreteInterpolant, DodecahedronGeometry as DodecahedronBufferGeometry, DodecahedronGeometry, DoubleSide, DstAlphaFactor, DstColorFactor, DynamicBufferAttribute, DynamicCopyUsage, DynamicDrawUsage, DynamicReadUsage, EdgesGeometry, EdgesHelper, EllipseCurve, EqualDepth, EqualStencilFunc, EquirectangularReflectionMapping, EquirectangularRefractionMapping, Euler, EventDispatcher, ExtrudeGeometry as ExtrudeBufferGeometry, ExtrudeGeometry, Face3, Face4, FaceColors, FileLoader, FlatShading, Float16BufferAttribute, Float32Attribute, Float32BufferAttribute, Float64Attribute, Float64BufferAttribute, FloatType, Fog, FogExp2, Font, FontLoader, FrontSide, Frustum, GLBufferAttribute, GLSL1, GLSL3, GammaEncoding, GeometryUtils, GreaterDepth, GreaterEqualDepth, GreaterEqualStencilFunc, GreaterStencilFunc, GridHelper, Group, HalfFloatType, HemisphereLight, HemisphereLightHelper, HemisphereLightProbe, IcosahedronGeometry as IcosahedronBufferGeometry, IcosahedronGeometry, ImageBitmapLoader, ImageLoader, ImageUtils, ImmediateRenderObject, IncrementStencilOp, IncrementWrapStencilOp, InstancedBufferAttribute, InstancedBufferGeometry, InstancedInterleavedBuffer, InstancedMesh, Int16Attribute, Int16BufferAttribute, Int32Attribute, Int32BufferAttribute, Int8Attribute, Int8BufferAttribute, IntType, InterleavedBuffer, InterleavedBufferAttribute, Interpolant, InterpolateDiscrete, InterpolateLinear, InterpolateSmooth, InvertStencilOp, JSONLoader, KeepStencilOp, KeyframeTrack, LOD, LatheGeometry as LatheBufferGeometry, LatheGeometry, Layers, LensFlare, LessDepth, LessEqualDepth, LessEqualStencilFunc, LessStencilFunc, Light, LightProbe, Line, Line3, LineBasicMaterial, LineCurve, LineCurve3, LineDashedMaterial, LineLoop, LinePieces, LineSegments, LineStrip, LinearEncoding, LinearFilter, LinearInterpolant, LinearMipMapLinearFilter, LinearMipMapNearestFilter, LinearMipmapLinearFilter, LinearMipmapNearestFilter, LinearToneMapping, Loader, LoaderUtils, LoadingManager, LogLuvEncoding, LoopOnce, LoopPingPong, LoopRepeat, LuminanceAlphaFormat, LuminanceFormat, MOUSE, Material, MaterialLoader, MathUtils as Math, MathUtils, Matrix3, Matrix4, MaxEquation, Mesh, MeshBasicMaterial, MeshDepthMaterial, MeshDistanceMaterial, MeshFaceMaterial, MeshLambertMaterial, MeshMatcapMaterial, MeshNormalMaterial, MeshPhongMaterial, MeshPhysicalMaterial, MeshStandardMaterial, MeshToonMaterial, MinEquation, MirroredRepeatWrapping, MixOperation, MultiMaterial, MultiplyBlending, MultiplyOperation, NearestFilter, NearestMipMapLinearFilter, NearestMipMapNearestFilter, NearestMipmapLinearFilter, NearestMipmapNearestFilter, NeverDepth, NeverStencilFunc, NoBlending, NoColors, NoToneMapping, NormalAnimationBlendMode, NormalBlending, NotEqualDepth, NotEqualStencilFunc, NumberKeyframeTrack, Object3D, ObjectLoader, ObjectSpaceNormalMap, OctahedronGeometry as OctahedronBufferGeometry, OctahedronGeometry, OneFactor, OneMinusDstAlphaFactor, OneMinusDstColorFactor, OneMinusSrcAlphaFactor, OneMinusSrcColorFactor, OrthographicCamera, PCFShadowMap, PCFSoftShadowMap, PMREMGenerator, ParametricGeometry as ParametricBufferGeometry, ParametricGeometry, Particle, ParticleBasicMaterial, ParticleSystem, ParticleSystemMaterial, Path, PerspectiveCamera, Plane, PlaneGeometry as PlaneBufferGeometry, PlaneGeometry, PlaneHelper, PointCloud, PointCloudMaterial, PointLight, PointLightHelper, Points, PointsMaterial, PolarGridHelper, PolyhedronGeometry as PolyhedronBufferGeometry, PolyhedronGeometry, PositionalAudio, PropertyBinding, PropertyMixer, QuadraticBezierCurve, QuadraticBezierCurve3, Quaternion, QuaternionKeyframeTrack, QuaternionLinearInterpolant, REVISION, RGBADepthPacking, RGBAFormat, RGBAIntegerFormat, RGBA_ASTC_10x10_Format, RGBA_ASTC_10x5_Format, RGBA_ASTC_10x6_Format, RGBA_ASTC_10x8_Format, RGBA_ASTC_12x10_Format, RGBA_ASTC_12x12_Format, RGBA_ASTC_4x4_Format, RGBA_ASTC_5x4_Format, RGBA_ASTC_5x5_Format, RGBA_ASTC_6x5_Format, RGBA_ASTC_6x6_Format, RGBA_ASTC_8x5_Format, RGBA_ASTC_8x6_Format, RGBA_ASTC_8x8_Format, RGBA_BPTC_Format, RGBA_ETC2_EAC_Format, RGBA_PVRTC_2BPPV1_Format, RGBA_PVRTC_4BPPV1_Format, RGBA_S3TC_DXT1_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT5_Format, RGBDEncoding, RGBEEncoding, RGBEFormat, RGBFormat, RGBIntegerFormat, RGBM16Encoding, RGBM7Encoding, RGB_ETC1_Format, RGB_ETC2_Format, RGB_PVRTC_2BPPV1_Format, RGB_PVRTC_4BPPV1_Format, RGB_S3TC_DXT1_Format, RGFormat, RGIntegerFormat, RawShaderMaterial, Ray, Raycaster, RectAreaLight, RedFormat, RedIntegerFormat, ReinhardToneMapping, RepeatWrapping, ReplaceStencilOp, ReverseSubtractEquation, RingGeometry as RingBufferGeometry, RingGeometry, SRGB8_ALPHA8_ASTC_10x10_Format, SRGB8_ALPHA8_ASTC_10x5_Format, SRGB8_ALPHA8_ASTC_10x6_Format, SRGB8_ALPHA8_ASTC_10x8_Format, SRGB8_ALPHA8_ASTC_12x10_Format, SRGB8_ALPHA8_ASTC_12x12_Format, SRGB8_ALPHA8_ASTC_4x4_Format, SRGB8_ALPHA8_ASTC_5x4_Format, SRGB8_ALPHA8_ASTC_5x5_Format, SRGB8_ALPHA8_ASTC_6x5_Format, SRGB8_ALPHA8_ASTC_6x6_Format, SRGB8_ALPHA8_ASTC_8x5_Format, SRGB8_ALPHA8_ASTC_8x6_Format, SRGB8_ALPHA8_ASTC_8x8_Format, Scene, SceneUtils, ShaderChunk, ShaderLib, ShaderMaterial, ShadowMaterial, Shape, ShapeGeometry as ShapeBufferGeometry, ShapeGeometry, ShapePath, ShapeUtils, ShortType, Skeleton, SkeletonHelper, SkinnedMesh, SmoothShading, Sphere, SphereGeometry as SphereBufferGeometry, SphereGeometry, Spherical, SphericalHarmonics3, Spline, SplineCurve, SplineCurve3, SpotLight, SpotLightHelper, Sprite, SpriteMaterial, SrcAlphaFactor, SrcAlphaSaturateFactor, SrcColorFactor, StaticCopyUsage, StaticDrawUsage, StaticReadUsage, StereoCamera, StreamCopyUsage, StreamDrawUsage, StreamReadUsage, StringKeyframeTrack, SubtractEquation, SubtractiveBlending, TOUCH, TangentSpaceNormalMap, TetrahedronGeometry as TetrahedronBufferGeometry, TetrahedronGeometry, TextGeometry as TextBufferGeometry, TextGeometry, Texture, TextureLoader, TorusGeometry as TorusBufferGeometry, TorusGeometry, TorusKnotGeometry as TorusKnotBufferGeometry, TorusKnotGeometry, Triangle, TriangleFanDrawMode, TriangleStripDrawMode, TrianglesDrawMode, TubeGeometry as TubeBufferGeometry, TubeGeometry, UVMapping, Uint16Attribute, Uint16BufferAttribute, Uint32Attribute, Uint32BufferAttribute, Uint8Attribute, Uint8BufferAttribute, Uint8ClampedAttribute, Uint8ClampedBufferAttribute, Uniform, UniformsLib, UniformsUtils, UnsignedByteType, UnsignedInt248Type, UnsignedIntType, UnsignedShort4444Type, UnsignedShort5551Type, UnsignedShort565Type, UnsignedShortType, VSMShadowMap, Vector2, Vector3, Vector4, VectorKeyframeTrack, Vertex, VertexColors, VideoTexture, WebGL1Renderer, WebGLCubeRenderTarget, WebGLMultisampleRenderTarget, WebGLRenderTarget, WebGLRenderTargetCube, WebGLRenderer, WebGLUtils, WireframeGeometry, WireframeHelper, WrapAroundEnding, XHRLoader, ZeroCurvatureEnding, ZeroFactor, ZeroSlopeEnding, ZeroStencilOp, sRGBEncoding };