diff --git a/README.md b/README.md
index fd46e14..5f55853 100644
--- a/README.md
+++ b/README.md
@@ -2,12 +2,10 @@
A 3D procedural skyscraper generator with shaders in Three.js.
-## Running
+## Running on local
-Run using `serve.sh`.
+Run using `python3 -m http.server` or with your favourite static site server tool.
## Requirements
-Working internet connection, Python, a WebGL2 capable browser
-
-Note: make sure broswer is updated and use it preferably in incognito mode if making changes to files (files serverd by python server are cached by default is some Python versions).
+Working internet connection, Python, a modern browser
diff --git a/index.html b/index.html
index 129a057..7e83e2b 100644
--- a/index.html
+++ b/index.html
@@ -1,15 +1,15 @@
-
-
- My first three.js app
-
-
-
-
-
-
-
-
-
\ No newline at end of file
+
+
+
+ My first three.js app
+
+
+
+
+
+
+
+
diff --git a/lib/orbitcontrols.js b/lib/orbitcontrols.js
new file mode 100644
index 0000000..0214546
--- /dev/null
+++ b/lib/orbitcontrols.js
@@ -0,0 +1,1396 @@
+import {
+ EventDispatcher,
+ MOUSE,
+ Quaternion,
+ Spherical,
+ TOUCH,
+ Vector2,
+ Vector3,
+ Plane,
+ Ray,
+ MathUtils
+} from './three.js';
+
+// OrbitControls 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
+
+const _changeEvent = { type: 'change' };
+const _startEvent = { type: 'start' };
+const _endEvent = { type: 'end' };
+const _ray = new Ray();
+const _plane = new Plane();
+const TILT_LIMIT = Math.cos( 70 * MathUtils.DEG2RAD );
+
+class OrbitControls extends EventDispatcher {
+
+ constructor( object, domElement ) {
+
+ super();
+
+ this.object = object;
+ this.domElement = domElement;
+ this.domElement.style.touchAction = 'none'; // disable touch scroll
+
+ // Set to false to disable this control
+ this.enabled = true;
+
+ // "target" sets the location of focus, where the object orbits around
+ this.target = new 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
+ this.zoomToCursor = false;
+
+ // 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: 'ArrowLeft', UP: 'ArrowUp', RIGHT: 'ArrowRight', BOTTOM: 'ArrowDown' };
+
+ // Mouse buttons
+ this.mouseButtons = { LEFT: MOUSE.ROTATE, MIDDLE: MOUSE.DOLLY, RIGHT: MOUSE.PAN };
+
+ // Touch fingers
+ this.touches = { ONE: TOUCH.ROTATE, TWO: 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.getDistance = function () {
+
+ return this.object.position.distanceTo( this.target );
+
+ };
+
+ this.listenToKeyEvents = function ( domElement ) {
+
+ domElement.addEventListener( 'keydown', onKeyDown );
+ this._domElementKeyEvents = domElement;
+
+ };
+
+ this.stopListenToKeyEvents = function () {
+
+ this._domElementKeyEvents.removeEventListener( 'keydown', onKeyDown );
+ this._domElementKeyEvents = null;
+
+ };
+
+ 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 () {
+
+ const offset = new Vector3();
+
+ // so camera.up is the orbit axis
+ const quat = new Quaternion().setFromUnitVectors( object.up, new Vector3( 0, 1, 0 ) );
+ const quatInverse = quat.clone().invert();
+
+ const lastPosition = new Vector3();
+ const lastQuaternion = new Quaternion();
+ const lastTargetPosition = new Vector3();
+
+ const twoPI = 2 * Math.PI;
+
+ return function update( deltaTime = null ) {
+
+ const 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( deltaTime ) );
+
+ }
+
+ 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
+
+ let min = scope.minAzimuthAngle;
+ let 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();
+
+
+ // move target to panned location
+
+ if ( scope.enableDamping === true ) {
+
+ scope.target.addScaledVector( panOffset, scope.dampingFactor );
+
+ } else {
+
+ scope.target.add( panOffset );
+
+ }
+
+ // adjust the camera position based on zoom only if we're not zooming to the cursor or if it's an ortho camera
+ // we adjust zoom later in these cases
+ if ( scope.zoomToCursor && performCursorZoom || scope.object.isOrthographicCamera ) {
+
+ spherical.radius = clampDistance( spherical.radius );
+
+ } else {
+
+ spherical.radius = clampDistance( spherical.radius * scale );
+
+ }
+
+
+ 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 );
+
+ }
+
+ // adjust camera position
+ let zoomChanged = false;
+ if ( scope.zoomToCursor && performCursorZoom ) {
+
+ let newRadius = null;
+ if ( scope.object.isPerspectiveCamera ) {
+
+ // move the camera down the pointer ray
+ // this method avoids floating point error
+ const prevRadius = offset.length();
+ newRadius = clampDistance( prevRadius * scale );
+
+ const radiusDelta = prevRadius - newRadius;
+ scope.object.position.addScaledVector( dollyDirection, radiusDelta );
+ scope.object.updateMatrixWorld();
+
+ } else if ( scope.object.isOrthographicCamera ) {
+
+ // adjust the ortho camera position based on zoom changes
+ const mouseBefore = new Vector3( mouse.x, mouse.y, 0 );
+ mouseBefore.unproject( scope.object );
+
+ scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom / scale ) );
+ scope.object.updateProjectionMatrix();
+ zoomChanged = true;
+
+ const mouseAfter = new Vector3( mouse.x, mouse.y, 0 );
+ mouseAfter.unproject( scope.object );
+
+ scope.object.position.sub( mouseAfter ).add( mouseBefore );
+ scope.object.updateMatrixWorld();
+
+ newRadius = offset.length();
+
+ } else {
+
+ console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - zoom to cursor disabled.' );
+ scope.zoomToCursor = false;
+
+ }
+
+ // handle the placement of the target
+ if ( newRadius !== null ) {
+
+ if ( this.screenSpacePanning ) {
+
+ // position the orbit target in front of the new camera position
+ scope.target.set( 0, 0, - 1 )
+ .transformDirection( scope.object.matrix )
+ .multiplyScalar( newRadius )
+ .add( scope.object.position );
+
+ } else {
+
+ // get the ray and translation plane to compute target
+ _ray.origin.copy( scope.object.position );
+ _ray.direction.set( 0, 0, - 1 ).transformDirection( scope.object.matrix );
+
+ // if the camera is 20 degrees above the horizon then don't adjust the focus target to avoid
+ // extremely large values
+ if ( Math.abs( scope.object.up.dot( _ray.direction ) ) < TILT_LIMIT ) {
+
+ object.lookAt( scope.target );
+
+ } else {
+
+ _plane.setFromNormalAndCoplanarPoint( scope.object.up, scope.target );
+ _ray.intersectPlane( _plane, scope.target );
+
+ }
+
+ }
+
+ }
+
+ } else if ( scope.object.isOrthographicCamera ) {
+
+ scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom / scale ) );
+ scope.object.updateProjectionMatrix();
+ zoomChanged = true;
+
+ }
+
+ scale = 1;
+ performCursorZoom = false;
+
+ // 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 ||
+ lastTargetPosition.distanceToSquared( scope.target ) > 0 ) {
+
+ scope.dispatchEvent( _changeEvent );
+
+ lastPosition.copy( scope.object.position );
+ lastQuaternion.copy( scope.object.quaternion );
+ lastTargetPosition.copy( scope.target );
+
+ zoomChanged = false;
+
+ return true;
+
+ }
+
+ return false;
+
+ };
+
+ }();
+
+ this.dispose = function () {
+
+ scope.domElement.removeEventListener( 'contextmenu', onContextMenu );
+
+ scope.domElement.removeEventListener( 'pointerdown', onPointerDown );
+ scope.domElement.removeEventListener( 'pointercancel', onPointerUp );
+ scope.domElement.removeEventListener( 'wheel', onMouseWheel );
+
+ scope.domElement.removeEventListener( 'pointermove', onPointerMove );
+ scope.domElement.removeEventListener( 'pointerup', onPointerUp );
+
+
+ if ( scope._domElementKeyEvents !== null ) {
+
+ scope._domElementKeyEvents.removeEventListener( 'keydown', onKeyDown );
+ scope._domElementKeyEvents = null;
+
+ }
+
+ //scope.dispatchEvent( { type: 'dispose' } ); // should this be added here?
+
+ };
+
+ //
+ // internals
+ //
+
+ const scope = this;
+
+ const STATE = {
+ NONE: - 1,
+ ROTATE: 0,
+ DOLLY: 1,
+ PAN: 2,
+ TOUCH_ROTATE: 3,
+ TOUCH_PAN: 4,
+ TOUCH_DOLLY_PAN: 5,
+ TOUCH_DOLLY_ROTATE: 6
+ };
+
+ let state = STATE.NONE;
+
+ const EPS = 0.000001;
+
+ // current position in spherical coordinates
+ const spherical = new Spherical();
+ const sphericalDelta = new Spherical();
+
+ let scale = 1;
+ const panOffset = new Vector3();
+
+ const rotateStart = new Vector2();
+ const rotateEnd = new Vector2();
+ const rotateDelta = new Vector2();
+
+ const panStart = new Vector2();
+ const panEnd = new Vector2();
+ const panDelta = new Vector2();
+
+ const dollyStart = new Vector2();
+ const dollyEnd = new Vector2();
+ const dollyDelta = new Vector2();
+
+ const dollyDirection = new Vector3();
+ const mouse = new Vector2();
+ let performCursorZoom = false;
+
+ const pointers = [];
+ const pointerPositions = {};
+
+ function getAutoRotationAngle( deltaTime ) {
+
+ if ( deltaTime !== null ) {
+
+ return ( 2 * Math.PI / 60 * scope.autoRotateSpeed ) * deltaTime;
+
+ } else {
+
+ 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;
+
+ }
+
+ const panLeft = function () {
+
+ const v = new Vector3();
+
+ return function panLeft( distance, objectMatrix ) {
+
+ v.setFromMatrixColumn( objectMatrix, 0 ); // get X column of objectMatrix
+ v.multiplyScalar( - distance );
+
+ panOffset.add( v );
+
+ };
+
+ }();
+
+ const panUp = function () {
+
+ const v = new 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
+ const pan = function () {
+
+ const offset = new Vector3();
+
+ return function pan( deltaX, deltaY ) {
+
+ const element = scope.domElement;
+
+ if ( scope.object.isPerspectiveCamera ) {
+
+ // perspective
+ const position = scope.object.position;
+ offset.copy( position ).sub( scope.target );
+ let 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 || scope.object.isOrthographicCamera ) {
+
+ scale /= dollyScale;
+
+ } else {
+
+ console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' );
+ scope.enableZoom = false;
+
+ }
+
+ }
+
+ function dollyIn( dollyScale ) {
+
+ if ( scope.object.isPerspectiveCamera || scope.object.isOrthographicCamera ) {
+
+ scale *= dollyScale;
+
+ } else {
+
+ console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' );
+ scope.enableZoom = false;
+
+ }
+
+ }
+
+ function updateMouseParameters( event ) {
+
+ if ( ! scope.zoomToCursor ) {
+
+ return;
+
+ }
+
+ performCursorZoom = true;
+
+ const rect = scope.domElement.getBoundingClientRect();
+ const x = event.clientX - rect.left;
+ const y = event.clientY - rect.top;
+ const w = rect.width;
+ const h = rect.height;
+
+ mouse.x = ( x / w ) * 2 - 1;
+ mouse.y = - ( y / h ) * 2 + 1;
+
+ dollyDirection.set( mouse.x, mouse.y, 1 ).unproject( scope.object ).sub( scope.object.position ).normalize();
+
+ }
+
+ function clampDistance( dist ) {
+
+ return Math.max( scope.minDistance, Math.min( scope.maxDistance, dist ) );
+
+ }
+
+ //
+ // event callbacks - update the object state
+ //
+
+ function handleMouseDownRotate( event ) {
+
+ rotateStart.set( event.clientX, event.clientY );
+
+ }
+
+ function handleMouseDownDolly( event ) {
+
+ updateMouseParameters( 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 );
+
+ const 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 handleMouseWheel( event ) {
+
+ updateMouseParameters( event );
+
+ if ( event.deltaY < 0 ) {
+
+ dollyIn( getZoomScale() );
+
+ } else if ( event.deltaY > 0 ) {
+
+ dollyOut( getZoomScale() );
+
+ }
+
+ scope.update();
+
+ }
+
+ function handleKeyDown( event ) {
+
+ let needsUpdate = false;
+
+ switch ( event.code ) {
+
+ case scope.keys.UP:
+
+ if ( event.ctrlKey || event.metaKey || event.shiftKey ) {
+
+ rotateUp( 2 * Math.PI * scope.rotateSpeed / scope.domElement.clientHeight );
+
+ } else {
+
+ pan( 0, scope.keyPanSpeed );
+
+ }
+
+ needsUpdate = true;
+ break;
+
+ case scope.keys.BOTTOM:
+
+ if ( event.ctrlKey || event.metaKey || event.shiftKey ) {
+
+ rotateUp( - 2 * Math.PI * scope.rotateSpeed / scope.domElement.clientHeight );
+
+ } else {
+
+ pan( 0, - scope.keyPanSpeed );
+
+ }
+
+ needsUpdate = true;
+ break;
+
+ case scope.keys.LEFT:
+
+ if ( event.ctrlKey || event.metaKey || event.shiftKey ) {
+
+ rotateLeft( 2 * Math.PI * scope.rotateSpeed / scope.domElement.clientHeight );
+
+ } else {
+
+ pan( scope.keyPanSpeed, 0 );
+
+ }
+
+ needsUpdate = true;
+ break;
+
+ case scope.keys.RIGHT:
+
+ if ( event.ctrlKey || event.metaKey || event.shiftKey ) {
+
+ rotateLeft( - 2 * Math.PI * scope.rotateSpeed / scope.domElement.clientHeight );
+
+ } else {
+
+ pan( - scope.keyPanSpeed, 0 );
+
+ }
+
+ needsUpdate = true;
+ break;
+
+ }
+
+ if ( needsUpdate ) {
+
+ // prevent the browser from scrolling on cursor keys
+ event.preventDefault();
+
+ scope.update();
+
+ }
+
+
+ }
+
+ function handleTouchStartRotate() {
+
+ if ( pointers.length === 1 ) {
+
+ rotateStart.set( pointers[ 0 ].pageX, pointers[ 0 ].pageY );
+
+ } else {
+
+ const x = 0.5 * ( pointers[ 0 ].pageX + pointers[ 1 ].pageX );
+ const y = 0.5 * ( pointers[ 0 ].pageY + pointers[ 1 ].pageY );
+
+ rotateStart.set( x, y );
+
+ }
+
+ }
+
+ function handleTouchStartPan() {
+
+ if ( pointers.length === 1 ) {
+
+ panStart.set( pointers[ 0 ].pageX, pointers[ 0 ].pageY );
+
+ } else {
+
+ const x = 0.5 * ( pointers[ 0 ].pageX + pointers[ 1 ].pageX );
+ const y = 0.5 * ( pointers[ 0 ].pageY + pointers[ 1 ].pageY );
+
+ panStart.set( x, y );
+
+ }
+
+ }
+
+ function handleTouchStartDolly() {
+
+ const dx = pointers[ 0 ].pageX - pointers[ 1 ].pageX;
+ const dy = pointers[ 0 ].pageY - pointers[ 1 ].pageY;
+
+ const distance = Math.sqrt( dx * dx + dy * dy );
+
+ dollyStart.set( 0, distance );
+
+ }
+
+ function handleTouchStartDollyPan() {
+
+ if ( scope.enableZoom ) handleTouchStartDolly();
+
+ if ( scope.enablePan ) handleTouchStartPan();
+
+ }
+
+ function handleTouchStartDollyRotate() {
+
+ if ( scope.enableZoom ) handleTouchStartDolly();
+
+ if ( scope.enableRotate ) handleTouchStartRotate();
+
+ }
+
+ function handleTouchMoveRotate( event ) {
+
+ if ( pointers.length == 1 ) {
+
+ rotateEnd.set( event.pageX, event.pageY );
+
+ } else {
+
+ const position = getSecondPointerPosition( event );
+
+ const x = 0.5 * ( event.pageX + position.x );
+ const y = 0.5 * ( event.pageY + position.y );
+
+ rotateEnd.set( x, y );
+
+ }
+
+ rotateDelta.subVectors( rotateEnd, rotateStart ).multiplyScalar( scope.rotateSpeed );
+
+ const 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 ( pointers.length === 1 ) {
+
+ panEnd.set( event.pageX, event.pageY );
+
+ } else {
+
+ const position = getSecondPointerPosition( event );
+
+ const x = 0.5 * ( event.pageX + position.x );
+ const y = 0.5 * ( event.pageY + position.y );
+
+ panEnd.set( x, y );
+
+ }
+
+ panDelta.subVectors( panEnd, panStart ).multiplyScalar( scope.panSpeed );
+
+ pan( panDelta.x, panDelta.y );
+
+ panStart.copy( panEnd );
+
+ }
+
+ function handleTouchMoveDolly( event ) {
+
+ const position = getSecondPointerPosition( event );
+
+ const dx = event.pageX - position.x;
+ const dy = event.pageY - position.y;
+
+ const 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 );
+
+ }
+
+ //
+ // event handlers - FSM: listen for events and reset state
+ //
+
+ function onPointerDown( event ) {
+
+ if ( scope.enabled === false ) return;
+
+ if ( pointers.length === 0 ) {
+
+ scope.domElement.setPointerCapture( event.pointerId );
+
+ scope.domElement.addEventListener( 'pointermove', onPointerMove );
+ scope.domElement.addEventListener( 'pointerup', onPointerUp );
+
+ }
+
+ //
+
+ addPointer( event );
+
+ if ( event.pointerType === 'touch' ) {
+
+ onTouchStart( event );
+
+ } else {
+
+ onMouseDown( event );
+
+ }
+
+ }
+
+ function onPointerMove( event ) {
+
+ if ( scope.enabled === false ) return;
+
+ if ( event.pointerType === 'touch' ) {
+
+ onTouchMove( event );
+
+ } else {
+
+ onMouseMove( event );
+
+ }
+
+ }
+
+ function onPointerUp( event ) {
+
+ removePointer( event );
+
+ if ( pointers.length === 0 ) {
+
+ scope.domElement.releasePointerCapture( event.pointerId );
+
+ scope.domElement.removeEventListener( 'pointermove', onPointerMove );
+ scope.domElement.removeEventListener( 'pointerup', onPointerUp );
+
+ }
+
+ scope.dispatchEvent( _endEvent );
+
+ state = STATE.NONE;
+
+ }
+
+ function onMouseDown( event ) {
+
+ let 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 MOUSE.DOLLY:
+
+ if ( scope.enableZoom === false ) return;
+
+ handleMouseDownDolly( event );
+
+ state = STATE.DOLLY;
+
+ break;
+
+ case 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 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.dispatchEvent( _startEvent );
+
+ }
+
+ }
+
+ function onMouseMove( event ) {
+
+ 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 onMouseWheel( event ) {
+
+ if ( scope.enabled === false || scope.enableZoom === false || state !== STATE.NONE ) return;
+
+ event.preventDefault();
+
+ scope.dispatchEvent( _startEvent );
+
+ handleMouseWheel( event );
+
+ scope.dispatchEvent( _endEvent );
+
+ }
+
+ function onKeyDown( event ) {
+
+ if ( scope.enabled === false || scope.enablePan === false ) return;
+
+ handleKeyDown( event );
+
+ }
+
+ function onTouchStart( event ) {
+
+ trackPointer( event );
+
+ switch ( pointers.length ) {
+
+ case 1:
+
+ switch ( scope.touches.ONE ) {
+
+ case TOUCH.ROTATE:
+
+ if ( scope.enableRotate === false ) return;
+
+ handleTouchStartRotate();
+
+ state = STATE.TOUCH_ROTATE;
+
+ break;
+
+ case TOUCH.PAN:
+
+ if ( scope.enablePan === false ) return;
+
+ handleTouchStartPan();
+
+ state = STATE.TOUCH_PAN;
+
+ break;
+
+ default:
+
+ state = STATE.NONE;
+
+ }
+
+ break;
+
+ case 2:
+
+ switch ( scope.touches.TWO ) {
+
+ case TOUCH.DOLLY_PAN:
+
+ if ( scope.enableZoom === false && scope.enablePan === false ) return;
+
+ handleTouchStartDollyPan();
+
+ state = STATE.TOUCH_DOLLY_PAN;
+
+ break;
+
+ case TOUCH.DOLLY_ROTATE:
+
+ if ( scope.enableZoom === false && scope.enableRotate === false ) return;
+
+ handleTouchStartDollyRotate();
+
+ 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 ) {
+
+ trackPointer( event );
+
+ 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 onContextMenu( event ) {
+
+ if ( scope.enabled === false ) return;
+
+ event.preventDefault();
+
+ }
+
+ function addPointer( event ) {
+
+ pointers.push( event );
+
+ }
+
+ function removePointer( event ) {
+
+ delete pointerPositions[ event.pointerId ];
+
+ for ( let i = 0; i < pointers.length; i ++ ) {
+
+ if ( pointers[ i ].pointerId == event.pointerId ) {
+
+ pointers.splice( i, 1 );
+ return;
+
+ }
+
+ }
+
+ }
+
+ function trackPointer( event ) {
+
+ let position = pointerPositions[ event.pointerId ];
+
+ if ( position === undefined ) {
+
+ position = new Vector2();
+ pointerPositions[ event.pointerId ] = position;
+
+ }
+
+ position.set( event.pageX, event.pageY );
+
+ }
+
+ function getSecondPointerPosition( event ) {
+
+ const pointer = ( event.pointerId === pointers[ 0 ].pointerId ) ? pointers[ 1 ] : pointers[ 0 ];
+
+ return pointerPositions[ pointer.pointerId ];
+
+ }
+
+ //
+
+ scope.domElement.addEventListener( 'contextmenu', onContextMenu );
+
+ scope.domElement.addEventListener( 'pointerdown', onPointerDown );
+ scope.domElement.addEventListener( 'pointercancel', onPointerUp );
+ scope.domElement.addEventListener( 'wheel', onMouseWheel, { passive: false } );
+
+ // force an update at start
+
+ this.update();
+
+ }
+
+}
+
+export { OrbitControls };
\ No newline at end of file
diff --git a/lib/three.js b/lib/three.js
index 00aeed2..89ca5e9 100644
--- a/lib/three.js
+++ b/lib/three.js
@@ -1,6639 +1,6725 @@
-(function (global, factory) {
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
- typeof define === 'function' && define.amd ? define(['exports'], factory) :
- (global = global || self, factory(global.THREE = {}));
-}(this, function (exports) { 'use strict';
+/**
+ * @license
+ * Copyright 2010-2023 Three.js Authors
+ * SPDX-License-Identifier: MIT
+ */
+const REVISION = '157';
+
+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;
+const CullFaceBack = 1;
+const CullFaceFront = 2;
+const CullFaceFrontBack = 3;
+const BasicShadowMap = 0;
+const PCFShadowMap = 1;
+const PCFSoftShadowMap = 2;
+const VSMShadowMap = 3;
+const FrontSide = 0;
+const BackSide = 1;
+const DoubleSide = 2;
+const TwoPassDoubleSide = 2; // r149
+const NoBlending = 0;
+const NormalBlending = 1;
+const AdditiveBlending = 2;
+const SubtractiveBlending = 3;
+const MultiplyBlending = 4;
+const CustomBlending = 5;
+const AddEquation = 100;
+const SubtractEquation = 101;
+const ReverseSubtractEquation = 102;
+const MinEquation = 103;
+const MaxEquation = 104;
+const ZeroFactor = 200;
+const OneFactor = 201;
+const SrcColorFactor = 202;
+const OneMinusSrcColorFactor = 203;
+const SrcAlphaFactor = 204;
+const OneMinusSrcAlphaFactor = 205;
+const DstAlphaFactor = 206;
+const OneMinusDstAlphaFactor = 207;
+const DstColorFactor = 208;
+const OneMinusDstColorFactor = 209;
+const SrcAlphaSaturateFactor = 210;
+const NeverDepth = 0;
+const AlwaysDepth = 1;
+const LessDepth = 2;
+const LessEqualDepth = 3;
+const EqualDepth = 4;
+const GreaterEqualDepth = 5;
+const GreaterDepth = 6;
+const NotEqualDepth = 7;
+const MultiplyOperation = 0;
+const MixOperation = 1;
+const AddOperation = 2;
+const NoToneMapping = 0;
+const LinearToneMapping = 1;
+const ReinhardToneMapping = 2;
+const CineonToneMapping = 3;
+const ACESFilmicToneMapping = 4;
+const CustomToneMapping = 5;
+
+const UVMapping = 300;
+const CubeReflectionMapping = 301;
+const CubeRefractionMapping = 302;
+const EquirectangularReflectionMapping = 303;
+const EquirectangularRefractionMapping = 304;
+const CubeUVReflectionMapping = 306;
+const RepeatWrapping = 1000;
+const ClampToEdgeWrapping = 1001;
+const MirroredRepeatWrapping = 1002;
+const NearestFilter = 1003;
+const NearestMipmapNearestFilter = 1004;
+const NearestMipMapNearestFilter = 1004;
+const NearestMipmapLinearFilter = 1005;
+const NearestMipMapLinearFilter = 1005;
+const LinearFilter = 1006;
+const LinearMipmapNearestFilter = 1007;
+const LinearMipMapNearestFilter = 1007;
+const LinearMipmapLinearFilter = 1008;
+const LinearMipMapLinearFilter = 1008;
+const UnsignedByteType = 1009;
+const ByteType = 1010;
+const ShortType = 1011;
+const UnsignedShortType = 1012;
+const IntType = 1013;
+const UnsignedIntType = 1014;
+const FloatType = 1015;
+const HalfFloatType = 1016;
+const UnsignedShort4444Type = 1017;
+const UnsignedShort5551Type = 1018;
+const UnsignedInt248Type = 1020;
+const AlphaFormat = 1021;
+const RGBAFormat = 1023;
+const LuminanceFormat = 1024;
+const LuminanceAlphaFormat = 1025;
+const DepthFormat = 1026;
+const DepthStencilFormat = 1027;
+const RedFormat = 1028;
+const RedIntegerFormat = 1029;
+const RGFormat = 1030;
+const RGIntegerFormat = 1031;
+const RGBAIntegerFormat = 1033;
+
+const RGB_S3TC_DXT1_Format = 33776;
+const RGBA_S3TC_DXT1_Format = 33777;
+const RGBA_S3TC_DXT3_Format = 33778;
+const RGBA_S3TC_DXT5_Format = 33779;
+const RGB_PVRTC_4BPPV1_Format = 35840;
+const RGB_PVRTC_2BPPV1_Format = 35841;
+const RGBA_PVRTC_4BPPV1_Format = 35842;
+const RGBA_PVRTC_2BPPV1_Format = 35843;
+const RGB_ETC1_Format = 36196;
+const RGB_ETC2_Format = 37492;
+const RGBA_ETC2_EAC_Format = 37496;
+const RGBA_ASTC_4x4_Format = 37808;
+const RGBA_ASTC_5x4_Format = 37809;
+const RGBA_ASTC_5x5_Format = 37810;
+const RGBA_ASTC_6x5_Format = 37811;
+const RGBA_ASTC_6x6_Format = 37812;
+const RGBA_ASTC_8x5_Format = 37813;
+const RGBA_ASTC_8x6_Format = 37814;
+const RGBA_ASTC_8x8_Format = 37815;
+const RGBA_ASTC_10x5_Format = 37816;
+const RGBA_ASTC_10x6_Format = 37817;
+const RGBA_ASTC_10x8_Format = 37818;
+const RGBA_ASTC_10x10_Format = 37819;
+const RGBA_ASTC_12x10_Format = 37820;
+const RGBA_ASTC_12x12_Format = 37821;
+const RGBA_BPTC_Format = 36492;
+const RGB_BPTC_SIGNED_Format = 36494;
+const RGB_BPTC_UNSIGNED_Format = 36495;
+const RED_RGTC1_Format = 36283;
+const SIGNED_RED_RGTC1_Format = 36284;
+const RED_GREEN_RGTC2_Format = 36285;
+const SIGNED_RED_GREEN_RGTC2_Format = 36286;
+const LoopOnce = 2200;
+const LoopRepeat = 2201;
+const LoopPingPong = 2202;
+const InterpolateDiscrete = 2300;
+const InterpolateLinear = 2301;
+const InterpolateSmooth = 2302;
+const ZeroCurvatureEnding = 2400;
+const ZeroSlopeEnding = 2401;
+const WrapAroundEnding = 2402;
+const NormalAnimationBlendMode = 2500;
+const AdditiveAnimationBlendMode = 2501;
+const TrianglesDrawMode = 0;
+const TriangleStripDrawMode = 1;
+const TriangleFanDrawMode = 2;
+/** @deprecated Use LinearSRGBColorSpace or NoColorSpace in three.js r152+. */
+const LinearEncoding = 3000;
+/** @deprecated Use SRGBColorSpace in three.js r152+. */
+const sRGBEncoding = 3001;
+const BasicDepthPacking = 3200;
+const RGBADepthPacking = 3201;
+const TangentSpaceNormalMap = 0;
+const ObjectSpaceNormalMap = 1;
+
+// Color space string identifiers, matching CSS Color Module Level 4 and WebGPU names where available.
+const NoColorSpace = '';
+const SRGBColorSpace = 'srgb';
+const LinearSRGBColorSpace = 'srgb-linear';
+const DisplayP3ColorSpace = 'display-p3';
+const LinearDisplayP3ColorSpace = 'display-p3-linear';
+
+const LinearTransfer = 'linear';
+const SRGBTransfer = 'srgb';
+
+const Rec709Primaries = 'rec709';
+const P3Primaries = 'p3';
+
+const ZeroStencilOp = 0;
+const KeepStencilOp = 7680;
+const ReplaceStencilOp = 7681;
+const IncrementStencilOp = 7682;
+const DecrementStencilOp = 7683;
+const IncrementWrapStencilOp = 34055;
+const DecrementWrapStencilOp = 34056;
+const InvertStencilOp = 5386;
+
+const NeverStencilFunc = 512;
+const LessStencilFunc = 513;
+const EqualStencilFunc = 514;
+const LessEqualStencilFunc = 515;
+const GreaterStencilFunc = 516;
+const NotEqualStencilFunc = 517;
+const GreaterEqualStencilFunc = 518;
+const AlwaysStencilFunc = 519;
+
+const NeverCompare = 512;
+const LessCompare = 513;
+const EqualCompare = 514;
+const LessEqualCompare = 515;
+const GreaterCompare = 516;
+const NotEqualCompare = 517;
+const GreaterEqualCompare = 518;
+const AlwaysCompare = 519;
+
+const StaticDrawUsage = 35044;
+const DynamicDrawUsage = 35048;
+const StreamDrawUsage = 35040;
+const StaticReadUsage = 35045;
+const DynamicReadUsage = 35049;
+const StreamReadUsage = 35041;
+const StaticCopyUsage = 35046;
+const DynamicCopyUsage = 35050;
+const StreamCopyUsage = 35042;
+
+const GLSL1 = '100';
+const GLSL3 = '300 es';
+
+const _SRGBAFormat = 1035; // fallback for WebGL 1
- // Polyfills
+const WebGLCoordinateSystem = 2000;
+const WebGPUCoordinateSystem = 2001;
- if ( Number.EPSILON === undefined ) {
+/**
+ * https://github.com/mrdoob/eventdispatcher.js/
+ */
- Number.EPSILON = Math.pow( 2, - 52 );
+class EventDispatcher {
- }
-
- if ( Number.isInteger === undefined ) {
-
- // Missing in IE
- // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger
-
- Number.isInteger = function ( value ) {
+ addEventListener( type, listener ) {
- return typeof value === 'number' && isFinite( value ) && Math.floor( value ) === value;
+ if ( this._listeners === undefined ) this._listeners = {};
- };
-
- }
+ const listeners = this._listeners;
- //
+ if ( listeners[ type ] === undefined ) {
- if ( Math.sign === undefined ) {
+ listeners[ type ] = [];
- // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sign
+ }
- Math.sign = function ( x ) {
+ if ( listeners[ type ].indexOf( listener ) === - 1 ) {
- return ( x < 0 ) ? - 1 : ( x > 0 ) ? 1 : + x;
+ listeners[ type ].push( listener );
- };
+ }
}
- if ( 'name' in Function.prototype === false ) {
-
- // Missing in IE
- // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name
+ hasEventListener( type, listener ) {
- Object.defineProperty( Function.prototype, 'name', {
+ if ( this._listeners === undefined ) return false;
- get: function () {
+ const listeners = this._listeners;
- return this.toString().match( /^\s*function\s*([^\(\s]*)/ )[ 1 ];
+ return listeners[ type ] !== undefined && listeners[ type ].indexOf( listener ) !== - 1;
- }
+ }
- } );
+ removeEventListener( type, listener ) {
- }
+ if ( this._listeners === undefined ) return;
- if ( Object.assign === undefined ) {
+ const listeners = this._listeners;
+ const listenerArray = listeners[ type ];
- // Missing in IE
- // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
+ if ( listenerArray !== undefined ) {
- Object.assign = function ( target ) {
+ const index = listenerArray.indexOf( listener );
- if ( target === undefined || target === null ) {
+ if ( index !== - 1 ) {
- throw new TypeError( 'Cannot convert undefined or null to object' );
+ listenerArray.splice( index, 1 );
}
- var output = Object( target );
+ }
- for ( var index = 1; index < arguments.length; index ++ ) {
+ }
- var source = arguments[ index ];
+ dispatchEvent( event ) {
- if ( source !== undefined && source !== null ) {
+ if ( this._listeners === undefined ) return;
- for ( var nextKey in source ) {
+ const listeners = this._listeners;
+ const listenerArray = listeners[ event.type ];
- if ( Object.prototype.hasOwnProperty.call( source, nextKey ) ) {
+ if ( listenerArray !== undefined ) {
- output[ nextKey ] = source[ nextKey ];
+ event.target = this;
- }
+ // Make a copy, in case listeners are removed while iterating.
+ const array = listenerArray.slice( 0 );
- }
+ for ( let i = 0, l = array.length; i < l; i ++ ) {
- }
+ array[ i ].call( this, event );
}
- return output;
+ event.target = null;
- };
+ }
}
- /**
- * https://github.com/mrdoob/eventdispatcher.js/
- */
+}
- function EventDispatcher() {}
+const _lut = [ '00', '01', '02', '03', '04', '05', '06', '07', '08', '09', '0a', '0b', '0c', '0d', '0e', '0f', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '1a', '1b', '1c', '1d', '1e', '1f', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '2a', '2b', '2c', '2d', '2e', '2f', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '3a', '3b', '3c', '3d', '3e', '3f', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '4a', '4b', '4c', '4d', '4e', '4f', '50', '51', '52', '53', '54', '55', '56', '57', '58', '59', '5a', '5b', '5c', '5d', '5e', '5f', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '6a', '6b', '6c', '6d', '6e', '6f', '70', '71', '72', '73', '74', '75', '76', '77', '78', '79', '7a', '7b', '7c', '7d', '7e', '7f', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '8a', '8b', '8c', '8d', '8e', '8f', '90', '91', '92', '93', '94', '95', '96', '97', '98', '99', '9a', '9b', '9c', '9d', '9e', '9f', 'a0', 'a1', 'a2', 'a3', 'a4', 'a5', 'a6', 'a7', 'a8', 'a9', 'aa', 'ab', 'ac', 'ad', 'ae', 'af', 'b0', 'b1', 'b2', 'b3', 'b4', 'b5', 'b6', 'b7', 'b8', 'b9', 'ba', 'bb', 'bc', 'bd', 'be', 'bf', 'c0', 'c1', 'c2', 'c3', 'c4', 'c5', 'c6', 'c7', 'c8', 'c9', 'ca', 'cb', 'cc', 'cd', 'ce', 'cf', 'd0', 'd1', 'd2', 'd3', 'd4', 'd5', 'd6', 'd7', 'd8', 'd9', 'da', 'db', 'dc', 'dd', 'de', 'df', 'e0', 'e1', 'e2', 'e3', 'e4', 'e5', 'e6', 'e7', 'e8', 'e9', 'ea', 'eb', 'ec', 'ed', 'ee', 'ef', 'f0', 'f1', 'f2', 'f3', 'f4', 'f5', 'f6', 'f7', 'f8', 'f9', 'fa', 'fb', 'fc', 'fd', 'fe', 'ff' ];
- Object.assign( EventDispatcher.prototype, {
+let _seed = 1234567;
- addEventListener: function ( type, listener ) {
- if ( this._listeners === undefined ) this._listeners = {};
+const DEG2RAD = Math.PI / 180;
+const RAD2DEG = 180 / Math.PI;
- var listeners = this._listeners;
+// http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/21963136#21963136
+function generateUUID() {
- if ( listeners[ type ] === undefined ) {
+ const d0 = Math.random() * 0xffffffff | 0;
+ const d1 = Math.random() * 0xffffffff | 0;
+ const d2 = Math.random() * 0xffffffff | 0;
+ const d3 = Math.random() * 0xffffffff | 0;
+ const uuid = _lut[ d0 & 0xff ] + _lut[ d0 >> 8 & 0xff ] + _lut[ d0 >> 16 & 0xff ] + _lut[ d0 >> 24 & 0xff ] + '-' +
+ _lut[ d1 & 0xff ] + _lut[ d1 >> 8 & 0xff ] + '-' + _lut[ d1 >> 16 & 0x0f | 0x40 ] + _lut[ d1 >> 24 & 0xff ] + '-' +
+ _lut[ d2 & 0x3f | 0x80 ] + _lut[ d2 >> 8 & 0xff ] + '-' + _lut[ d2 >> 16 & 0xff ] + _lut[ d2 >> 24 & 0xff ] +
+ _lut[ d3 & 0xff ] + _lut[ d3 >> 8 & 0xff ] + _lut[ d3 >> 16 & 0xff ] + _lut[ d3 >> 24 & 0xff ];
- listeners[ type ] = [];
+ // .toLowerCase() here flattens concatenated strings to save heap memory space.
+ return uuid.toLowerCase();
- }
+}
- if ( listeners[ type ].indexOf( listener ) === - 1 ) {
+function clamp( value, min, max ) {
- listeners[ type ].push( listener );
+ return Math.max( min, Math.min( max, value ) );
- }
+}
- },
+// compute euclidean modulo of m % n
+// https://en.wikipedia.org/wiki/Modulo_operation
+function euclideanModulo( n, m ) {
- hasEventListener: function ( type, listener ) {
+ return ( ( n % m ) + m ) % m;
- if ( this._listeners === undefined ) return false;
+}
- var listeners = this._listeners;
+// Linear mapping from range to range
+function mapLinear( x, a1, a2, b1, b2 ) {
- return listeners[ type ] !== undefined && listeners[ type ].indexOf( listener ) !== - 1;
+ return b1 + ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 );
- },
+}
+
+// https://www.gamedev.net/tutorials/programming/general-and-gameplay-programming/inverse-lerp-a-super-useful-yet-often-overlooked-function-r5230/
+function inverseLerp( x, y, value ) {
- removeEventListener: function ( type, listener ) {
+ if ( x !== y ) {
- if ( this._listeners === undefined ) return;
+ return ( value - x ) / ( y - x );
- var listeners = this._listeners;
- var listenerArray = listeners[ type ];
+ } else {
- if ( listenerArray !== undefined ) {
+ return 0;
- var index = listenerArray.indexOf( listener );
+ }
- if ( index !== - 1 ) {
+}
- listenerArray.splice( index, 1 );
+// https://en.wikipedia.org/wiki/Linear_interpolation
+function lerp( x, y, t ) {
- }
+ return ( 1 - t ) * x + t * y;
- }
+}
- },
+// http://www.rorydriscoll.com/2016/03/07/frame-rate-independent-damping-using-lerp/
+function damp( x, y, lambda, dt ) {
- dispatchEvent: function ( event ) {
+ return lerp( x, y, 1 - Math.exp( - lambda * dt ) );
- if ( this._listeners === undefined ) return;
+}
- var listeners = this._listeners;
- var listenerArray = listeners[ event.type ];
+// https://www.desmos.com/calculator/vcsjnyz7x4
+function pingpong( x, length = 1 ) {
- if ( listenerArray !== undefined ) {
+ return length - Math.abs( euclideanModulo( x, length * 2 ) - length );
- event.target = this;
+}
- var array = listenerArray.slice( 0 );
+// http://en.wikipedia.org/wiki/Smoothstep
+function smoothstep( x, min, max ) {
- for ( var i = 0, l = array.length; i < l; i ++ ) {
+ if ( x <= min ) return 0;
+ if ( x >= max ) return 1;
- array[ i ].call( this, event );
+ x = ( x - min ) / ( max - min );
- }
+ return x * x * ( 3 - 2 * x );
- }
+}
- }
+function smootherstep( x, min, max ) {
- } );
+ if ( x <= min ) return 0;
+ if ( x >= max ) return 1;
- var REVISION = '108';
- var MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2, ROTATE: 0, DOLLY: 1, PAN: 2 };
- var TOUCH = { ROTATE: 0, PAN: 1, DOLLY_PAN: 2, DOLLY_ROTATE: 3 };
- var CullFaceNone = 0;
- var CullFaceBack = 1;
- var CullFaceFront = 2;
- var CullFaceFrontBack = 3;
- var FrontFaceDirectionCW = 0;
- var FrontFaceDirectionCCW = 1;
- var BasicShadowMap = 0;
- var PCFShadowMap = 1;
- var PCFSoftShadowMap = 2;
- var VSMShadowMap = 3;
- var FrontSide = 0;
- var BackSide = 1;
- var DoubleSide = 2;
- var FlatShading = 1;
- var SmoothShading = 2;
- var NoColors = 0;
- var FaceColors = 1;
- var VertexColors = 2;
- var NoBlending = 0;
- var NormalBlending = 1;
- var AdditiveBlending = 2;
- var SubtractiveBlending = 3;
- var MultiplyBlending = 4;
- var CustomBlending = 5;
- var AddEquation = 100;
- var SubtractEquation = 101;
- var ReverseSubtractEquation = 102;
- var MinEquation = 103;
- var MaxEquation = 104;
- var ZeroFactor = 200;
- var OneFactor = 201;
- var SrcColorFactor = 202;
- var OneMinusSrcColorFactor = 203;
- var SrcAlphaFactor = 204;
- var OneMinusSrcAlphaFactor = 205;
- var DstAlphaFactor = 206;
- var OneMinusDstAlphaFactor = 207;
- var DstColorFactor = 208;
- var OneMinusDstColorFactor = 209;
- var SrcAlphaSaturateFactor = 210;
- var NeverDepth = 0;
- var AlwaysDepth = 1;
- var LessDepth = 2;
- var LessEqualDepth = 3;
- var EqualDepth = 4;
- var GreaterEqualDepth = 5;
- var GreaterDepth = 6;
- var NotEqualDepth = 7;
- var MultiplyOperation = 0;
- var MixOperation = 1;
- var AddOperation = 2;
- var NoToneMapping = 0;
- var LinearToneMapping = 1;
- var ReinhardToneMapping = 2;
- var Uncharted2ToneMapping = 3;
- var CineonToneMapping = 4;
- var ACESFilmicToneMapping = 5;
-
- var UVMapping = 300;
- var CubeReflectionMapping = 301;
- var CubeRefractionMapping = 302;
- var EquirectangularReflectionMapping = 303;
- var EquirectangularRefractionMapping = 304;
- var SphericalReflectionMapping = 305;
- var CubeUVReflectionMapping = 306;
- var CubeUVRefractionMapping = 307;
- var RepeatWrapping = 1000;
- var ClampToEdgeWrapping = 1001;
- var MirroredRepeatWrapping = 1002;
- var NearestFilter = 1003;
- var NearestMipmapNearestFilter = 1004;
- var NearestMipMapNearestFilter = 1004;
- var NearestMipmapLinearFilter = 1005;
- var NearestMipMapLinearFilter = 1005;
- var LinearFilter = 1006;
- var LinearMipmapNearestFilter = 1007;
- var LinearMipMapNearestFilter = 1007;
- var LinearMipmapLinearFilter = 1008;
- var LinearMipMapLinearFilter = 1008;
- var UnsignedByteType = 1009;
- var ByteType = 1010;
- var ShortType = 1011;
- var UnsignedShortType = 1012;
- var IntType = 1013;
- var UnsignedIntType = 1014;
- var FloatType = 1015;
- var HalfFloatType = 1016;
- var UnsignedShort4444Type = 1017;
- var UnsignedShort5551Type = 1018;
- var UnsignedShort565Type = 1019;
- var UnsignedInt248Type = 1020;
- var AlphaFormat = 1021;
- var RGBFormat = 1022;
- var RGBAFormat = 1023;
- var LuminanceFormat = 1024;
- var LuminanceAlphaFormat = 1025;
- var RGBEFormat = RGBAFormat;
- var DepthFormat = 1026;
- var DepthStencilFormat = 1027;
- var RedFormat = 1028;
- var RGB_S3TC_DXT1_Format = 33776;
- var RGBA_S3TC_DXT1_Format = 33777;
- var RGBA_S3TC_DXT3_Format = 33778;
- var RGBA_S3TC_DXT5_Format = 33779;
- var RGB_PVRTC_4BPPV1_Format = 35840;
- var RGB_PVRTC_2BPPV1_Format = 35841;
- var RGBA_PVRTC_4BPPV1_Format = 35842;
- var RGBA_PVRTC_2BPPV1_Format = 35843;
- var RGB_ETC1_Format = 36196;
- var RGBA_ASTC_4x4_Format = 37808;
- var RGBA_ASTC_5x4_Format = 37809;
- var RGBA_ASTC_5x5_Format = 37810;
- var RGBA_ASTC_6x5_Format = 37811;
- var RGBA_ASTC_6x6_Format = 37812;
- var RGBA_ASTC_8x5_Format = 37813;
- var RGBA_ASTC_8x6_Format = 37814;
- var RGBA_ASTC_8x8_Format = 37815;
- var RGBA_ASTC_10x5_Format = 37816;
- var RGBA_ASTC_10x6_Format = 37817;
- var RGBA_ASTC_10x8_Format = 37818;
- var RGBA_ASTC_10x10_Format = 37819;
- var RGBA_ASTC_12x10_Format = 37820;
- var RGBA_ASTC_12x12_Format = 37821;
- var LoopOnce = 2200;
- var LoopRepeat = 2201;
- var LoopPingPong = 2202;
- var InterpolateDiscrete = 2300;
- var InterpolateLinear = 2301;
- var InterpolateSmooth = 2302;
- var ZeroCurvatureEnding = 2400;
- var ZeroSlopeEnding = 2401;
- var WrapAroundEnding = 2402;
- var TrianglesDrawMode = 0;
- var TriangleStripDrawMode = 1;
- var TriangleFanDrawMode = 2;
- var LinearEncoding = 3000;
- var sRGBEncoding = 3001;
- var GammaEncoding = 3007;
- var RGBEEncoding = 3002;
- var LogLuvEncoding = 3003;
- var RGBM7Encoding = 3004;
- var RGBM16Encoding = 3005;
- var RGBDEncoding = 3006;
- var BasicDepthPacking = 3200;
- var RGBADepthPacking = 3201;
- var TangentSpaceNormalMap = 0;
- var ObjectSpaceNormalMap = 1;
-
- var ZeroStencilOp = 0;
- var KeepStencilOp = 7680;
- var ReplaceStencilOp = 7681;
- var IncrementStencilOp = 7682;
- var DecrementStencilOp = 7683;
- var IncrementWrapStencilOp = 34055;
- var DecrementWrapStencilOp = 34056;
- var InvertStencilOp = 5386;
-
- var NeverStencilFunc = 512;
- var LessStencilFunc = 513;
- var EqualStencilFunc = 514;
- var LessEqualStencilFunc = 515;
- var GreaterStencilFunc = 516;
- var NotEqualStencilFunc = 517;
- var GreaterEqualStencilFunc = 518;
- var AlwaysStencilFunc = 519;
+ x = ( x - min ) / ( max - min );
- /**
- * @author alteredq / http://alteredqualia.com/
- * @author mrdoob / http://mrdoob.com/
- */
+ return x * x * x * ( x * ( x * 6 - 15 ) + 10 );
- var _lut = [];
+}
- for ( var i = 0; i < 256; i ++ ) {
+// Random integer from interval
+function randInt( low, high ) {
- _lut[ i ] = ( i < 16 ? '0' : '' ) + ( i ).toString( 16 );
+ return low + Math.floor( Math.random() * ( high - low + 1 ) );
- }
+}
- var _Math = {
+// Random float from interval
+function randFloat( low, high ) {
- DEG2RAD: Math.PI / 180,
- RAD2DEG: 180 / Math.PI,
+ return low + Math.random() * ( high - low );
- generateUUID: function () {
+}
- // http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/21963136#21963136
+// Random float from <-range/2, range/2> interval
+function randFloatSpread( range ) {
- var d0 = Math.random() * 0xffffffff | 0;
- var d1 = Math.random() * 0xffffffff | 0;
- var d2 = Math.random() * 0xffffffff | 0;
- var d3 = Math.random() * 0xffffffff | 0;
- var uuid = _lut[ d0 & 0xff ] + _lut[ d0 >> 8 & 0xff ] + _lut[ d0 >> 16 & 0xff ] + _lut[ d0 >> 24 & 0xff ] + '-' +
- _lut[ d1 & 0xff ] + _lut[ d1 >> 8 & 0xff ] + '-' + _lut[ d1 >> 16 & 0x0f | 0x40 ] + _lut[ d1 >> 24 & 0xff ] + '-' +
- _lut[ d2 & 0x3f | 0x80 ] + _lut[ d2 >> 8 & 0xff ] + '-' + _lut[ d2 >> 16 & 0xff ] + _lut[ d2 >> 24 & 0xff ] +
- _lut[ d3 & 0xff ] + _lut[ d3 >> 8 & 0xff ] + _lut[ d3 >> 16 & 0xff ] + _lut[ d3 >> 24 & 0xff ];
+ return range * ( 0.5 - Math.random() );
- // .toUpperCase() here flattens concatenated strings to save heap memory space.
- return uuid.toUpperCase();
+}
- },
+// Deterministic pseudo-random float in the interval [ 0, 1 ]
+function seededRandom( s ) {
- clamp: function ( value, min, max ) {
+ if ( s !== undefined ) _seed = s;
- return Math.max( min, Math.min( max, value ) );
+ // Mulberry32 generator
- },
+ let t = _seed += 0x6D2B79F5;
- // compute euclidian modulo of m % n
- // https://en.wikipedia.org/wiki/Modulo_operation
+ t = Math.imul( t ^ t >>> 15, t | 1 );
- euclideanModulo: function ( n, m ) {
+ t ^= t + Math.imul( t ^ t >>> 7, t | 61 );
- return ( ( n % m ) + m ) % m;
+ return ( ( t ^ t >>> 14 ) >>> 0 ) / 4294967296;
- },
+}
- // Linear mapping from range to range
+function degToRad( degrees ) {
- mapLinear: function ( x, a1, a2, b1, b2 ) {
+ return degrees * DEG2RAD;
- return b1 + ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 );
+}
- },
+function radToDeg( radians ) {
- // https://en.wikipedia.org/wiki/Linear_interpolation
+ return radians * RAD2DEG;
- lerp: function ( x, y, t ) {
+}
- return ( 1 - t ) * x + t * y;
+function isPowerOfTwo( value ) {
- },
+ return ( value & ( value - 1 ) ) === 0 && value !== 0;
- // http://en.wikipedia.org/wiki/Smoothstep
+}
- smoothstep: function ( x, min, max ) {
+function ceilPowerOfTwo( value ) {
- if ( x <= min ) return 0;
- if ( x >= max ) return 1;
+ return Math.pow( 2, Math.ceil( Math.log( value ) / Math.LN2 ) );
- x = ( x - min ) / ( max - min );
+}
- return x * x * ( 3 - 2 * x );
+function floorPowerOfTwo( value ) {
- },
+ return Math.pow( 2, Math.floor( Math.log( value ) / Math.LN2 ) );
- smootherstep: function ( x, min, max ) {
+}
- if ( x <= min ) return 0;
- if ( x >= max ) return 1;
+function setQuaternionFromProperEuler( q, a, b, c, order ) {
- x = ( x - min ) / ( max - min );
+ // Intrinsic Proper Euler Angles - see https://en.wikipedia.org/wiki/Euler_angles
- return x * x * x * ( x * ( x * 6 - 15 ) + 10 );
+ // rotations are applied to the axes in the order specified by 'order'
+ // rotation by angle 'a' is applied first, then by angle 'b', then by angle 'c'
+ // angles are in radians
- },
+ const cos = Math.cos;
+ const sin = Math.sin;
- // Random integer from interval
+ const c2 = cos( b / 2 );
+ const s2 = sin( b / 2 );
- randInt: function ( low, high ) {
+ const c13 = cos( ( a + c ) / 2 );
+ const s13 = sin( ( a + c ) / 2 );
- return low + Math.floor( Math.random() * ( high - low + 1 ) );
+ const c1_3 = cos( ( a - c ) / 2 );
+ const s1_3 = sin( ( a - c ) / 2 );
- },
+ const c3_1 = cos( ( c - a ) / 2 );
+ const s3_1 = sin( ( c - a ) / 2 );
- // Random float from interval
+ switch ( order ) {
- randFloat: function ( low, high ) {
+ case 'XYX':
+ q.set( c2 * s13, s2 * c1_3, s2 * s1_3, c2 * c13 );
+ break;
- return low + Math.random() * ( high - low );
+ case 'YZY':
+ q.set( s2 * s1_3, c2 * s13, s2 * c1_3, c2 * c13 );
+ break;
- },
+ case 'ZXZ':
+ q.set( s2 * c1_3, s2 * s1_3, c2 * s13, c2 * c13 );
+ break;
- // Random float from <-range/2, range/2> interval
+ case 'XZX':
+ q.set( c2 * s13, s2 * s3_1, s2 * c3_1, c2 * c13 );
+ break;
- randFloatSpread: function ( range ) {
+ case 'YXY':
+ q.set( s2 * c3_1, c2 * s13, s2 * s3_1, c2 * c13 );
+ break;
- return range * ( 0.5 - Math.random() );
+ case 'ZYZ':
+ q.set( s2 * s3_1, s2 * c3_1, c2 * s13, c2 * c13 );
+ break;
- },
+ default:
+ console.warn( 'THREE.MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: ' + order );
- degToRad: function ( degrees ) {
+ }
- return degrees * _Math.DEG2RAD;
+}
- },
+function denormalize( value, array ) {
- radToDeg: function ( radians ) {
+ switch ( array.constructor ) {
- return radians * _Math.RAD2DEG;
+ case Float32Array:
- },
+ return value;
- isPowerOfTwo: function ( value ) {
+ case Uint32Array:
- return ( value & ( value - 1 ) ) === 0 && value !== 0;
+ return value / 4294967295.0;
- },
+ case Uint16Array:
- ceilPowerOfTwo: function ( value ) {
+ return value / 65535.0;
- return Math.pow( 2, Math.ceil( Math.log( value ) / Math.LN2 ) );
+ case Uint8Array:
- },
+ return value / 255.0;
- floorPowerOfTwo: function ( value ) {
+ case Int32Array:
- return Math.pow( 2, Math.floor( Math.log( value ) / Math.LN2 ) );
+ return Math.max( value / 2147483647.0, - 1.0 );
- }
+ case Int16Array:
- };
+ return Math.max( value / 32767.0, - 1.0 );
- /**
- * @author mrdoob / http://mrdoob.com/
- * @author philogb / http://blog.thejit.org/
- * @author egraether / http://egraether.com/
- * @author zz85 / http://www.lab4games.net/zz85/blog
- */
+ case Int8Array:
- function Vector2( x, y ) {
+ return Math.max( value / 127.0, - 1.0 );
- this.x = x || 0;
- this.y = y || 0;
+ default:
+
+ throw new Error( 'Invalid component type.' );
}
- Object.defineProperties( Vector2.prototype, {
+}
- "width": {
+function normalize( value, array ) {
- get: function () {
+ switch ( array.constructor ) {
- return this.x;
+ case Float32Array:
- },
+ return value;
- set: function ( value ) {
+ case Uint32Array:
- this.x = value;
+ return Math.round( value * 4294967295.0 );
- }
+ case Uint16Array:
- },
+ return Math.round( value * 65535.0 );
- "height": {
+ case Uint8Array:
- get: function () {
+ return Math.round( value * 255.0 );
- return this.y;
+ case Int32Array:
- },
+ return Math.round( value * 2147483647.0 );
- set: function ( value ) {
+ case Int16Array:
- this.y = value;
+ return Math.round( value * 32767.0 );
- }
+ case Int8Array:
- }
+ return Math.round( value * 127.0 );
- } );
+ default:
- Object.assign( Vector2.prototype, {
+ throw new Error( 'Invalid component type.' );
- isVector2: true,
+ }
- set: function ( x, y ) {
+}
- this.x = x;
- this.y = y;
+const MathUtils = {
+ DEG2RAD: DEG2RAD,
+ RAD2DEG: RAD2DEG,
+ generateUUID: generateUUID,
+ clamp: clamp,
+ euclideanModulo: euclideanModulo,
+ mapLinear: mapLinear,
+ inverseLerp: inverseLerp,
+ lerp: lerp,
+ damp: damp,
+ pingpong: pingpong,
+ smoothstep: smoothstep,
+ smootherstep: smootherstep,
+ randInt: randInt,
+ randFloat: randFloat,
+ randFloatSpread: randFloatSpread,
+ seededRandom: seededRandom,
+ degToRad: degToRad,
+ radToDeg: radToDeg,
+ isPowerOfTwo: isPowerOfTwo,
+ ceilPowerOfTwo: ceilPowerOfTwo,
+ floorPowerOfTwo: floorPowerOfTwo,
+ setQuaternionFromProperEuler: setQuaternionFromProperEuler,
+ normalize: normalize,
+ denormalize: denormalize
+};
- return this;
+class Vector2 {
- },
+ constructor( x = 0, y = 0 ) {
- setScalar: function ( scalar ) {
+ Vector2.prototype.isVector2 = true;
- this.x = scalar;
- this.y = scalar;
+ this.x = x;
+ this.y = y;
- return this;
+ }
- },
+ get width() {
- setX: function ( x ) {
+ return this.x;
- this.x = x;
+ }
- return this;
+ set width( value ) {
- },
+ this.x = value;
- setY: function ( y ) {
+ }
- this.y = y;
+ get height() {
- return this;
+ return this.y;
- },
+ }
- setComponent: function ( index, value ) {
+ set height( value ) {
- switch ( index ) {
+ this.y = value;
- case 0: this.x = value; break;
- case 1: this.y = value; break;
- default: throw new Error( 'index is out of range: ' + index );
+ }
- }
+ set( x, y ) {
- return this;
+ this.x = x;
+ this.y = y;
- },
+ return this;
- getComponent: function ( index ) {
+ }
- switch ( index ) {
+ setScalar( scalar ) {
- case 0: return this.x;
- case 1: return this.y;
- default: throw new Error( 'index is out of range: ' + index );
+ this.x = scalar;
+ this.y = scalar;
- }
+ return this;
- },
+ }
- clone: function () {
+ setX( x ) {
- return new this.constructor( this.x, this.y );
+ this.x = x;
- },
+ return this;
- copy: function ( v ) {
+ }
- this.x = v.x;
- this.y = v.y;
+ setY( y ) {
- return this;
+ this.y = y;
- },
+ return this;
- add: function ( v, w ) {
+ }
- if ( w !== undefined ) {
+ setComponent( index, value ) {
- console.warn( 'THREE.Vector2: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );
- return this.addVectors( v, w );
+ switch ( index ) {
- }
+ case 0: this.x = value; break;
+ case 1: this.y = value; break;
+ default: throw new Error( 'index is out of range: ' + index );
- this.x += v.x;
- this.y += v.y;
+ }
- return this;
+ return this;
- },
+ }
- addScalar: function ( s ) {
+ getComponent( index ) {
- this.x += s;
- this.y += s;
+ switch ( index ) {
- return this;
+ case 0: return this.x;
+ case 1: return this.y;
+ default: throw new Error( 'index is out of range: ' + index );
- },
+ }
- addVectors: function ( a, b ) {
+ }
- this.x = a.x + b.x;
- this.y = a.y + b.y;
+ clone() {
- return this;
+ return new this.constructor( this.x, this.y );
- },
+ }
- addScaledVector: function ( v, s ) {
+ copy( v ) {
- this.x += v.x * s;
- this.y += v.y * s;
+ this.x = v.x;
+ this.y = v.y;
- return this;
+ return this;
- },
+ }
- sub: function ( v, w ) {
+ add( v ) {
- if ( w !== undefined ) {
+ this.x += v.x;
+ this.y += v.y;
- console.warn( 'THREE.Vector2: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );
- return this.subVectors( v, w );
+ return this;
- }
+ }
- this.x -= v.x;
- this.y -= v.y;
+ addScalar( s ) {
- return this;
+ this.x += s;
+ this.y += s;
- },
+ return this;
- subScalar: function ( s ) {
+ }
- this.x -= s;
- this.y -= s;
+ addVectors( a, b ) {
- return this;
+ this.x = a.x + b.x;
+ this.y = a.y + b.y;
- },
+ return this;
- subVectors: function ( a, b ) {
+ }
- this.x = a.x - b.x;
- this.y = a.y - b.y;
+ addScaledVector( v, s ) {
- return this;
+ this.x += v.x * s;
+ this.y += v.y * s;
- },
+ return this;
- multiply: function ( v ) {
+ }
- this.x *= v.x;
- this.y *= v.y;
+ sub( v ) {
- return this;
+ this.x -= v.x;
+ this.y -= v.y;
- },
+ return this;
- multiplyScalar: function ( scalar ) {
+ }
- this.x *= scalar;
- this.y *= scalar;
+ subScalar( s ) {
- return this;
+ this.x -= s;
+ this.y -= s;
- },
+ return this;
- divide: function ( v ) {
+ }
- this.x /= v.x;
- this.y /= v.y;
+ subVectors( a, b ) {
- return this;
+ this.x = a.x - b.x;
+ this.y = a.y - b.y;
- },
+ return this;
- divideScalar: function ( scalar ) {
+ }
- return this.multiplyScalar( 1 / scalar );
+ multiply( v ) {
- },
+ this.x *= v.x;
+ this.y *= v.y;
- applyMatrix3: function ( m ) {
+ return this;
- var x = this.x, y = this.y;
- var e = m.elements;
+ }
- this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ];
- this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ];
+ multiplyScalar( scalar ) {
- return this;
+ this.x *= scalar;
+ this.y *= scalar;
- },
+ return this;
- min: function ( v ) {
+ }
- this.x = Math.min( this.x, v.x );
- this.y = Math.min( this.y, v.y );
+ divide( v ) {
- return this;
+ this.x /= v.x;
+ this.y /= v.y;
- },
+ return this;
- max: function ( v ) {
+ }
- this.x = Math.max( this.x, v.x );
- this.y = Math.max( this.y, v.y );
+ divideScalar( scalar ) {
- return this;
+ return this.multiplyScalar( 1 / scalar );
- },
+ }
- clamp: function ( min, max ) {
+ applyMatrix3( m ) {
- // assumes min < max, componentwise
+ const x = this.x, y = this.y;
+ const e = m.elements;
- this.x = Math.max( min.x, Math.min( max.x, this.x ) );
- this.y = Math.max( min.y, Math.min( max.y, this.y ) );
+ this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ];
+ this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ];
- return this;
+ return this;
- },
+ }
- clampScalar: function ( minVal, maxVal ) {
+ min( v ) {
- this.x = Math.max( minVal, Math.min( maxVal, this.x ) );
- this.y = Math.max( minVal, Math.min( maxVal, this.y ) );
+ this.x = Math.min( this.x, v.x );
+ this.y = Math.min( this.y, v.y );
- return this;
+ return this;
- },
+ }
- clampLength: function ( min, max ) {
+ max( v ) {
- var length = this.length();
+ this.x = Math.max( this.x, v.x );
+ this.y = Math.max( this.y, v.y );
- return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );
+ return this;
- },
+ }
- floor: function () {
+ clamp( min, max ) {
- this.x = Math.floor( this.x );
- this.y = Math.floor( this.y );
+ // assumes min < max, componentwise
- return this;
+ this.x = Math.max( min.x, Math.min( max.x, this.x ) );
+ this.y = Math.max( min.y, Math.min( max.y, this.y ) );
- },
+ return this;
- ceil: function () {
+ }
- this.x = Math.ceil( this.x );
- this.y = Math.ceil( this.y );
+ clampScalar( minVal, maxVal ) {
- return this;
+ this.x = Math.max( minVal, Math.min( maxVal, this.x ) );
+ this.y = Math.max( minVal, Math.min( maxVal, this.y ) );
- },
+ return this;
- round: function () {
+ }
- this.x = Math.round( this.x );
- this.y = Math.round( this.y );
+ clampLength( min, max ) {
- return this;
+ const length = this.length();
- },
+ return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );
- roundToZero: function () {
+ }
- this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );
- this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );
+ floor() {
- return this;
+ this.x = Math.floor( this.x );
+ this.y = Math.floor( this.y );
- },
+ return this;
- negate: function () {
+ }
- this.x = - this.x;
- this.y = - this.y;
+ ceil() {
- return this;
+ this.x = Math.ceil( this.x );
+ this.y = Math.ceil( this.y );
- },
+ return this;
- dot: function ( v ) {
+ }
- return this.x * v.x + this.y * v.y;
+ round() {
- },
+ this.x = Math.round( this.x );
+ this.y = Math.round( this.y );
- cross: function ( v ) {
+ return this;
- return this.x * v.y - this.y * v.x;
+ }
- },
+ roundToZero() {
- lengthSq: function () {
+ this.x = Math.trunc( this.x );
+ this.y = Math.trunc( this.y );
- return this.x * this.x + this.y * this.y;
+ return this;
- },
+ }
- length: function () {
+ negate() {
- return Math.sqrt( this.x * this.x + this.y * this.y );
+ this.x = - this.x;
+ this.y = - this.y;
- },
+ return this;
- manhattanLength: function () {
+ }
- return Math.abs( this.x ) + Math.abs( this.y );
+ dot( v ) {
- },
+ return this.x * v.x + this.y * v.y;
- normalize: function () {
+ }
- return this.divideScalar( this.length() || 1 );
+ cross( v ) {
- },
+ return this.x * v.y - this.y * v.x;
- angle: function () {
+ }
- // computes the angle in radians with respect to the positive x-axis
+ lengthSq() {
- var angle = Math.atan2( this.y, this.x );
+ return this.x * this.x + this.y * this.y;
- if ( angle < 0 ) angle += 2 * Math.PI;
+ }
- return angle;
+ length() {
- },
+ return Math.sqrt( this.x * this.x + this.y * this.y );
- distanceTo: function ( v ) {
+ }
- return Math.sqrt( this.distanceToSquared( v ) );
+ manhattanLength() {
- },
+ return Math.abs( this.x ) + Math.abs( this.y );
- distanceToSquared: function ( v ) {
+ }
- var dx = this.x - v.x, dy = this.y - v.y;
- return dx * dx + dy * dy;
+ normalize() {
- },
+ return this.divideScalar( this.length() || 1 );
- manhattanDistanceTo: function ( v ) {
+ }
- return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y );
+ angle() {
- },
+ // computes the angle in radians with respect to the positive x-axis
- setLength: function ( length ) {
+ const angle = Math.atan2( - this.y, - this.x ) + Math.PI;
- return this.normalize().multiplyScalar( length );
+ return angle;
- },
+ }
- lerp: function ( v, alpha ) {
+ angleTo( v ) {
- this.x += ( v.x - this.x ) * alpha;
- this.y += ( v.y - this.y ) * alpha;
+ const denominator = Math.sqrt( this.lengthSq() * v.lengthSq() );
- return this;
+ if ( denominator === 0 ) return Math.PI / 2;
- },
+ const theta = this.dot( v ) / denominator;
- lerpVectors: function ( v1, v2, alpha ) {
+ // clamp, to handle numerical problems
- return this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 );
+ return Math.acos( clamp( theta, - 1, 1 ) );
- },
+ }
- equals: function ( v ) {
+ distanceTo( v ) {
- return ( ( v.x === this.x ) && ( v.y === this.y ) );
+ return Math.sqrt( this.distanceToSquared( v ) );
- },
+ }
- fromArray: function ( array, offset ) {
+ distanceToSquared( v ) {
- if ( offset === undefined ) offset = 0;
+ const dx = this.x - v.x, dy = this.y - v.y;
+ return dx * dx + dy * dy;
- this.x = array[ offset ];
- this.y = array[ offset + 1 ];
+ }
- return this;
+ manhattanDistanceTo( v ) {
- },
+ return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y );
- toArray: function ( array, offset ) {
+ }
- if ( array === undefined ) array = [];
- if ( offset === undefined ) offset = 0;
+ setLength( length ) {
- array[ offset ] = this.x;
- array[ offset + 1 ] = this.y;
+ return this.normalize().multiplyScalar( length );
- return array;
+ }
- },
+ lerp( v, alpha ) {
- fromBufferAttribute: function ( attribute, index, offset ) {
+ this.x += ( v.x - this.x ) * alpha;
+ this.y += ( v.y - this.y ) * alpha;
- if ( offset !== undefined ) {
+ return this;
- console.warn( 'THREE.Vector2: offset has been removed from .fromBufferAttribute().' );
+ }
- }
+ lerpVectors( v1, v2, alpha ) {
- this.x = attribute.getX( index );
- this.y = attribute.getY( index );
+ this.x = v1.x + ( v2.x - v1.x ) * alpha;
+ this.y = v1.y + ( v2.y - v1.y ) * alpha;
- return this;
+ return this;
- },
+ }
- rotateAround: function ( center, angle ) {
+ equals( v ) {
- var c = Math.cos( angle ), s = Math.sin( angle );
+ return ( ( v.x === this.x ) && ( v.y === this.y ) );
- var x = this.x - center.x;
- var y = this.y - center.y;
+ }
- this.x = x * c - y * s + center.x;
- this.y = x * s + y * c + center.y;
+ fromArray( array, offset = 0 ) {
- return this;
+ this.x = array[ offset ];
+ this.y = array[ offset + 1 ];
- }
+ return this;
- } );
+ }
- /**
- * @author mikael emtinger / http://gomo.se/
- * @author alteredq / http://alteredqualia.com/
- * @author WestLangley / http://github.com/WestLangley
- * @author bhouston / http://clara.io
- */
+ toArray( array = [], offset = 0 ) {
- function Quaternion( x, y, z, w ) {
+ array[ offset ] = this.x;
+ array[ offset + 1 ] = this.y;
- this._x = x || 0;
- this._y = y || 0;
- this._z = z || 0;
- this._w = ( w !== undefined ) ? w : 1;
+ return array;
}
- Object.assign( Quaternion, {
+ fromBufferAttribute( attribute, index ) {
- slerp: function ( qa, qb, qm, t ) {
+ this.x = attribute.getX( index );
+ this.y = attribute.getY( index );
- return qm.copy( qa ).slerp( qb, t );
+ return this;
- },
+ }
- slerpFlat: function ( dst, dstOffset, src0, srcOffset0, src1, srcOffset1, t ) {
+ rotateAround( center, angle ) {
- // fuzz-free, array-based Quaternion SLERP operation
+ const c = Math.cos( angle ), s = Math.sin( angle );
- var x0 = src0[ srcOffset0 + 0 ],
- y0 = src0[ srcOffset0 + 1 ],
- z0 = src0[ srcOffset0 + 2 ],
- w0 = src0[ srcOffset0 + 3 ],
+ const x = this.x - center.x;
+ const y = this.y - center.y;
- x1 = src1[ srcOffset1 + 0 ],
- y1 = src1[ srcOffset1 + 1 ],
- z1 = src1[ srcOffset1 + 2 ],
- w1 = src1[ srcOffset1 + 3 ];
+ this.x = x * c - y * s + center.x;
+ this.y = x * s + y * c + center.y;
- if ( w0 !== w1 || x0 !== x1 || y0 !== y1 || z0 !== z1 ) {
+ return this;
- var s = 1 - t,
+ }
- cos = x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1,
+ random() {
- dir = ( cos >= 0 ? 1 : - 1 ),
- sqrSin = 1 - cos * cos;
+ this.x = Math.random();
+ this.y = Math.random();
- // Skip the Slerp for tiny steps to avoid numeric problems:
- if ( sqrSin > Number.EPSILON ) {
+ return this;
- var sin = Math.sqrt( sqrSin ),
- len = Math.atan2( sin, cos * dir );
+ }
- s = Math.sin( s * len ) / sin;
- t = Math.sin( t * len ) / sin;
+ *[ Symbol.iterator ]() {
- }
+ yield this.x;
+ yield this.y;
- var tDir = t * dir;
+ }
- x0 = x0 * s + x1 * tDir;
- y0 = y0 * s + y1 * tDir;
- z0 = z0 * s + z1 * tDir;
- w0 = w0 * s + w1 * tDir;
+}
- // Normalize in case we just did a lerp:
- if ( s === 1 - t ) {
+class Matrix3 {
- var f = 1 / Math.sqrt( x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0 );
+ constructor( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) {
- x0 *= f;
- y0 *= f;
- z0 *= f;
- w0 *= f;
+ Matrix3.prototype.isMatrix3 = true;
- }
+ this.elements = [
- }
+ 1, 0, 0,
+ 0, 1, 0,
+ 0, 0, 1
- dst[ dstOffset ] = x0;
- dst[ dstOffset + 1 ] = y0;
- dst[ dstOffset + 2 ] = z0;
- dst[ dstOffset + 3 ] = w0;
+ ];
+
+ if ( n11 !== undefined ) {
+
+ this.set( n11, n12, n13, n21, n22, n23, n31, n32, n33 );
}
- } );
+ }
- Object.defineProperties( Quaternion.prototype, {
+ set( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) {
- x: {
+ const te = this.elements;
- get: function () {
+ te[ 0 ] = n11; te[ 1 ] = n21; te[ 2 ] = n31;
+ te[ 3 ] = n12; te[ 4 ] = n22; te[ 5 ] = n32;
+ te[ 6 ] = n13; te[ 7 ] = n23; te[ 8 ] = n33;
- return this._x;
+ return this;
- },
+ }
- set: function ( value ) {
+ identity() {
- this._x = value;
- this._onChangeCallback();
+ this.set(
- }
+ 1, 0, 0,
+ 0, 1, 0,
+ 0, 0, 1
- },
+ );
- y: {
+ return this;
- get: function () {
+ }
- return this._y;
+ copy( m ) {
- },
+ const te = this.elements;
+ const me = m.elements;
- set: function ( value ) {
+ te[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ];
+ te[ 3 ] = me[ 3 ]; te[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ];
+ te[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ]; te[ 8 ] = me[ 8 ];
- this._y = value;
- this._onChangeCallback();
+ return this;
- }
+ }
- },
+ extractBasis( xAxis, yAxis, zAxis ) {
- z: {
+ xAxis.setFromMatrix3Column( this, 0 );
+ yAxis.setFromMatrix3Column( this, 1 );
+ zAxis.setFromMatrix3Column( this, 2 );
- get: function () {
+ return this;
- return this._z;
+ }
- },
+ setFromMatrix4( m ) {
- set: function ( value ) {
+ const me = m.elements;
- this._z = value;
- this._onChangeCallback();
+ this.set(
- }
+ me[ 0 ], me[ 4 ], me[ 8 ],
+ me[ 1 ], me[ 5 ], me[ 9 ],
+ me[ 2 ], me[ 6 ], me[ 10 ]
- },
+ );
- w: {
+ return this;
- get: function () {
+ }
- return this._w;
+ multiply( m ) {
- },
+ return this.multiplyMatrices( this, m );
- set: function ( value ) {
+ }
- this._w = value;
- this._onChangeCallback();
+ premultiply( m ) {
- }
+ return this.multiplyMatrices( m, this );
- }
+ }
- } );
+ multiplyMatrices( a, b ) {
- Object.assign( Quaternion.prototype, {
+ const ae = a.elements;
+ const be = b.elements;
+ const te = this.elements;
- isQuaternion: true,
+ const a11 = ae[ 0 ], a12 = ae[ 3 ], a13 = ae[ 6 ];
+ const a21 = ae[ 1 ], a22 = ae[ 4 ], a23 = ae[ 7 ];
+ const a31 = ae[ 2 ], a32 = ae[ 5 ], a33 = ae[ 8 ];
- set: function ( x, y, z, w ) {
+ const b11 = be[ 0 ], b12 = be[ 3 ], b13 = be[ 6 ];
+ const b21 = be[ 1 ], b22 = be[ 4 ], b23 = be[ 7 ];
+ const b31 = be[ 2 ], b32 = be[ 5 ], b33 = be[ 8 ];
- this._x = x;
- this._y = y;
- this._z = z;
- this._w = w;
+ te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31;
+ te[ 3 ] = a11 * b12 + a12 * b22 + a13 * b32;
+ te[ 6 ] = a11 * b13 + a12 * b23 + a13 * b33;
- this._onChangeCallback();
+ te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31;
+ te[ 4 ] = a21 * b12 + a22 * b22 + a23 * b32;
+ te[ 7 ] = a21 * b13 + a22 * b23 + a23 * b33;
- return this;
+ te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31;
+ te[ 5 ] = a31 * b12 + a32 * b22 + a33 * b32;
+ te[ 8 ] = a31 * b13 + a32 * b23 + a33 * b33;
- },
+ return this;
- clone: function () {
+ }
- return new this.constructor( this._x, this._y, this._z, this._w );
+ multiplyScalar( s ) {
- },
+ const te = this.elements;
- copy: function ( quaternion ) {
+ te[ 0 ] *= s; te[ 3 ] *= s; te[ 6 ] *= s;
+ te[ 1 ] *= s; te[ 4 ] *= s; te[ 7 ] *= s;
+ te[ 2 ] *= s; te[ 5 ] *= s; te[ 8 ] *= s;
- this._x = quaternion.x;
- this._y = quaternion.y;
- this._z = quaternion.z;
- this._w = quaternion.w;
+ return this;
- this._onChangeCallback();
+ }
- return this;
+ determinant() {
- },
+ const te = this.elements;
+
+ const a = te[ 0 ], b = te[ 1 ], c = te[ 2 ],
+ d = te[ 3 ], e = te[ 4 ], f = te[ 5 ],
+ g = te[ 6 ], h = te[ 7 ], i = te[ 8 ];
- setFromEuler: function ( euler, update ) {
+ return a * e * i - a * f * h - b * d * i + b * f * g + c * d * h - c * e * g;
- if ( ! ( euler && euler.isEuler ) ) {
+ }
- throw new Error( 'THREE.Quaternion: .setFromEuler() now expects an Euler rotation rather than a Vector3 and order.' );
+ invert() {
- }
+ const te = this.elements,
- var x = euler._x, y = euler._y, z = euler._z, order = euler.order;
+ n11 = te[ 0 ], n21 = te[ 1 ], n31 = te[ 2 ],
+ n12 = te[ 3 ], n22 = te[ 4 ], n32 = te[ 5 ],
+ n13 = te[ 6 ], n23 = te[ 7 ], n33 = te[ 8 ],
- // http://www.mathworks.com/matlabcentral/fileexchange/
- // 20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/
- // content/SpinCalc.m
+ t11 = n33 * n22 - n32 * n23,
+ t12 = n32 * n13 - n33 * n12,
+ t13 = n23 * n12 - n22 * n13,
- var cos = Math.cos;
- var sin = Math.sin;
+ det = n11 * t11 + n21 * t12 + n31 * t13;
- var c1 = cos( x / 2 );
- var c2 = cos( y / 2 );
- var c3 = cos( z / 2 );
+ if ( det === 0 ) return this.set( 0, 0, 0, 0, 0, 0, 0, 0, 0 );
- var s1 = sin( x / 2 );
- var s2 = sin( y / 2 );
- var s3 = sin( z / 2 );
+ const detInv = 1 / det;
- if ( order === 'XYZ' ) {
+ te[ 0 ] = t11 * detInv;
+ te[ 1 ] = ( n31 * n23 - n33 * n21 ) * detInv;
+ te[ 2 ] = ( n32 * n21 - n31 * n22 ) * detInv;
- this._x = s1 * c2 * c3 + c1 * s2 * s3;
- this._y = c1 * s2 * c3 - s1 * c2 * s3;
- this._z = c1 * c2 * s3 + s1 * s2 * c3;
- this._w = c1 * c2 * c3 - s1 * s2 * s3;
+ te[ 3 ] = t12 * detInv;
+ te[ 4 ] = ( n33 * n11 - n31 * n13 ) * detInv;
+ te[ 5 ] = ( n31 * n12 - n32 * n11 ) * detInv;
- } else if ( order === 'YXZ' ) {
+ te[ 6 ] = t13 * detInv;
+ te[ 7 ] = ( n21 * n13 - n23 * n11 ) * detInv;
+ te[ 8 ] = ( n22 * n11 - n21 * n12 ) * detInv;
- this._x = s1 * c2 * c3 + c1 * s2 * s3;
- this._y = c1 * s2 * c3 - s1 * c2 * s3;
- this._z = c1 * c2 * s3 - s1 * s2 * c3;
- this._w = c1 * c2 * c3 + s1 * s2 * s3;
+ return this;
- } else if ( order === 'ZXY' ) {
+ }
- this._x = s1 * c2 * c3 - c1 * s2 * s3;
- this._y = c1 * s2 * c3 + s1 * c2 * s3;
- this._z = c1 * c2 * s3 + s1 * s2 * c3;
- this._w = c1 * c2 * c3 - s1 * s2 * s3;
+ transpose() {
- } else if ( order === 'ZYX' ) {
+ let tmp;
+ const m = this.elements;
- this._x = s1 * c2 * c3 - c1 * s2 * s3;
- this._y = c1 * s2 * c3 + s1 * c2 * s3;
- this._z = c1 * c2 * s3 - s1 * s2 * c3;
- this._w = c1 * c2 * c3 + s1 * s2 * s3;
+ tmp = m[ 1 ]; m[ 1 ] = m[ 3 ]; m[ 3 ] = tmp;
+ tmp = m[ 2 ]; m[ 2 ] = m[ 6 ]; m[ 6 ] = tmp;
+ tmp = m[ 5 ]; m[ 5 ] = m[ 7 ]; m[ 7 ] = tmp;
- } else if ( order === 'YZX' ) {
+ return this;
- this._x = s1 * c2 * c3 + c1 * s2 * s3;
- this._y = c1 * s2 * c3 + s1 * c2 * s3;
- this._z = c1 * c2 * s3 - s1 * s2 * c3;
- this._w = c1 * c2 * c3 - s1 * s2 * s3;
+ }
- } else if ( order === 'XZY' ) {
+ getNormalMatrix( matrix4 ) {
- this._x = s1 * c2 * c3 - c1 * s2 * s3;
- this._y = c1 * s2 * c3 - s1 * c2 * s3;
- this._z = c1 * c2 * s3 + s1 * s2 * c3;
- this._w = c1 * c2 * c3 + s1 * s2 * s3;
+ return this.setFromMatrix4( matrix4 ).invert().transpose();
- }
+ }
- if ( update !== false ) this._onChangeCallback();
+ transposeIntoArray( r ) {
- return this;
+ const m = this.elements;
- },
+ r[ 0 ] = m[ 0 ];
+ r[ 1 ] = m[ 3 ];
+ r[ 2 ] = m[ 6 ];
+ r[ 3 ] = m[ 1 ];
+ r[ 4 ] = m[ 4 ];
+ r[ 5 ] = m[ 7 ];
+ r[ 6 ] = m[ 2 ];
+ r[ 7 ] = m[ 5 ];
+ r[ 8 ] = m[ 8 ];
- setFromAxisAngle: function ( axis, angle ) {
+ return this;
- // http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm
+ }
- // assumes axis is normalized
+ setUvTransform( tx, ty, sx, sy, rotation, cx, cy ) {
- var halfAngle = angle / 2, s = Math.sin( halfAngle );
+ const c = Math.cos( rotation );
+ const s = Math.sin( rotation );
- this._x = axis.x * s;
- this._y = axis.y * s;
- this._z = axis.z * s;
- this._w = Math.cos( halfAngle );
+ 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
+ );
- this._onChangeCallback();
+ return this;
- return this;
+ }
- },
+ //
- setFromRotationMatrix: function ( m ) {
+ scale( sx, sy ) {
- // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm
+ this.premultiply( _m3.makeScale( sx, sy ) );
- // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
+ return this;
+
+ }
- var te = m.elements,
+ rotate( theta ) {
- m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ],
- m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ],
- m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ],
+ this.premultiply( _m3.makeRotation( - theta ) );
- trace = m11 + m22 + m33,
- s;
+ return this;
- if ( trace > 0 ) {
+ }
- s = 0.5 / Math.sqrt( trace + 1.0 );
+ translate( tx, ty ) {
- this._w = 0.25 / s;
- this._x = ( m32 - m23 ) * s;
- this._y = ( m13 - m31 ) * s;
- this._z = ( m21 - m12 ) * s;
+ this.premultiply( _m3.makeTranslation( tx, ty ) );
- } else if ( m11 > m22 && m11 > m33 ) {
+ return this;
- s = 2.0 * Math.sqrt( 1.0 + m11 - m22 - m33 );
+ }
- this._w = ( m32 - m23 ) / s;
- this._x = 0.25 * s;
- this._y = ( m12 + m21 ) / s;
- this._z = ( m13 + m31 ) / s;
+ // for 2D Transforms
- } else if ( m22 > m33 ) {
+ makeTranslation( x, y ) {
- s = 2.0 * Math.sqrt( 1.0 + m22 - m11 - m33 );
+ if ( x.isVector2 ) {
- this._w = ( m13 - m31 ) / s;
- this._x = ( m12 + m21 ) / s;
- this._y = 0.25 * s;
- this._z = ( m23 + m32 ) / s;
+ this.set(
- } else {
+ 1, 0, x.x,
+ 0, 1, x.y,
+ 0, 0, 1
- s = 2.0 * Math.sqrt( 1.0 + m33 - m11 - m22 );
+ );
- this._w = ( m21 - m12 ) / s;
- this._x = ( m13 + m31 ) / s;
- this._y = ( m23 + m32 ) / s;
- this._z = 0.25 * s;
+ } else {
- }
+ this.set(
- this._onChangeCallback();
+ 1, 0, x,
+ 0, 1, y,
+ 0, 0, 1
- return this;
+ );
- },
+ }
- setFromUnitVectors: function ( vFrom, vTo ) {
+ return this;
- // assumes direction vectors vFrom and vTo are normalized
+ }
- var EPS = 0.000001;
+ makeRotation( theta ) {
- var r = vFrom.dot( vTo ) + 1;
+ // counterclockwise
- if ( r < EPS ) {
+ const c = Math.cos( theta );
+ const s = Math.sin( theta );
- r = 0;
+ this.set(
- if ( Math.abs( vFrom.x ) > Math.abs( vFrom.z ) ) {
+ c, - s, 0,
+ s, c, 0,
+ 0, 0, 1
- this._x = - vFrom.y;
- this._y = vFrom.x;
- this._z = 0;
- this._w = r;
+ );
- } else {
+ return this;
- this._x = 0;
- this._y = - vFrom.z;
- this._z = vFrom.y;
- this._w = r;
+ }
- }
+ makeScale( x, y ) {
- } else {
+ this.set(
- // crossVectors( vFrom, vTo ); // inlined to avoid cyclic dependency on Vector3
+ x, 0, 0,
+ 0, y, 0,
+ 0, 0, 1
- this._x = vFrom.y * vTo.z - vFrom.z * vTo.y;
- this._y = vFrom.z * vTo.x - vFrom.x * vTo.z;
- this._z = vFrom.x * vTo.y - vFrom.y * vTo.x;
- this._w = r;
+ );
- }
+ return this;
- return this.normalize();
+ }
- },
+ //
- angleTo: function ( q ) {
+ equals( matrix ) {
- return 2 * Math.acos( Math.abs( _Math.clamp( this.dot( q ), - 1, 1 ) ) );
+ const te = this.elements;
+ const me = matrix.elements;
- },
+ for ( let i = 0; i < 9; i ++ ) {
- rotateTowards: function ( q, step ) {
+ if ( te[ i ] !== me[ i ] ) return false;
- var angle = this.angleTo( q );
+ }
- if ( angle === 0 ) return this;
+ return true;
- var t = Math.min( 1, step / angle );
+ }
- this.slerp( q, t );
+ fromArray( array, offset = 0 ) {
- return this;
+ for ( let i = 0; i < 9; i ++ ) {
- },
+ this.elements[ i ] = array[ i + offset ];
- inverse: function () {
+ }
- // quaternion is assumed to have unit length
+ return this;
- return this.conjugate();
+ }
- },
+ toArray( array = [], offset = 0 ) {
- conjugate: function () {
+ const te = this.elements;
- this._x *= - 1;
- this._y *= - 1;
- this._z *= - 1;
+ array[ offset ] = te[ 0 ];
+ array[ offset + 1 ] = te[ 1 ];
+ array[ offset + 2 ] = te[ 2 ];
- this._onChangeCallback();
+ array[ offset + 3 ] = te[ 3 ];
+ array[ offset + 4 ] = te[ 4 ];
+ array[ offset + 5 ] = te[ 5 ];
- return this;
+ array[ offset + 6 ] = te[ 6 ];
+ array[ offset + 7 ] = te[ 7 ];
+ array[ offset + 8 ] = te[ 8 ];
- },
+ return array;
- dot: function ( v ) {
+ }
- return this._x * v._x + this._y * v._y + this._z * v._z + this._w * v._w;
+ clone() {
- },
+ return new this.constructor().fromArray( this.elements );
- lengthSq: function () {
+ }
- return this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w;
+}
- },
+const _m3 = /*@__PURE__*/ new Matrix3();
- length: function () {
+function arrayNeedsUint32( array ) {
- return Math.sqrt( this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w );
+ // assumes larger values usually on last
- },
+ for ( let i = array.length - 1; i >= 0; -- i ) {
- normalize: function () {
+ if ( array[ i ] >= 65535 ) return true; // account for PRIMITIVE_RESTART_FIXED_INDEX, #24565
- var l = this.length();
+ }
- if ( l === 0 ) {
+ return false;
- this._x = 0;
- this._y = 0;
- this._z = 0;
- this._w = 1;
+}
- } else {
+const TYPED_ARRAYS = {
+ Int8Array: Int8Array,
+ Uint8Array: Uint8Array,
+ Uint8ClampedArray: Uint8ClampedArray,
+ Int16Array: Int16Array,
+ Uint16Array: Uint16Array,
+ Int32Array: Int32Array,
+ Uint32Array: Uint32Array,
+ Float32Array: Float32Array,
+ Float64Array: Float64Array
+};
- l = 1 / l;
+function getTypedArray( type, buffer ) {
- this._x = this._x * l;
- this._y = this._y * l;
- this._z = this._z * l;
- this._w = this._w * l;
+ return new TYPED_ARRAYS[ type ]( buffer );
- }
+}
- this._onChangeCallback();
+function createElementNS( name ) {
- return this;
+ return document.createElementNS( 'http://www.w3.org/1999/xhtml', name );
- },
+}
- multiply: function ( q, p ) {
+function createCanvasElement() {
- if ( p !== undefined ) {
+ const canvas = createElementNS( 'canvas' );
+ canvas.style.display = 'block';
+ return canvas;
- console.warn( 'THREE.Quaternion: .multiply() now only accepts one argument. Use .multiplyQuaternions( a, b ) instead.' );
- return this.multiplyQuaternions( q, p );
+}
- }
+const _cache = {};
- return this.multiplyQuaternions( this, q );
+function warnOnce( message ) {
- },
+ if ( message in _cache ) return;
- premultiply: function ( q ) {
+ _cache[ message ] = true;
- return this.multiplyQuaternions( q, this );
+ console.warn( message );
- },
+}
- multiplyQuaternions: function ( a, b ) {
+/**
+ * Matrices converting P3 <-> Rec. 709 primaries, without gamut mapping
+ * or clipping. Based on W3C specifications for sRGB and Display P3,
+ * and ICC specifications for the D50 connection space. Values in/out
+ * are _linear_ sRGB and _linear_ Display P3.
+ *
+ * Note that both sRGB and Display P3 use the sRGB transfer functions.
+ *
+ * Reference:
+ * - http://www.russellcottrell.com/photo/matrixCalculator.htm
+ */
- // from http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm
+const LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 = /*@__PURE__*/ new Matrix3().set(
+ 0.8224621, 0.177538, 0.0,
+ 0.0331941, 0.9668058, 0.0,
+ 0.0170827, 0.0723974, 0.9105199,
+);
- var qax = a._x, qay = a._y, qaz = a._z, qaw = a._w;
- var qbx = b._x, qby = b._y, qbz = b._z, qbw = b._w;
+const LINEAR_DISPLAY_P3_TO_LINEAR_SRGB = /*@__PURE__*/ new Matrix3().set(
+ 1.2249401, - 0.2249404, 0.0,
+ - 0.0420569, 1.0420571, 0.0,
+ - 0.0196376, - 0.0786361, 1.0982735
+);
- this._x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby;
- this._y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz;
- this._z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx;
- this._w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz;
+/**
+ * Defines supported color spaces by transfer function and primaries,
+ * and provides conversions to/from the Linear-sRGB reference space.
+ */
+const COLOR_SPACES = {
+ [ LinearSRGBColorSpace ]: {
+ transfer: LinearTransfer,
+ primaries: Rec709Primaries,
+ toReference: ( color ) => color,
+ fromReference: ( color ) => color,
+ },
+ [ SRGBColorSpace ]: {
+ transfer: SRGBTransfer,
+ primaries: Rec709Primaries,
+ toReference: ( color ) => color.convertSRGBToLinear(),
+ fromReference: ( color ) => color.convertLinearToSRGB(),
+ },
+ [ LinearDisplayP3ColorSpace ]: {
+ transfer: LinearTransfer,
+ primaries: P3Primaries,
+ toReference: ( color ) => color.applyMatrix3( LINEAR_DISPLAY_P3_TO_LINEAR_SRGB ),
+ fromReference: ( color ) => color.applyMatrix3( LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 ),
+ },
+ [ DisplayP3ColorSpace ]: {
+ transfer: SRGBTransfer,
+ primaries: P3Primaries,
+ toReference: ( color ) => color.convertSRGBToLinear().applyMatrix3( LINEAR_DISPLAY_P3_TO_LINEAR_SRGB ),
+ fromReference: ( color ) => color.applyMatrix3( LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 ).convertLinearToSRGB(),
+ },
+};
- this._onChangeCallback();
+const SUPPORTED_WORKING_COLOR_SPACES = new Set( [ LinearSRGBColorSpace, LinearDisplayP3ColorSpace ] );
- return this;
+const ColorManagement = {
- },
+ enabled: true,
- slerp: function ( qb, t ) {
+ _workingColorSpace: LinearSRGBColorSpace,
- if ( t === 0 ) return this;
- if ( t === 1 ) return this.copy( qb );
+ get legacyMode() {
- var x = this._x, y = this._y, z = this._z, w = this._w;
+ console.warn( 'THREE.ColorManagement: .legacyMode=false renamed to .enabled=true in r150.' );
- // http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/
+ return ! this.enabled;
- var cosHalfTheta = w * qb._w + x * qb._x + y * qb._y + z * qb._z;
+ },
- if ( cosHalfTheta < 0 ) {
+ set legacyMode( legacyMode ) {
- this._w = - qb._w;
- this._x = - qb._x;
- this._y = - qb._y;
- this._z = - qb._z;
+ console.warn( 'THREE.ColorManagement: .legacyMode=false renamed to .enabled=true in r150.' );
- cosHalfTheta = - cosHalfTheta;
+ this.enabled = ! legacyMode;
- } else {
+ },
- this.copy( qb );
+ get workingColorSpace() {
- }
+ return this._workingColorSpace;
- if ( cosHalfTheta >= 1.0 ) {
+ },
- this._w = w;
- this._x = x;
- this._y = y;
- this._z = z;
+ set workingColorSpace( colorSpace ) {
- return this;
+ if ( ! SUPPORTED_WORKING_COLOR_SPACES.has( colorSpace ) ) {
- }
+ throw new Error( `Unsupported working color space, "${ colorSpace }".` );
- var sqrSinHalfTheta = 1.0 - cosHalfTheta * cosHalfTheta;
+ }
- if ( sqrSinHalfTheta <= Number.EPSILON ) {
+ this._workingColorSpace = colorSpace;
- var s = 1 - t;
- this._w = s * w + t * this._w;
- this._x = s * x + t * this._x;
- this._y = s * y + t * this._y;
- this._z = s * z + t * this._z;
+ },
- this.normalize();
- this._onChangeCallback();
+ convert: function ( color, sourceColorSpace, targetColorSpace ) {
- return this;
+ if ( this.enabled === false || sourceColorSpace === targetColorSpace || ! sourceColorSpace || ! targetColorSpace ) {
- }
+ return color;
- var sinHalfTheta = Math.sqrt( sqrSinHalfTheta );
- var halfTheta = Math.atan2( sinHalfTheta, cosHalfTheta );
- var ratioA = Math.sin( ( 1 - t ) * halfTheta ) / sinHalfTheta,
- ratioB = Math.sin( t * halfTheta ) / sinHalfTheta;
+ }
- this._w = ( w * ratioA + this._w * ratioB );
- this._x = ( x * ratioA + this._x * ratioB );
- this._y = ( y * ratioA + this._y * ratioB );
- this._z = ( z * ratioA + this._z * ratioB );
+ const sourceToReference = COLOR_SPACES[ sourceColorSpace ].toReference;
+ const targetFromReference = COLOR_SPACES[ targetColorSpace ].fromReference;
- this._onChangeCallback();
+ return targetFromReference( sourceToReference( color ) );
- return this;
+ },
- },
+ fromWorkingColorSpace: function ( color, targetColorSpace ) {
- equals: function ( quaternion ) {
+ return this.convert( color, this._workingColorSpace, targetColorSpace );
- return ( quaternion._x === this._x ) && ( quaternion._y === this._y ) && ( quaternion._z === this._z ) && ( quaternion._w === this._w );
+ },
- },
+ toWorkingColorSpace: function ( color, sourceColorSpace ) {
- fromArray: function ( array, offset ) {
+ return this.convert( color, sourceColorSpace, this._workingColorSpace );
- if ( offset === undefined ) offset = 0;
+ },
- this._x = array[ offset ];
- this._y = array[ offset + 1 ];
- this._z = array[ offset + 2 ];
- this._w = array[ offset + 3 ];
+ getPrimaries: function ( colorSpace ) {
- this._onChangeCallback();
+ return COLOR_SPACES[ colorSpace ].primaries;
- return this;
+ },
- },
+ getTransfer: function ( colorSpace ) {
- toArray: function ( array, offset ) {
+ if ( colorSpace === NoColorSpace ) return LinearTransfer;
- if ( array === undefined ) array = [];
- if ( offset === undefined ) offset = 0;
+ return COLOR_SPACES[ colorSpace ].transfer;
- array[ offset ] = this._x;
- array[ offset + 1 ] = this._y;
- array[ offset + 2 ] = this._z;
- array[ offset + 3 ] = this._w;
+ },
- return array;
+};
- },
- _onChange: function ( callback ) {
+function SRGBToLinear( c ) {
- this._onChangeCallback = callback;
+ return ( c < 0.04045 ) ? c * 0.0773993808 : Math.pow( c * 0.9478672986 + 0.0521327014, 2.4 );
- return this;
+}
- },
+function LinearToSRGB( c ) {
- _onChangeCallback: function () {}
+ return ( c < 0.0031308 ) ? c * 12.92 : 1.055 * ( Math.pow( c, 0.41666 ) ) - 0.055;
- } );
+}
- /**
- * @author mrdoob / http://mrdoob.com/
- * @author kile / http://kile.stravaganza.org/
- * @author philogb / http://blog.thejit.org/
- * @author mikael emtinger / http://gomo.se/
- * @author egraether / http://egraether.com/
- * @author WestLangley / http://github.com/WestLangley
- */
+let _canvas;
- var _vector = new Vector3();
- var _quaternion = new Quaternion();
+class ImageUtils {
- function Vector3( x, y, z ) {
+ static getDataURL( image ) {
- this.x = x || 0;
- this.y = y || 0;
- this.z = z || 0;
+ if ( /^data:/i.test( image.src ) ) {
- }
+ return image.src;
- Object.assign( Vector3.prototype, {
+ }
- isVector3: true,
+ if ( typeof HTMLCanvasElement === 'undefined' ) {
- set: function ( x, y, z ) {
+ return image.src;
- this.x = x;
- this.y = y;
- this.z = z;
+ }
- return this;
+ let canvas;
- },
+ if ( image instanceof HTMLCanvasElement ) {
- setScalar: function ( scalar ) {
+ canvas = image;
- this.x = scalar;
- this.y = scalar;
- this.z = scalar;
+ } else {
- return this;
+ if ( _canvas === undefined ) _canvas = createElementNS( 'canvas' );
- },
+ _canvas.width = image.width;
+ _canvas.height = image.height;
- setX: function ( x ) {
+ const context = _canvas.getContext( '2d' );
- this.x = x;
+ if ( image instanceof ImageData ) {
- return this;
+ context.putImageData( image, 0, 0 );
- },
+ } else {
- setY: function ( y ) {
+ context.drawImage( image, 0, 0, image.width, image.height );
- this.y = y;
+ }
- return this;
+ canvas = _canvas;
- },
+ }
- setZ: function ( z ) {
+ if ( canvas.width > 2048 || canvas.height > 2048 ) {
- this.z = z;
+ console.warn( 'THREE.ImageUtils.getDataURL: Image converted to jpg for performance reasons', image );
- return this;
+ return canvas.toDataURL( 'image/jpeg', 0.6 );
- },
+ } else {
- setComponent: function ( index, value ) {
+ return canvas.toDataURL( 'image/png' );
- switch ( index ) {
+ }
- case 0: this.x = value; break;
- case 1: this.y = value; break;
- case 2: this.z = value; break;
- default: throw new Error( 'index is out of range: ' + index );
+ }
- }
+ static sRGBToLinear( image ) {
- return this;
+ if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) ||
+ ( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) ||
+ ( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) {
- },
+ const canvas = createElementNS( 'canvas' );
+
+ canvas.width = image.width;
+ canvas.height = image.height;
- getComponent: function ( index ) {
+ const context = canvas.getContext( '2d' );
+ context.drawImage( image, 0, 0, image.width, image.height );
- switch ( index ) {
+ const imageData = context.getImageData( 0, 0, image.width, image.height );
+ const data = imageData.data;
- case 0: return this.x;
- case 1: return this.y;
- case 2: return this.z;
- default: throw new Error( 'index is out of range: ' + index );
+ for ( let i = 0; i < data.length; i ++ ) {
+
+ data[ i ] = SRGBToLinear( data[ i ] / 255 ) * 255;
}
- },
+ context.putImageData( imageData, 0, 0 );
- clone: function () {
+ return canvas;
- return new this.constructor( this.x, this.y, this.z );
+ } else if ( image.data ) {
- },
+ const data = image.data.slice( 0 );
- copy: function ( v ) {
+ for ( let i = 0; i < data.length; i ++ ) {
- this.x = v.x;
- this.y = v.y;
- this.z = v.z;
+ if ( data instanceof Uint8Array || data instanceof Uint8ClampedArray ) {
- return this;
+ data[ i ] = Math.floor( SRGBToLinear( data[ i ] / 255 ) * 255 );
- },
+ } else {
- add: function ( v, w ) {
+ // assuming float
- if ( w !== undefined ) {
+ data[ i ] = SRGBToLinear( data[ i ] );
- console.warn( 'THREE.Vector3: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );
- return this.addVectors( v, w );
+ }
}
- this.x += v.x;
- this.y += v.y;
- this.z += v.z;
+ return {
+ data: data,
+ width: image.width,
+ height: image.height
+ };
- return this;
+ } else {
- },
+ console.warn( 'THREE.ImageUtils.sRGBToLinear(): Unsupported image type. No color space conversion applied.' );
+ return image;
- addScalar: function ( s ) {
+ }
- this.x += s;
- this.y += s;
- this.z += s;
+ }
- return this;
+}
- },
+let _sourceId = 0;
- addVectors: function ( a, b ) {
+class Source {
- this.x = a.x + b.x;
- this.y = a.y + b.y;
- this.z = a.z + b.z;
+ constructor( data = null ) {
- return this;
+ this.isSource = true;
- },
+ Object.defineProperty( this, 'id', { value: _sourceId ++ } );
- addScaledVector: function ( v, s ) {
+ this.uuid = generateUUID();
- this.x += v.x * s;
- this.y += v.y * s;
- this.z += v.z * s;
+ this.data = data;
- return this;
+ this.version = 0;
- },
+ }
- sub: function ( v, w ) {
+ set needsUpdate( value ) {
- if ( w !== undefined ) {
+ if ( value === true ) this.version ++;
- console.warn( 'THREE.Vector3: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );
- return this.subVectors( v, w );
+ }
- }
+ toJSON( meta ) {
- this.x -= v.x;
- this.y -= v.y;
- this.z -= v.z;
+ const isRootObject = ( meta === undefined || typeof meta === 'string' );
- return this;
+ if ( ! isRootObject && meta.images[ this.uuid ] !== undefined ) {
- },
+ return meta.images[ this.uuid ];
- subScalar: function ( s ) {
+ }
- this.x -= s;
- this.y -= s;
- this.z -= s;
+ const output = {
+ uuid: this.uuid,
+ url: ''
+ };
- return this;
+ const data = this.data;
- },
+ if ( data !== null ) {
- subVectors: function ( a, b ) {
+ let url;
- this.x = a.x - b.x;
- this.y = a.y - b.y;
- this.z = a.z - b.z;
+ if ( Array.isArray( data ) ) {
- return this;
+ // cube texture
- },
+ url = [];
- multiply: function ( v, w ) {
+ for ( let i = 0, l = data.length; i < l; i ++ ) {
- if ( w !== undefined ) {
+ if ( data[ i ].isDataTexture ) {
- console.warn( 'THREE.Vector3: .multiply() now only accepts one argument. Use .multiplyVectors( a, b ) instead.' );
- return this.multiplyVectors( v, w );
+ url.push( serializeImage( data[ i ].image ) );
- }
-
- this.x *= v.x;
- this.y *= v.y;
- this.z *= v.z;
+ } else {
- return this;
+ url.push( serializeImage( data[ i ] ) );
- },
+ }
- multiplyScalar: function ( scalar ) {
+ }
- this.x *= scalar;
- this.y *= scalar;
- this.z *= scalar;
+ } else {
- return this;
+ // texture
- },
+ url = serializeImage( data );
- multiplyVectors: function ( a, b ) {
+ }
- this.x = a.x * b.x;
- this.y = a.y * b.y;
- this.z = a.z * b.z;
+ output.url = url;
- return this;
+ }
- },
+ if ( ! isRootObject ) {
- applyEuler: function ( euler ) {
+ meta.images[ this.uuid ] = output;
- if ( ! ( euler && euler.isEuler ) ) {
+ }
- console.error( 'THREE.Vector3: .applyEuler() now expects an Euler rotation rather than a Vector3 and order.' );
+ return output;
- }
+ }
- return this.applyQuaternion( _quaternion.setFromEuler( euler ) );
+}
- },
+function serializeImage( image ) {
- applyAxisAngle: function ( axis, angle ) {
+ if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) ||
+ ( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) ||
+ ( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) {
- return this.applyQuaternion( _quaternion.setFromAxisAngle( axis, angle ) );
+ // default images
- },
+ return ImageUtils.getDataURL( image );
- applyMatrix3: function ( m ) {
+ } else {
- var x = this.x, y = this.y, z = this.z;
- var e = m.elements;
+ if ( image.data ) {
- this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ] * z;
- this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ] * z;
- this.z = e[ 2 ] * x + e[ 5 ] * y + e[ 8 ] * z;
+ // images of DataTexture
- return this;
+ return {
+ data: Array.from( image.data ),
+ width: image.width,
+ height: image.height,
+ type: image.data.constructor.name
+ };
- },
+ } else {
- applyMatrix4: function ( m ) {
+ console.warn( 'THREE.Texture: Unable to serialize Texture.' );
+ return {};
- var x = this.x, y = this.y, z = this.z;
- var e = m.elements;
+ }
- var w = 1 / ( e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] );
+ }
- this.x = ( e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] ) * w;
- this.y = ( e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] ) * w;
- this.z = ( e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] ) * w;
+}
- return this;
+let _textureId = 0;
- },
+class Texture extends EventDispatcher {
- applyQuaternion: function ( q ) {
+ constructor( image = Texture.DEFAULT_IMAGE, mapping = Texture.DEFAULT_MAPPING, wrapS = ClampToEdgeWrapping, wrapT = ClampToEdgeWrapping, magFilter = LinearFilter, minFilter = LinearMipmapLinearFilter, format = RGBAFormat, type = UnsignedByteType, anisotropy = Texture.DEFAULT_ANISOTROPY, colorSpace = NoColorSpace ) {
- var x = this.x, y = this.y, z = this.z;
- var qx = q.x, qy = q.y, qz = q.z, qw = q.w;
+ super();
- // calculate quat * vector
+ this.isTexture = true;
- var ix = qw * x + qy * z - qz * y;
- var iy = qw * y + qz * x - qx * z;
- var iz = qw * z + qx * y - qy * x;
- var iw = - qx * x - qy * y - qz * z;
+ Object.defineProperty( this, 'id', { value: _textureId ++ } );
- // calculate result * inverse quat
+ this.uuid = generateUUID();
- this.x = ix * qw + iw * - qx + iy * - qz - iz * - qy;
- this.y = iy * qw + iw * - qy + iz * - qx - ix * - qz;
- this.z = iz * qw + iw * - qz + ix * - qy - iy * - qx;
+ this.name = '';
- return this;
+ this.source = new Source( image );
+ this.mipmaps = [];
- },
+ this.mapping = mapping;
+ this.channel = 0;
- project: function ( camera ) {
+ this.wrapS = wrapS;
+ this.wrapT = wrapT;
- return this.applyMatrix4( camera.matrixWorldInverse ).applyMatrix4( camera.projectionMatrix );
+ this.magFilter = magFilter;
+ this.minFilter = minFilter;
- },
+ this.anisotropy = anisotropy;
- unproject: function ( camera ) {
+ this.format = format;
+ this.internalFormat = null;
+ this.type = type;
- return this.applyMatrix4( camera.projectionMatrixInverse ).applyMatrix4( camera.matrixWorld );
+ this.offset = new Vector2( 0, 0 );
+ this.repeat = new Vector2( 1, 1 );
+ this.center = new Vector2( 0, 0 );
+ this.rotation = 0;
- },
+ this.matrixAutoUpdate = true;
+ this.matrix = new Matrix3();
- transformDirection: function ( m ) {
+ this.generateMipmaps = true;
+ this.premultiplyAlpha = false;
+ this.flipY = true;
+ this.unpackAlignment = 4; // valid values: 1, 2, 4, 8 (see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml)
- // input: THREE.Matrix4 affine matrix
- // vector interpreted as a direction
+ if ( typeof colorSpace === 'string' ) {
- var x = this.x, y = this.y, z = this.z;
- var e = m.elements;
+ this.colorSpace = colorSpace;
- this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z;
- this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z;
- this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z;
+ } else { // @deprecated, r152
- return this.normalize();
+ warnOnce( 'THREE.Texture: Property .encoding has been replaced by .colorSpace.' );
+ this.colorSpace = colorSpace === sRGBEncoding ? SRGBColorSpace : NoColorSpace;
- },
+ }
- divide: function ( v ) {
- this.x /= v.x;
- this.y /= v.y;
- this.z /= v.z;
+ this.userData = {};
- return this;
+ this.version = 0;
+ this.onUpdate = null;
- },
+ this.isRenderTargetTexture = false; // indicates whether a texture belongs to a render target or not
+ this.needsPMREMUpdate = false; // indicates whether this texture should be processed by PMREMGenerator or not (only relevant for render target textures)
- divideScalar: function ( scalar ) {
+ }
- return this.multiplyScalar( 1 / scalar );
+ get image() {
- },
+ return this.source.data;
- min: function ( v ) {
+ }
- this.x = Math.min( this.x, v.x );
- this.y = Math.min( this.y, v.y );
- this.z = Math.min( this.z, v.z );
+ set image( value = null ) {
- return this;
+ this.source.data = value;
- },
+ }
- max: function ( v ) {
+ updateMatrix() {
- this.x = Math.max( this.x, v.x );
- this.y = Math.max( this.y, v.y );
- this.z = Math.max( this.z, v.z );
+ this.matrix.setUvTransform( this.offset.x, this.offset.y, this.repeat.x, this.repeat.y, this.rotation, this.center.x, this.center.y );
- return this;
+ }
- },
+ clone() {
- clamp: function ( min, max ) {
+ return new this.constructor().copy( this );
- // assumes min < max, componentwise
+ }
- this.x = Math.max( min.x, Math.min( max.x, this.x ) );
- this.y = Math.max( min.y, Math.min( max.y, this.y ) );
- this.z = Math.max( min.z, Math.min( max.z, this.z ) );
+ copy( source ) {
- return this;
+ this.name = source.name;
- },
+ this.source = source.source;
+ this.mipmaps = source.mipmaps.slice( 0 );
- clampScalar: function ( minVal, maxVal ) {
+ this.mapping = source.mapping;
+ this.channel = source.channel;
- this.x = Math.max( minVal, Math.min( maxVal, this.x ) );
- this.y = Math.max( minVal, Math.min( maxVal, this.y ) );
- this.z = Math.max( minVal, Math.min( maxVal, this.z ) );
+ this.wrapS = source.wrapS;
+ this.wrapT = source.wrapT;
- return this;
+ this.magFilter = source.magFilter;
+ this.minFilter = source.minFilter;
- },
+ this.anisotropy = source.anisotropy;
- clampLength: function ( min, max ) {
+ this.format = source.format;
+ this.internalFormat = source.internalFormat;
+ this.type = source.type;
- var length = this.length();
+ this.offset.copy( source.offset );
+ this.repeat.copy( source.repeat );
+ this.center.copy( source.center );
+ this.rotation = source.rotation;
- return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );
+ this.matrixAutoUpdate = source.matrixAutoUpdate;
+ this.matrix.copy( source.matrix );
- },
+ this.generateMipmaps = source.generateMipmaps;
+ this.premultiplyAlpha = source.premultiplyAlpha;
+ this.flipY = source.flipY;
+ this.unpackAlignment = source.unpackAlignment;
+ this.colorSpace = source.colorSpace;
- floor: function () {
+ this.userData = JSON.parse( JSON.stringify( source.userData ) );
- this.x = Math.floor( this.x );
- this.y = Math.floor( this.y );
- this.z = Math.floor( this.z );
+ this.needsUpdate = true;
- return this;
+ return this;
- },
+ }
- ceil: function () {
+ toJSON( meta ) {
- this.x = Math.ceil( this.x );
- this.y = Math.ceil( this.y );
- this.z = Math.ceil( this.z );
+ const isRootObject = ( meta === undefined || typeof meta === 'string' );
- return this;
+ if ( ! isRootObject && meta.textures[ this.uuid ] !== undefined ) {
- },
+ return meta.textures[ this.uuid ];
- round: function () {
+ }
- this.x = Math.round( this.x );
- this.y = Math.round( this.y );
- this.z = Math.round( this.z );
+ const output = {
- return this;
+ metadata: {
+ version: 4.6,
+ type: 'Texture',
+ generator: 'Texture.toJSON'
+ },
- },
+ uuid: this.uuid,
+ name: this.name,
- roundToZero: function () {
+ image: this.source.toJSON( meta ).uuid,
- this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );
- this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );
- this.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z );
+ mapping: this.mapping,
+ channel: this.channel,
- return this;
+ repeat: [ this.repeat.x, this.repeat.y ],
+ offset: [ this.offset.x, this.offset.y ],
+ center: [ this.center.x, this.center.y ],
+ rotation: this.rotation,
- },
+ wrap: [ this.wrapS, this.wrapT ],
- negate: function () {
+ format: this.format,
+ internalFormat: this.internalFormat,
+ type: this.type,
+ colorSpace: this.colorSpace,
- this.x = - this.x;
- this.y = - this.y;
- this.z = - this.z;
+ minFilter: this.minFilter,
+ magFilter: this.magFilter,
+ anisotropy: this.anisotropy,
- return this;
+ flipY: this.flipY,
- },
+ generateMipmaps: this.generateMipmaps,
+ premultiplyAlpha: this.premultiplyAlpha,
+ unpackAlignment: this.unpackAlignment
- dot: function ( v ) {
+ };
- return this.x * v.x + this.y * v.y + this.z * v.z;
+ if ( Object.keys( this.userData ).length > 0 ) output.userData = this.userData;
- },
+ if ( ! isRootObject ) {
- // TODO lengthSquared?
+ meta.textures[ this.uuid ] = output;
- lengthSq: function () {
+ }
- return this.x * this.x + this.y * this.y + this.z * this.z;
+ return output;
- },
+ }
- length: function () {
+ dispose() {
- return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z );
+ this.dispatchEvent( { type: 'dispose' } );
- },
+ }
- manhattanLength: function () {
+ transformUv( uv ) {
- return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z );
+ if ( this.mapping !== UVMapping ) return uv;
- },
+ uv.applyMatrix3( this.matrix );
- normalize: function () {
+ if ( uv.x < 0 || uv.x > 1 ) {
- return this.divideScalar( this.length() || 1 );
+ switch ( this.wrapS ) {
- },
+ case RepeatWrapping:
- setLength: function ( length ) {
+ uv.x = uv.x - Math.floor( uv.x );
+ break;
- return this.normalize().multiplyScalar( length );
+ case ClampToEdgeWrapping:
- },
+ uv.x = uv.x < 0 ? 0 : 1;
+ break;
- lerp: function ( v, alpha ) {
+ case MirroredRepeatWrapping:
- this.x += ( v.x - this.x ) * alpha;
- this.y += ( v.y - this.y ) * alpha;
- this.z += ( v.z - this.z ) * alpha;
+ if ( Math.abs( Math.floor( uv.x ) % 2 ) === 1 ) {
- return this;
+ uv.x = Math.ceil( uv.x ) - uv.x;
- },
+ } else {
- lerpVectors: function ( v1, v2, alpha ) {
+ uv.x = uv.x - Math.floor( uv.x );
- return this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 );
+ }
- },
+ break;
- cross: function ( v, w ) {
+ }
- if ( w !== undefined ) {
+ }
- console.warn( 'THREE.Vector3: .cross() now only accepts one argument. Use .crossVectors( a, b ) instead.' );
- return this.crossVectors( v, w );
+ if ( uv.y < 0 || uv.y > 1 ) {
- }
+ switch ( this.wrapT ) {
- return this.crossVectors( this, v );
+ case RepeatWrapping:
- },
+ uv.y = uv.y - Math.floor( uv.y );
+ break;
- crossVectors: function ( a, b ) {
+ case ClampToEdgeWrapping:
- var ax = a.x, ay = a.y, az = a.z;
- var bx = b.x, by = b.y, bz = b.z;
+ uv.y = uv.y < 0 ? 0 : 1;
+ break;
- this.x = ay * bz - az * by;
- this.y = az * bx - ax * bz;
- this.z = ax * by - ay * bx;
+ case MirroredRepeatWrapping:
- return this;
+ if ( Math.abs( Math.floor( uv.y ) % 2 ) === 1 ) {
- },
+ uv.y = Math.ceil( uv.y ) - uv.y;
- projectOnVector: function ( vector ) {
+ } else {
- var scalar = vector.dot( this ) / vector.lengthSq();
+ uv.y = uv.y - Math.floor( uv.y );
- return this.copy( vector ).multiplyScalar( scalar );
+ }
- },
+ break;
- projectOnPlane: function ( planeNormal ) {
+ }
- _vector.copy( this ).projectOnVector( planeNormal );
+ }
- return this.sub( _vector );
+ if ( this.flipY ) {
- },
+ uv.y = 1 - uv.y;
- reflect: function ( normal ) {
+ }
- // reflect incident vector off plane orthogonal to normal
- // normal is assumed to have unit length
+ return uv;
- return this.sub( _vector.copy( normal ).multiplyScalar( 2 * this.dot( normal ) ) );
+ }
- },
+ set needsUpdate( value ) {
- angleTo: function ( v ) {
+ if ( value === true ) {
- var theta = this.dot( v ) / ( Math.sqrt( this.lengthSq() * v.lengthSq() ) );
+ this.version ++;
+ this.source.needsUpdate = true;
- // clamp, to handle numerical problems
+ }
- return Math.acos( _Math.clamp( theta, - 1, 1 ) );
+ }
- },
+ get encoding() { // @deprecated, r152
- distanceTo: function ( v ) {
+ warnOnce( 'THREE.Texture: Property .encoding has been replaced by .colorSpace.' );
+ return this.colorSpace === SRGBColorSpace ? sRGBEncoding : LinearEncoding;
- return Math.sqrt( this.distanceToSquared( v ) );
+ }
- },
+ set encoding( encoding ) { // @deprecated, r152
- distanceToSquared: function ( v ) {
+ warnOnce( 'THREE.Texture: Property .encoding has been replaced by .colorSpace.' );
+ this.colorSpace = encoding === sRGBEncoding ? SRGBColorSpace : NoColorSpace;
- var dx = this.x - v.x, dy = this.y - v.y, dz = this.z - v.z;
+ }
- return dx * dx + dy * dy + dz * dz;
+}
- },
+Texture.DEFAULT_IMAGE = null;
+Texture.DEFAULT_MAPPING = UVMapping;
+Texture.DEFAULT_ANISOTROPY = 1;
- manhattanDistanceTo: function ( v ) {
+class Vector4 {
- return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y ) + Math.abs( this.z - v.z );
+ constructor( x = 0, y = 0, z = 0, w = 1 ) {
- },
+ Vector4.prototype.isVector4 = true;
- setFromSpherical: function ( s ) {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ this.w = w;
- return this.setFromSphericalCoords( s.radius, s.phi, s.theta );
+ }
- },
+ get width() {
- setFromSphericalCoords: function ( radius, phi, theta ) {
+ return this.z;
- var sinPhiRadius = Math.sin( phi ) * radius;
+ }
- this.x = sinPhiRadius * Math.sin( theta );
- this.y = Math.cos( phi ) * radius;
- this.z = sinPhiRadius * Math.cos( theta );
+ set width( value ) {
- return this;
+ this.z = value;
- },
+ }
- setFromCylindrical: function ( c ) {
+ get height() {
- return this.setFromCylindricalCoords( c.radius, c.theta, c.y );
+ return this.w;
- },
+ }
- setFromCylindricalCoords: function ( radius, theta, y ) {
+ set height( value ) {
- this.x = radius * Math.sin( theta );
- this.y = y;
- this.z = radius * Math.cos( theta );
+ this.w = value;
- return this;
+ }
- },
+ set( x, y, z, w ) {
- setFromMatrixPosition: function ( m ) {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ this.w = w;
- var e = m.elements;
+ return this;
- this.x = e[ 12 ];
- this.y = e[ 13 ];
- this.z = e[ 14 ];
+ }
- return this;
+ setScalar( scalar ) {
- },
+ this.x = scalar;
+ this.y = scalar;
+ this.z = scalar;
+ this.w = scalar;
- setFromMatrixScale: function ( m ) {
+ return this;
- var sx = this.setFromMatrixColumn( m, 0 ).length();
- var sy = this.setFromMatrixColumn( m, 1 ).length();
- var sz = this.setFromMatrixColumn( m, 2 ).length();
+ }
- this.x = sx;
- this.y = sy;
- this.z = sz;
+ setX( x ) {
- return this;
+ this.x = x;
- },
+ return this;
- setFromMatrixColumn: function ( m, index ) {
+ }
- return this.fromArray( m.elements, index * 4 );
+ setY( y ) {
- },
+ this.y = y;
- equals: function ( v ) {
+ return this;
- return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) );
+ }
- },
+ setZ( z ) {
- fromArray: function ( array, offset ) {
+ this.z = z;
- if ( offset === undefined ) offset = 0;
+ return this;
- this.x = array[ offset ];
- this.y = array[ offset + 1 ];
- this.z = array[ offset + 2 ];
+ }
- return this;
+ setW( w ) {
- },
+ this.w = w;
- toArray: function ( array, offset ) {
+ return this;
- if ( array === undefined ) array = [];
- if ( offset === undefined ) offset = 0;
+ }
- array[ offset ] = this.x;
- array[ offset + 1 ] = this.y;
- array[ offset + 2 ] = this.z;
+ setComponent( index, value ) {
- return array;
+ switch ( index ) {
- },
+ case 0: this.x = value; break;
+ case 1: this.y = value; break;
+ case 2: this.z = value; break;
+ case 3: this.w = value; break;
+ default: throw new Error( 'index is out of range: ' + index );
- fromBufferAttribute: function ( attribute, index, offset ) {
+ }
- if ( offset !== undefined ) {
+ return this;
- console.warn( 'THREE.Vector3: offset has been removed from .fromBufferAttribute().' );
+ }
- }
+ getComponent( index ) {
- this.x = attribute.getX( index );
- this.y = attribute.getY( index );
- this.z = attribute.getZ( index );
+ switch ( index ) {
- return this;
+ case 0: return this.x;
+ case 1: return this.y;
+ case 2: return this.z;
+ case 3: return this.w;
+ default: throw new Error( 'index is out of range: ' + index );
}
- } );
+ }
- /**
- * @author alteredq / http://alteredqualia.com/
- * @author WestLangley / http://github.com/WestLangley
- * @author bhouston / http://clara.io
- * @author tschw
- */
+ clone() {
- var _vector$1 = new Vector3();
+ return new this.constructor( this.x, this.y, this.z, this.w );
- function Matrix3() {
+ }
- this.elements = [
+ copy( v ) {
- 1, 0, 0,
- 0, 1, 0,
- 0, 0, 1
+ this.x = v.x;
+ this.y = v.y;
+ this.z = v.z;
+ this.w = ( v.w !== undefined ) ? v.w : 1;
- ];
+ return this;
+
+ }
- if ( arguments.length > 0 ) {
+ add( v ) {
- console.error( 'THREE.Matrix3: the constructor no longer reads arguments. use .set() instead.' );
+ this.x += v.x;
+ this.y += v.y;
+ this.z += v.z;
+ this.w += v.w;
- }
+ return this;
}
- Object.assign( Matrix3.prototype, {
+ addScalar( s ) {
- isMatrix3: true,
+ this.x += s;
+ this.y += s;
+ this.z += s;
+ this.w += s;
- set: function ( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) {
+ return this;
- var te = this.elements;
+ }
- te[ 0 ] = n11; te[ 1 ] = n21; te[ 2 ] = n31;
- te[ 3 ] = n12; te[ 4 ] = n22; te[ 5 ] = n32;
- te[ 6 ] = n13; te[ 7 ] = n23; te[ 8 ] = n33;
+ addVectors( a, b ) {
- return this;
+ this.x = a.x + b.x;
+ this.y = a.y + b.y;
+ this.z = a.z + b.z;
+ this.w = a.w + b.w;
- },
+ return this;
- identity: function () {
+ }
- this.set(
+ addScaledVector( v, s ) {
- 1, 0, 0,
- 0, 1, 0,
- 0, 0, 1
+ this.x += v.x * s;
+ this.y += v.y * s;
+ this.z += v.z * s;
+ this.w += v.w * s;
- );
+ return this;
- return this;
+ }
- },
+ sub( v ) {
- clone: function () {
+ this.x -= v.x;
+ this.y -= v.y;
+ this.z -= v.z;
+ this.w -= v.w;
- return new this.constructor().fromArray( this.elements );
+ return this;
- },
+ }
- copy: function ( m ) {
+ subScalar( s ) {
- var te = this.elements;
- var me = m.elements;
+ this.x -= s;
+ this.y -= s;
+ this.z -= s;
+ this.w -= s;
- te[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ];
- te[ 3 ] = me[ 3 ]; te[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ];
- te[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ]; te[ 8 ] = me[ 8 ];
+ return this;
- return this;
+ }
- },
+ subVectors( a, b ) {
- setFromMatrix4: function ( m ) {
+ this.x = a.x - b.x;
+ this.y = a.y - b.y;
+ this.z = a.z - b.z;
+ this.w = a.w - b.w;
- var me = m.elements;
+ return this;
- this.set(
+ }
- me[ 0 ], me[ 4 ], me[ 8 ],
- me[ 1 ], me[ 5 ], me[ 9 ],
- me[ 2 ], me[ 6 ], me[ 10 ]
+ multiply( v ) {
- );
+ this.x *= v.x;
+ this.y *= v.y;
+ this.z *= v.z;
+ this.w *= v.w;
- return this;
+ return this;
- },
+ }
- applyToBufferAttribute: function ( attribute ) {
+ multiplyScalar( scalar ) {
- for ( var i = 0, l = attribute.count; i < l; i ++ ) {
+ this.x *= scalar;
+ this.y *= scalar;
+ this.z *= scalar;
+ this.w *= scalar;
- _vector$1.x = attribute.getX( i );
- _vector$1.y = attribute.getY( i );
- _vector$1.z = attribute.getZ( i );
+ return this;
- _vector$1.applyMatrix3( this );
+ }
- attribute.setXYZ( i, _vector$1.x, _vector$1.y, _vector$1.z );
+ applyMatrix4( m ) {
- }
+ const x = this.x, y = this.y, z = this.z, w = this.w;
+ const e = m.elements;
- return attribute;
+ this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] * w;
+ this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] * w;
+ this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] * w;
+ this.w = e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] * w;
- },
+ return this;
- multiply: function ( m ) {
+ }
- return this.multiplyMatrices( this, m );
+ divideScalar( scalar ) {
- },
+ return this.multiplyScalar( 1 / scalar );
- premultiply: function ( m ) {
+ }
- return this.multiplyMatrices( m, this );
+ setAxisAngleFromQuaternion( q ) {
- },
+ // http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm
- multiplyMatrices: function ( a, b ) {
+ // q is assumed to be normalized
- var ae = a.elements;
- var be = b.elements;
- var te = this.elements;
+ this.w = 2 * Math.acos( q.w );
- var a11 = ae[ 0 ], a12 = ae[ 3 ], a13 = ae[ 6 ];
- var a21 = ae[ 1 ], a22 = ae[ 4 ], a23 = ae[ 7 ];
- var a31 = ae[ 2 ], a32 = ae[ 5 ], a33 = ae[ 8 ];
+ const s = Math.sqrt( 1 - q.w * q.w );
- var b11 = be[ 0 ], b12 = be[ 3 ], b13 = be[ 6 ];
- var b21 = be[ 1 ], b22 = be[ 4 ], b23 = be[ 7 ];
- var b31 = be[ 2 ], b32 = be[ 5 ], b33 = be[ 8 ];
+ if ( s < 0.0001 ) {
- te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31;
- te[ 3 ] = a11 * b12 + a12 * b22 + a13 * b32;
- te[ 6 ] = a11 * b13 + a12 * b23 + a13 * b33;
+ this.x = 1;
+ this.y = 0;
+ this.z = 0;
- te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31;
- te[ 4 ] = a21 * b12 + a22 * b22 + a23 * b32;
- te[ 7 ] = a21 * b13 + a22 * b23 + a23 * b33;
+ } else {
- te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31;
- te[ 5 ] = a31 * b12 + a32 * b22 + a33 * b32;
- te[ 8 ] = a31 * b13 + a32 * b23 + a33 * b33;
+ this.x = q.x / s;
+ this.y = q.y / s;
+ this.z = q.z / s;
- return this;
+ }
- },
+ return this;
- multiplyScalar: function ( s ) {
+ }
- var te = this.elements;
+ setAxisAngleFromRotationMatrix( m ) {
- te[ 0 ] *= s; te[ 3 ] *= s; te[ 6 ] *= s;
- te[ 1 ] *= s; te[ 4 ] *= s; te[ 7 ] *= s;
- te[ 2 ] *= s; te[ 5 ] *= s; te[ 8 ] *= s;
+ // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm
- return this;
+ // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
- },
+ let angle, x, y, z; // variables for result
+ const epsilon = 0.01, // margin to allow for rounding errors
+ epsilon2 = 0.1, // margin to distinguish between 0 and 180 degrees
- determinant: function () {
+ te = m.elements,
- var te = this.elements;
+ m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ],
+ m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ],
+ m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ];
- var a = te[ 0 ], b = te[ 1 ], c = te[ 2 ],
- d = te[ 3 ], e = te[ 4 ], f = te[ 5 ],
- g = te[ 6 ], h = te[ 7 ], i = te[ 8 ];
+ if ( ( Math.abs( m12 - m21 ) < epsilon ) &&
+ ( Math.abs( m13 - m31 ) < epsilon ) &&
+ ( Math.abs( m23 - m32 ) < epsilon ) ) {
- return a * e * i - a * f * h - b * d * i + b * f * g + c * d * h - c * e * g;
+ // singularity found
+ // first check for identity matrix which must have +1 for all terms
+ // in leading diagonal and zero in other terms
- },
+ if ( ( Math.abs( m12 + m21 ) < epsilon2 ) &&
+ ( Math.abs( m13 + m31 ) < epsilon2 ) &&
+ ( Math.abs( m23 + m32 ) < epsilon2 ) &&
+ ( Math.abs( m11 + m22 + m33 - 3 ) < epsilon2 ) ) {
- getInverse: function ( matrix, throwOnDegenerate ) {
+ // this singularity is identity matrix so angle = 0
- if ( matrix && matrix.isMatrix4 ) {
+ this.set( 1, 0, 0, 0 );
- console.error( "THREE.Matrix3: .getInverse() no longer takes a Matrix4 argument." );
+ return this; // zero angle, arbitrary axis
}
- var me = matrix.elements,
- te = this.elements,
-
- n11 = me[ 0 ], n21 = me[ 1 ], n31 = me[ 2 ],
- n12 = me[ 3 ], n22 = me[ 4 ], n32 = me[ 5 ],
- n13 = me[ 6 ], n23 = me[ 7 ], n33 = me[ 8 ],
+ // otherwise this singularity is angle = 180
- t11 = n33 * n22 - n32 * n23,
- t12 = n32 * n13 - n33 * n12,
- t13 = n23 * n12 - n22 * n13,
+ angle = Math.PI;
- det = n11 * t11 + n21 * t12 + n31 * t13;
+ const xx = ( m11 + 1 ) / 2;
+ const yy = ( m22 + 1 ) / 2;
+ const zz = ( m33 + 1 ) / 2;
+ const xy = ( m12 + m21 ) / 4;
+ const xz = ( m13 + m31 ) / 4;
+ const yz = ( m23 + m32 ) / 4;
- if ( det === 0 ) {
+ if ( ( xx > yy ) && ( xx > zz ) ) {
- var msg = "THREE.Matrix3: .getInverse() can't invert matrix, determinant is 0";
+ // m11 is the largest diagonal term
- if ( throwOnDegenerate === true ) {
+ if ( xx < epsilon ) {
- throw new Error( msg );
+ x = 0;
+ y = 0.707106781;
+ z = 0.707106781;
} else {
- console.warn( msg );
+ x = Math.sqrt( xx );
+ y = xy / x;
+ z = xz / x;
}
- return this.identity();
+ } else if ( yy > zz ) {
- }
+ // m22 is the largest diagonal term
- var detInv = 1 / det;
+ if ( yy < epsilon ) {
- te[ 0 ] = t11 * detInv;
- te[ 1 ] = ( n31 * n23 - n33 * n21 ) * detInv;
- te[ 2 ] = ( n32 * n21 - n31 * n22 ) * detInv;
+ x = 0.707106781;
+ y = 0;
+ z = 0.707106781;
- te[ 3 ] = t12 * detInv;
- te[ 4 ] = ( n33 * n11 - n31 * n13 ) * detInv;
- te[ 5 ] = ( n31 * n12 - n32 * n11 ) * detInv;
+ } else {
- te[ 6 ] = t13 * detInv;
- te[ 7 ] = ( n21 * n13 - n23 * n11 ) * detInv;
- te[ 8 ] = ( n22 * n11 - n21 * n12 ) * detInv;
+ y = Math.sqrt( yy );
+ x = xy / y;
+ z = yz / y;
- return this;
+ }
- },
+ } else {
- transpose: function () {
+ // m33 is the largest diagonal term so base result on this
- var tmp, m = this.elements;
+ if ( zz < epsilon ) {
- tmp = m[ 1 ]; m[ 1 ] = m[ 3 ]; m[ 3 ] = tmp;
- tmp = m[ 2 ]; m[ 2 ] = m[ 6 ]; m[ 6 ] = tmp;
- tmp = m[ 5 ]; m[ 5 ] = m[ 7 ]; m[ 7 ] = tmp;
+ x = 0.707106781;
+ y = 0.707106781;
+ z = 0;
- return this;
+ } else {
- },
+ z = Math.sqrt( zz );
+ x = xz / z;
+ y = yz / z;
- getNormalMatrix: function ( matrix4 ) {
+ }
- return this.setFromMatrix4( matrix4 ).getInverse( this ).transpose();
+ }
- },
+ this.set( x, y, z, angle );
- transposeIntoArray: function ( r ) {
+ return this; // return 180 deg rotation
- var m = this.elements;
+ }
- r[ 0 ] = m[ 0 ];
- r[ 1 ] = m[ 3 ];
- r[ 2 ] = m[ 6 ];
- r[ 3 ] = m[ 1 ];
- r[ 4 ] = m[ 4 ];
- r[ 5 ] = m[ 7 ];
- r[ 6 ] = m[ 2 ];
- r[ 7 ] = m[ 5 ];
- r[ 8 ] = m[ 8 ];
+ // as we have reached here there are no singularities so we can handle normally
- return this;
+ let s = Math.sqrt( ( m32 - m23 ) * ( m32 - m23 ) +
+ ( m13 - m31 ) * ( m13 - m31 ) +
+ ( m21 - m12 ) * ( m21 - m12 ) ); // used to normalize
- },
+ if ( Math.abs( s ) < 0.001 ) s = 1;
- setUvTransform: function ( tx, ty, sx, sy, rotation, cx, cy ) {
+ // prevent divide by zero, should not happen if matrix is orthogonal and should be
+ // caught by singularity test above, but I've left it in just in case
- var c = Math.cos( rotation );
- var s = Math.sin( rotation );
+ this.x = ( m32 - m23 ) / s;
+ this.y = ( m13 - m31 ) / s;
+ this.z = ( m21 - m12 ) / s;
+ this.w = Math.acos( ( m11 + m22 + m33 - 1 ) / 2 );
- 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;
- },
+ }
- scale: function ( sx, sy ) {
+ min( v ) {
- var te = this.elements;
+ this.x = Math.min( this.x, v.x );
+ this.y = Math.min( this.y, v.y );
+ this.z = Math.min( this.z, v.z );
+ this.w = Math.min( this.w, v.w );
- te[ 0 ] *= sx; te[ 3 ] *= sx; te[ 6 ] *= sx;
- te[ 1 ] *= sy; te[ 4 ] *= sy; te[ 7 ] *= sy;
+ return this;
- return this;
-
- },
-
- rotate: function ( theta ) {
-
- var c = Math.cos( theta );
- var s = Math.sin( theta );
-
- var te = this.elements;
+ }
- var a11 = te[ 0 ], a12 = te[ 3 ], a13 = te[ 6 ];
- var a21 = te[ 1 ], a22 = te[ 4 ], a23 = te[ 7 ];
+ max( v ) {
- te[ 0 ] = c * a11 + s * a21;
- te[ 3 ] = c * a12 + s * a22;
- te[ 6 ] = c * a13 + s * a23;
+ this.x = Math.max( this.x, v.x );
+ this.y = Math.max( this.y, v.y );
+ this.z = Math.max( this.z, v.z );
+ this.w = Math.max( this.w, v.w );
- te[ 1 ] = - s * a11 + c * a21;
- te[ 4 ] = - s * a12 + c * a22;
- te[ 7 ] = - s * a13 + c * a23;
+ return this;
- return this;
+ }
- },
+ clamp( min, max ) {
- translate: function ( tx, ty ) {
+ // assumes min < max, componentwise
- var te = this.elements;
+ this.x = Math.max( min.x, Math.min( max.x, this.x ) );
+ this.y = Math.max( min.y, Math.min( max.y, this.y ) );
+ this.z = Math.max( min.z, Math.min( max.z, this.z ) );
+ this.w = Math.max( min.w, Math.min( max.w, this.w ) );
- te[ 0 ] += tx * te[ 2 ]; te[ 3 ] += tx * te[ 5 ]; te[ 6 ] += tx * te[ 8 ];
- te[ 1 ] += ty * te[ 2 ]; te[ 4 ] += ty * te[ 5 ]; te[ 7 ] += ty * te[ 8 ];
+ return this;
- return this;
+ }
- },
+ clampScalar( minVal, maxVal ) {
- equals: function ( matrix ) {
+ this.x = Math.max( minVal, Math.min( maxVal, this.x ) );
+ this.y = Math.max( minVal, Math.min( maxVal, this.y ) );
+ this.z = Math.max( minVal, Math.min( maxVal, this.z ) );
+ this.w = Math.max( minVal, Math.min( maxVal, this.w ) );
- var te = this.elements;
- var me = matrix.elements;
+ return this;
- for ( var i = 0; i < 9; i ++ ) {
+ }
- if ( te[ i ] !== me[ i ] ) return false;
+ clampLength( min, max ) {
- }
+ const length = this.length();
- return true;
+ return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );
- },
+ }
- fromArray: function ( array, offset ) {
+ floor() {
- if ( offset === undefined ) offset = 0;
+ this.x = Math.floor( this.x );
+ this.y = Math.floor( this.y );
+ this.z = Math.floor( this.z );
+ this.w = Math.floor( this.w );
- for ( var i = 0; i < 9; i ++ ) {
+ return this;
- this.elements[ i ] = array[ i + offset ];
+ }
- }
+ ceil() {
- return this;
+ this.x = Math.ceil( this.x );
+ this.y = Math.ceil( this.y );
+ this.z = Math.ceil( this.z );
+ this.w = Math.ceil( this.w );
- },
+ return this;
- toArray: function ( array, offset ) {
+ }
- if ( array === undefined ) array = [];
- if ( offset === undefined ) offset = 0;
+ round() {
- var te = this.elements;
+ this.x = Math.round( this.x );
+ this.y = Math.round( this.y );
+ this.z = Math.round( this.z );
+ this.w = Math.round( this.w );
- array[ offset ] = te[ 0 ];
- array[ offset + 1 ] = te[ 1 ];
- array[ offset + 2 ] = te[ 2 ];
+ return this;
- array[ offset + 3 ] = te[ 3 ];
- array[ offset + 4 ] = te[ 4 ];
- array[ offset + 5 ] = te[ 5 ];
+ }
- array[ offset + 6 ] = te[ 6 ];
- array[ offset + 7 ] = te[ 7 ];
- array[ offset + 8 ] = te[ 8 ];
+ roundToZero() {
- return array;
+ this.x = Math.trunc( this.x );
+ this.y = Math.trunc( this.y );
+ this.z = Math.trunc( this.z );
+ this.w = Math.trunc( this.w );
- }
+ return this;
- } );
+ }
- /**
- * @author mrdoob / http://mrdoob.com/
- * @author alteredq / http://alteredqualia.com/
- * @author szimek / https://github.com/szimek/
- */
+ negate() {
- var _canvas;
+ this.x = - this.x;
+ this.y = - this.y;
+ this.z = - this.z;
+ this.w = - this.w;
- var ImageUtils = {
+ return this;
- getDataURL: function ( image ) {
+ }
- var canvas;
+ dot( v ) {
- if ( typeof HTMLCanvasElement == 'undefined' ) {
+ return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w;
- return image.src;
+ }
- } else if ( image instanceof HTMLCanvasElement ) {
+ lengthSq() {
- canvas = image;
+ return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w;
- } else {
+ }
- if ( _canvas === undefined ) _canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' );
+ length() {
- _canvas.width = image.width;
- _canvas.height = image.height;
+ return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w );
- var context = _canvas.getContext( '2d' );
+ }
- if ( image instanceof ImageData ) {
+ manhattanLength() {
- context.putImageData( image, 0, 0 );
+ return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ) + Math.abs( this.w );
- } else {
+ }
- context.drawImage( image, 0, 0, image.width, image.height );
+ normalize() {
- }
+ return this.divideScalar( this.length() || 1 );
- canvas = _canvas;
+ }
- }
+ setLength( length ) {
- if ( canvas.width > 2048 || canvas.height > 2048 ) {
+ return this.normalize().multiplyScalar( length );
- return canvas.toDataURL( 'image/jpeg', 0.6 );
+ }
- } else {
+ lerp( v, alpha ) {
- return canvas.toDataURL( 'image/png' );
+ this.x += ( v.x - this.x ) * alpha;
+ this.y += ( v.y - this.y ) * alpha;
+ this.z += ( v.z - this.z ) * alpha;
+ this.w += ( v.w - this.w ) * alpha;
- }
+ return this;
- }
+ }
- };
+ lerpVectors( v1, v2, alpha ) {
- /**
- * @author mrdoob / http://mrdoob.com/
- * @author alteredq / http://alteredqualia.com/
- * @author szimek / https://github.com/szimek/
- */
+ this.x = v1.x + ( v2.x - v1.x ) * alpha;
+ this.y = v1.y + ( v2.y - v1.y ) * alpha;
+ this.z = v1.z + ( v2.z - v1.z ) * alpha;
+ this.w = v1.w + ( v2.w - v1.w ) * alpha;
- var textureId = 0;
+ return this;
- function Texture( image, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ) {
+ }
- Object.defineProperty( this, 'id', { value: textureId ++ } );
+ equals( v ) {
- this.uuid = _Math.generateUUID();
+ return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) && ( v.w === this.w ) );
- this.name = '';
+ }
- this.image = image !== undefined ? image : Texture.DEFAULT_IMAGE;
- this.mipmaps = [];
+ fromArray( array, offset = 0 ) {
- this.mapping = mapping !== undefined ? mapping : Texture.DEFAULT_MAPPING;
+ this.x = array[ offset ];
+ this.y = array[ offset + 1 ];
+ this.z = array[ offset + 2 ];
+ this.w = array[ offset + 3 ];
- this.wrapS = wrapS !== undefined ? wrapS : ClampToEdgeWrapping;
- this.wrapT = wrapT !== undefined ? wrapT : ClampToEdgeWrapping;
+ return this;
- this.magFilter = magFilter !== undefined ? magFilter : LinearFilter;
- this.minFilter = minFilter !== undefined ? minFilter : LinearMipmapLinearFilter;
+ }
- this.anisotropy = anisotropy !== undefined ? anisotropy : 1;
+ toArray( array = [], offset = 0 ) {
- this.format = format !== undefined ? format : RGBAFormat;
- this.type = type !== undefined ? type : UnsignedByteType;
+ array[ offset ] = this.x;
+ array[ offset + 1 ] = this.y;
+ array[ offset + 2 ] = this.z;
+ array[ offset + 3 ] = this.w;
- this.offset = new Vector2( 0, 0 );
- this.repeat = new Vector2( 1, 1 );
- this.center = new Vector2( 0, 0 );
- this.rotation = 0;
+ return array;
- this.matrixAutoUpdate = true;
- this.matrix = new Matrix3();
+ }
- this.generateMipmaps = true;
- this.premultiplyAlpha = false;
- this.flipY = true;
- this.unpackAlignment = 4; // valid values: 1, 2, 4, 8 (see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml)
+ fromBufferAttribute( attribute, index ) {
- // Values of encoding !== THREE.LinearEncoding only supported on map, envMap and emissiveMap.
- //
- // Also changing the encoding after already used by a Material will not automatically make the Material
- // update. You need to explicitly call Material.needsUpdate to trigger it to recompile.
- this.encoding = encoding !== undefined ? encoding : LinearEncoding;
+ this.x = attribute.getX( index );
+ this.y = attribute.getY( index );
+ this.z = attribute.getZ( index );
+ this.w = attribute.getW( index );
- this.version = 0;
- this.onUpdate = null;
+ return this;
}
- Texture.DEFAULT_IMAGE = undefined;
- Texture.DEFAULT_MAPPING = UVMapping;
-
- Texture.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
+ random() {
- constructor: Texture,
+ this.x = Math.random();
+ this.y = Math.random();
+ this.z = Math.random();
+ this.w = Math.random();
- isTexture: true,
-
- updateMatrix: function () {
-
- this.matrix.setUvTransform( this.offset.x, this.offset.y, this.repeat.x, this.repeat.y, this.rotation, this.center.x, this.center.y );
+ return this;
- },
+ }
- clone: function () {
+ *[ Symbol.iterator ]() {
- return new this.constructor().copy( this );
+ yield this.x;
+ yield this.y;
+ yield this.z;
+ yield this.w;
- },
+ }
- copy: function ( source ) {
+}
- this.name = source.name;
+/*
+ In options, we can specify:
+ * Texture parameters for an auto-generated target texture
+ * depthBuffer/stencilBuffer: Booleans to indicate if we should generate these buffers
+*/
+class RenderTarget extends EventDispatcher {
- this.image = source.image;
- this.mipmaps = source.mipmaps.slice( 0 );
+ constructor( width = 1, height = 1, options = {} ) {
- this.mapping = source.mapping;
+ super();
- this.wrapS = source.wrapS;
- this.wrapT = source.wrapT;
+ this.isRenderTarget = true;
- this.magFilter = source.magFilter;
- this.minFilter = source.minFilter;
+ this.width = width;
+ this.height = height;
+ this.depth = 1;
- this.anisotropy = source.anisotropy;
+ this.scissor = new Vector4( 0, 0, width, height );
+ this.scissorTest = false;
- this.format = source.format;
- this.type = source.type;
+ this.viewport = new Vector4( 0, 0, width, height );
- this.offset.copy( source.offset );
- this.repeat.copy( source.repeat );
- this.center.copy( source.center );
- this.rotation = source.rotation;
+ const image = { width: width, height: height, depth: 1 };
- this.matrixAutoUpdate = source.matrixAutoUpdate;
- this.matrix.copy( source.matrix );
+ if ( options.encoding !== undefined ) {
- this.generateMipmaps = source.generateMipmaps;
- this.premultiplyAlpha = source.premultiplyAlpha;
- this.flipY = source.flipY;
- this.unpackAlignment = source.unpackAlignment;
- this.encoding = source.encoding;
+ // @deprecated, r152
+ warnOnce( 'THREE.WebGLRenderTarget: option.encoding has been replaced by option.colorSpace.' );
+ options.colorSpace = options.encoding === sRGBEncoding ? SRGBColorSpace : NoColorSpace;
- return this;
+ }
- },
+ options = Object.assign( {
+ generateMipmaps: false,
+ internalFormat: null,
+ minFilter: LinearFilter,
+ depthBuffer: true,
+ stencilBuffer: false,
+ depthTexture: null,
+ samples: 0
+ }, options );
- toJSON: function ( meta ) {
+ this.texture = new Texture( image, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.colorSpace );
+ this.texture.isRenderTargetTexture = true;
- var isRootObject = ( meta === undefined || typeof meta === 'string' );
+ this.texture.flipY = false;
+ this.texture.generateMipmaps = options.generateMipmaps;
+ this.texture.internalFormat = options.internalFormat;
- if ( ! isRootObject && meta.textures[ this.uuid ] !== undefined ) {
+ this.depthBuffer = options.depthBuffer;
+ this.stencilBuffer = options.stencilBuffer;
- return meta.textures[ this.uuid ];
+ this.depthTexture = options.depthTexture;
- }
+ this.samples = options.samples;
- var output = {
+ }
- metadata: {
- version: 4.5,
- type: 'Texture',
- generator: 'Texture.toJSON'
- },
+ setSize( width, height, depth = 1 ) {
- uuid: this.uuid,
- name: this.name,
+ if ( this.width !== width || this.height !== height || this.depth !== depth ) {
- mapping: this.mapping,
+ this.width = width;
+ this.height = height;
+ this.depth = depth;
- repeat: [ this.repeat.x, this.repeat.y ],
- offset: [ this.offset.x, this.offset.y ],
- center: [ this.center.x, this.center.y ],
- rotation: this.rotation,
+ this.texture.image.width = width;
+ this.texture.image.height = height;
+ this.texture.image.depth = depth;
- wrap: [ this.wrapS, this.wrapT ],
+ this.dispose();
- format: this.format,
- type: this.type,
- encoding: this.encoding,
+ }
- minFilter: this.minFilter,
- magFilter: this.magFilter,
- anisotropy: this.anisotropy,
+ this.viewport.set( 0, 0, width, height );
+ this.scissor.set( 0, 0, width, height );
- flipY: this.flipY,
+ }
- premultiplyAlpha: this.premultiplyAlpha,
- unpackAlignment: this.unpackAlignment
+ clone() {
- };
+ return new this.constructor().copy( this );
- if ( this.image !== undefined ) {
+ }
- // TODO: Move to THREE.Image
+ copy( source ) {
- var image = this.image;
+ this.width = source.width;
+ this.height = source.height;
+ this.depth = source.depth;
- if ( image.uuid === undefined ) {
+ this.scissor.copy( source.scissor );
+ this.scissorTest = source.scissorTest;
- image.uuid = _Math.generateUUID(); // UGH
+ this.viewport.copy( source.viewport );
- }
+ this.texture = source.texture.clone();
+ this.texture.isRenderTargetTexture = true;
- if ( ! isRootObject && meta.images[ image.uuid ] === undefined ) {
+ // ensure image object is not shared, see #20328
- var url;
+ const image = Object.assign( {}, source.texture.image );
+ this.texture.source = new Source( image );
- if ( Array.isArray( image ) ) {
+ this.depthBuffer = source.depthBuffer;
+ this.stencilBuffer = source.stencilBuffer;
- // process array of images e.g. CubeTexture
+ if ( source.depthTexture !== null ) this.depthTexture = source.depthTexture.clone();
- url = [];
+ this.samples = source.samples;
- for ( var i = 0, l = image.length; i < l; i ++ ) {
+ return this;
- url.push( ImageUtils.getDataURL( image[ i ] ) );
+ }
- }
+ dispose() {
- } else {
+ this.dispatchEvent( { type: 'dispose' } );
- // process single image
+ }
- url = ImageUtils.getDataURL( image );
+}
- }
+class WebGLRenderTarget extends RenderTarget {
- meta.images[ image.uuid ] = {
- uuid: image.uuid,
- url: url
- };
+ constructor( width = 1, height = 1, options = {} ) {
- }
+ super( width, height, options );
- output.image = image.uuid;
+ this.isWebGLRenderTarget = true;
- }
+ }
- if ( ! isRootObject ) {
+}
- meta.textures[ this.uuid ] = output;
+class DataArrayTexture extends Texture {
- }
+ constructor( data = null, width = 1, height = 1, depth = 1 ) {
- return output;
+ super( null );
- },
+ this.isDataArrayTexture = true;
- dispose: function () {
+ this.image = { data, width, height, depth };
- this.dispatchEvent( { type: 'dispose' } );
+ this.magFilter = NearestFilter;
+ this.minFilter = NearestFilter;
- },
+ this.wrapR = ClampToEdgeWrapping;
- transformUv: function ( uv ) {
+ this.generateMipmaps = false;
+ this.flipY = false;
+ this.unpackAlignment = 1;
- if ( this.mapping !== UVMapping ) return uv;
+ }
- uv.applyMatrix3( this.matrix );
+}
- if ( uv.x < 0 || uv.x > 1 ) {
+class WebGLArrayRenderTarget extends WebGLRenderTarget {
- switch ( this.wrapS ) {
+ constructor( width = 1, height = 1, depth = 1 ) {
- case RepeatWrapping:
+ super( width, height );
- uv.x = uv.x - Math.floor( uv.x );
- break;
+ this.isWebGLArrayRenderTarget = true;
- case ClampToEdgeWrapping:
+ this.depth = depth;
- uv.x = uv.x < 0 ? 0 : 1;
- break;
+ this.texture = new DataArrayTexture( null, width, height, depth );
- case MirroredRepeatWrapping:
+ this.texture.isRenderTargetTexture = true;
- if ( Math.abs( Math.floor( uv.x ) % 2 ) === 1 ) {
+ }
- uv.x = Math.ceil( uv.x ) - uv.x;
+}
- } else {
+class Data3DTexture extends Texture {
- uv.x = uv.x - Math.floor( uv.x );
+ constructor( data = null, width = 1, height = 1, depth = 1 ) {
- }
- break;
+ // We're going to add .setXXX() methods for setting properties later.
+ // Users can still set in DataTexture3D directly.
+ //
+ // const texture = new THREE.DataTexture3D( data, width, height, depth );
+ // texture.anisotropy = 16;
+ //
+ // See #14839
- }
+ super( null );
- }
+ this.isData3DTexture = true;
- if ( uv.y < 0 || uv.y > 1 ) {
+ this.image = { data, width, height, depth };
- switch ( this.wrapT ) {
+ this.magFilter = NearestFilter;
+ this.minFilter = NearestFilter;
- case RepeatWrapping:
+ this.wrapR = ClampToEdgeWrapping;
- uv.y = uv.y - Math.floor( uv.y );
- break;
+ this.generateMipmaps = false;
+ this.flipY = false;
+ this.unpackAlignment = 1;
- case ClampToEdgeWrapping:
+ }
- uv.y = uv.y < 0 ? 0 : 1;
- break;
+}
- case MirroredRepeatWrapping:
+class WebGL3DRenderTarget extends WebGLRenderTarget {
- if ( Math.abs( Math.floor( uv.y ) % 2 ) === 1 ) {
+ constructor( width = 1, height = 1, depth = 1 ) {
- uv.y = Math.ceil( uv.y ) - uv.y;
+ super( width, height );
- } else {
+ this.isWebGL3DRenderTarget = true;
- uv.y = uv.y - Math.floor( uv.y );
+ this.depth = depth;
- }
- break;
+ this.texture = new Data3DTexture( null, width, height, depth );
- }
+ this.texture.isRenderTargetTexture = true;
- }
+ }
- if ( this.flipY ) {
+}
- uv.y = 1 - uv.y;
+class WebGLMultipleRenderTargets extends WebGLRenderTarget {
- }
+ constructor( width = 1, height = 1, count = 1, options = {} ) {
- return uv;
+ super( width, height, options );
- }
+ this.isWebGLMultipleRenderTargets = true;
- } );
+ const texture = this.texture;
- Object.defineProperty( Texture.prototype, "needsUpdate", {
+ this.texture = [];
- set: function ( value ) {
+ for ( let i = 0; i < count; i ++ ) {
- if ( value === true ) this.version ++;
+ this.texture[ i ] = texture.clone();
+ this.texture[ i ].isRenderTargetTexture = true;
}
- } );
-
- /**
- * @author supereggbert / http://www.paulbrunt.co.uk/
- * @author philogb / http://blog.thejit.org/
- * @author mikael emtinger / http://gomo.se/
- * @author egraether / http://egraether.com/
- * @author WestLangley / http://github.com/WestLangley
- */
-
- function Vector4( x, y, z, w ) {
-
- this.x = x || 0;
- this.y = y || 0;
- this.z = z || 0;
- this.w = ( w !== undefined ) ? w : 1;
-
}
- Object.defineProperties( Vector4.prototype, {
-
- "width": {
-
- get: function () {
+ setSize( width, height, depth = 1 ) {
- return this.z;
+ if ( this.width !== width || this.height !== height || this.depth !== depth ) {
- },
+ this.width = width;
+ this.height = height;
+ this.depth = depth;
- set: function ( value ) {
+ for ( let i = 0, il = this.texture.length; i < il; i ++ ) {
- this.z = value;
+ this.texture[ i ].image.width = width;
+ this.texture[ i ].image.height = height;
+ this.texture[ i ].image.depth = depth;
}
- },
-
- "height": {
+ this.dispose();
- get: function () {
+ }
- return this.w;
+ this.viewport.set( 0, 0, width, height );
+ this.scissor.set( 0, 0, width, height );
- },
+ }
- set: function ( value ) {
+ copy( source ) {
- this.w = value;
+ this.dispose();
- }
+ this.width = source.width;
+ this.height = source.height;
+ this.depth = source.depth;
- }
+ this.scissor.copy( source.scissor );
+ this.scissorTest = source.scissorTest;
- } );
+ this.viewport.copy( source.viewport );
- Object.assign( Vector4.prototype, {
+ this.depthBuffer = source.depthBuffer;
+ this.stencilBuffer = source.stencilBuffer;
- isVector4: true,
+ if ( source.depthTexture !== null ) this.depthTexture = source.depthTexture.clone();
- set: function ( x, y, z, w ) {
+ this.texture.length = 0;
- this.x = x;
- this.y = y;
- this.z = z;
- this.w = w;
+ for ( let i = 0, il = source.texture.length; i < il; i ++ ) {
- return this;
+ this.texture[ i ] = source.texture[ i ].clone();
+ this.texture[ i ].isRenderTargetTexture = true;
- },
+ }
- setScalar: function ( scalar ) {
+ return this;
- this.x = scalar;
- this.y = scalar;
- this.z = scalar;
- this.w = scalar;
+ }
- return this;
+}
- },
+class Quaternion {
- setX: function ( x ) {
+ constructor( x = 0, y = 0, z = 0, w = 1 ) {
- this.x = x;
+ this.isQuaternion = true;
- return this;
+ this._x = x;
+ this._y = y;
+ this._z = z;
+ this._w = w;
- },
+ }
- setY: function ( y ) {
+ static slerpFlat( dst, dstOffset, src0, srcOffset0, src1, srcOffset1, t ) {
- this.y = y;
+ // fuzz-free, array-based Quaternion SLERP operation
- return this;
+ let x0 = src0[ srcOffset0 + 0 ],
+ y0 = src0[ srcOffset0 + 1 ],
+ z0 = src0[ srcOffset0 + 2 ],
+ w0 = src0[ srcOffset0 + 3 ];
- },
+ const x1 = src1[ srcOffset1 + 0 ],
+ y1 = src1[ srcOffset1 + 1 ],
+ z1 = src1[ srcOffset1 + 2 ],
+ w1 = src1[ srcOffset1 + 3 ];
- setZ: function ( z ) {
+ if ( t === 0 ) {
- this.z = z;
+ dst[ dstOffset + 0 ] = x0;
+ dst[ dstOffset + 1 ] = y0;
+ dst[ dstOffset + 2 ] = z0;
+ dst[ dstOffset + 3 ] = w0;
+ return;
- return this;
+ }
- },
+ if ( t === 1 ) {
- setW: function ( w ) {
+ dst[ dstOffset + 0 ] = x1;
+ dst[ dstOffset + 1 ] = y1;
+ dst[ dstOffset + 2 ] = z1;
+ dst[ dstOffset + 3 ] = w1;
+ return;
- this.w = w;
+ }
- return this;
+ if ( w0 !== w1 || x0 !== x1 || y0 !== y1 || z0 !== z1 ) {
- },
+ let s = 1 - t;
+ const cos = x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1,
+ dir = ( cos >= 0 ? 1 : - 1 ),
+ sqrSin = 1 - cos * cos;
- setComponent: function ( index, value ) {
+ // Skip the Slerp for tiny steps to avoid numeric problems:
+ if ( sqrSin > Number.EPSILON ) {
- switch ( index ) {
+ const sin = Math.sqrt( sqrSin ),
+ len = Math.atan2( sin, cos * dir );
- case 0: this.x = value; break;
- case 1: this.y = value; break;
- case 2: this.z = value; break;
- case 3: this.w = value; break;
- default: throw new Error( 'index is out of range: ' + index );
+ s = Math.sin( s * len ) / sin;
+ t = Math.sin( t * len ) / sin;
}
- return this;
+ const tDir = t * dir;
- },
+ x0 = x0 * s + x1 * tDir;
+ y0 = y0 * s + y1 * tDir;
+ z0 = z0 * s + z1 * tDir;
+ w0 = w0 * s + w1 * tDir;
- getComponent: function ( index ) {
+ // Normalize in case we just did a lerp:
+ if ( s === 1 - t ) {
- switch ( index ) {
+ const f = 1 / Math.sqrt( x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0 );
- case 0: return this.x;
- case 1: return this.y;
- case 2: return this.z;
- case 3: return this.w;
- default: throw new Error( 'index is out of range: ' + index );
+ x0 *= f;
+ y0 *= f;
+ z0 *= f;
+ w0 *= f;
}
- },
+ }
- clone: function () {
+ dst[ dstOffset ] = x0;
+ dst[ dstOffset + 1 ] = y0;
+ dst[ dstOffset + 2 ] = z0;
+ dst[ dstOffset + 3 ] = w0;
- return new this.constructor( this.x, this.y, this.z, this.w );
+ }
- },
+ static multiplyQuaternionsFlat( dst, dstOffset, src0, srcOffset0, src1, srcOffset1 ) {
- copy: function ( v ) {
+ const x0 = src0[ srcOffset0 ];
+ const y0 = src0[ srcOffset0 + 1 ];
+ const z0 = src0[ srcOffset0 + 2 ];
+ const w0 = src0[ srcOffset0 + 3 ];
- this.x = v.x;
- this.y = v.y;
- this.z = v.z;
- this.w = ( v.w !== undefined ) ? v.w : 1;
+ const x1 = src1[ srcOffset1 ];
+ const y1 = src1[ srcOffset1 + 1 ];
+ const z1 = src1[ srcOffset1 + 2 ];
+ const w1 = src1[ srcOffset1 + 3 ];
- return this;
+ dst[ dstOffset ] = x0 * w1 + w0 * x1 + y0 * z1 - z0 * y1;
+ dst[ dstOffset + 1 ] = y0 * w1 + w0 * y1 + z0 * x1 - x0 * z1;
+ dst[ dstOffset + 2 ] = z0 * w1 + w0 * z1 + x0 * y1 - y0 * x1;
+ dst[ dstOffset + 3 ] = w0 * w1 - x0 * x1 - y0 * y1 - z0 * z1;
- },
+ return dst;
- add: function ( v, w ) {
+ }
- if ( w !== undefined ) {
+ get x() {
- console.warn( 'THREE.Vector4: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );
- return this.addVectors( v, w );
+ return this._x;
- }
+ }
- this.x += v.x;
- this.y += v.y;
- this.z += v.z;
- this.w += v.w;
+ set x( value ) {
- return this;
+ this._x = value;
+ this._onChangeCallback();
- },
+ }
- addScalar: function ( s ) {
+ get y() {
- this.x += s;
- this.y += s;
- this.z += s;
- this.w += s;
+ return this._y;
- return this;
+ }
- },
+ set y( value ) {
- addVectors: function ( a, b ) {
+ this._y = value;
+ this._onChangeCallback();
- this.x = a.x + b.x;
- this.y = a.y + b.y;
- this.z = a.z + b.z;
- this.w = a.w + b.w;
+ }
- return this;
+ get z() {
- },
+ return this._z;
- addScaledVector: function ( v, s ) {
+ }
- this.x += v.x * s;
- this.y += v.y * s;
- this.z += v.z * s;
- this.w += v.w * s;
+ set z( value ) {
- return this;
+ this._z = value;
+ this._onChangeCallback();
- },
+ }
- sub: function ( v, w ) {
+ get w() {
- if ( w !== undefined ) {
+ return this._w;
- console.warn( 'THREE.Vector4: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );
- return this.subVectors( v, w );
+ }
- }
+ set w( value ) {
- this.x -= v.x;
- this.y -= v.y;
- this.z -= v.z;
- this.w -= v.w;
+ this._w = value;
+ this._onChangeCallback();
- return this;
+ }
- },
+ set( x, y, z, w ) {
- subScalar: function ( s ) {
+ this._x = x;
+ this._y = y;
+ this._z = z;
+ this._w = w;
- this.x -= s;
- this.y -= s;
- this.z -= s;
- this.w -= s;
+ this._onChangeCallback();
- return this;
+ return this;
- },
+ }
- subVectors: function ( a, b ) {
+ clone() {
- this.x = a.x - b.x;
- this.y = a.y - b.y;
- this.z = a.z - b.z;
- this.w = a.w - b.w;
+ return new this.constructor( this._x, this._y, this._z, this._w );
- return this;
+ }
- },
+ copy( quaternion ) {
- multiplyScalar: function ( scalar ) {
+ this._x = quaternion.x;
+ this._y = quaternion.y;
+ this._z = quaternion.z;
+ this._w = quaternion.w;
- this.x *= scalar;
- this.y *= scalar;
- this.z *= scalar;
- this.w *= scalar;
+ this._onChangeCallback();
- return this;
+ return this;
- },
+ }
- applyMatrix4: function ( m ) {
+ setFromEuler( euler, update ) {
- var x = this.x, y = this.y, z = this.z, w = this.w;
- var e = m.elements;
+ const x = euler._x, y = euler._y, z = euler._z, order = euler._order;
- this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] * w;
- this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] * w;
- this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] * w;
- this.w = e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] * w;
+ // http://www.mathworks.com/matlabcentral/fileexchange/
+ // 20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/
+ // content/SpinCalc.m
- return this;
+ const cos = Math.cos;
+ const sin = Math.sin;
- },
+ const c1 = cos( x / 2 );
+ const c2 = cos( y / 2 );
+ const c3 = cos( z / 2 );
- divideScalar: function ( scalar ) {
+ const s1 = sin( x / 2 );
+ const s2 = sin( y / 2 );
+ const s3 = sin( z / 2 );
- return this.multiplyScalar( 1 / scalar );
+ switch ( order ) {
- },
+ case 'XYZ':
+ this._x = s1 * c2 * c3 + c1 * s2 * s3;
+ this._y = c1 * s2 * c3 - s1 * c2 * s3;
+ this._z = c1 * c2 * s3 + s1 * s2 * c3;
+ this._w = c1 * c2 * c3 - s1 * s2 * s3;
+ break;
- setAxisAngleFromQuaternion: function ( q ) {
+ case 'YXZ':
+ this._x = s1 * c2 * c3 + c1 * s2 * s3;
+ this._y = c1 * s2 * c3 - s1 * c2 * s3;
+ this._z = c1 * c2 * s3 - s1 * s2 * c3;
+ this._w = c1 * c2 * c3 + s1 * s2 * s3;
+ break;
- // http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm
-
- // q is assumed to be normalized
-
- this.w = 2 * Math.acos( q.w );
+ case 'ZXY':
+ this._x = s1 * c2 * c3 - c1 * s2 * s3;
+ this._y = c1 * s2 * c3 + s1 * c2 * s3;
+ this._z = c1 * c2 * s3 + s1 * s2 * c3;
+ this._w = c1 * c2 * c3 - s1 * s2 * s3;
+ break;
- var s = Math.sqrt( 1 - q.w * q.w );
+ case 'ZYX':
+ this._x = s1 * c2 * c3 - c1 * s2 * s3;
+ this._y = c1 * s2 * c3 + s1 * c2 * s3;
+ this._z = c1 * c2 * s3 - s1 * s2 * c3;
+ this._w = c1 * c2 * c3 + s1 * s2 * s3;
+ break;
- if ( s < 0.0001 ) {
+ case 'YZX':
+ this._x = s1 * c2 * c3 + c1 * s2 * s3;
+ this._y = c1 * s2 * c3 + s1 * c2 * s3;
+ this._z = c1 * c2 * s3 - s1 * s2 * c3;
+ this._w = c1 * c2 * c3 - s1 * s2 * s3;
+ break;
- this.x = 1;
- this.y = 0;
- this.z = 0;
+ case 'XZY':
+ this._x = s1 * c2 * c3 - c1 * s2 * s3;
+ this._y = c1 * s2 * c3 - s1 * c2 * s3;
+ this._z = c1 * c2 * s3 + s1 * s2 * c3;
+ this._w = c1 * c2 * c3 + s1 * s2 * s3;
+ break;
- } else {
+ default:
+ console.warn( 'THREE.Quaternion: .setFromEuler() encountered an unknown order: ' + order );
- this.x = q.x / s;
- this.y = q.y / s;
- this.z = q.z / s;
+ }
- }
+ if ( update !== false ) this._onChangeCallback();
- return this;
+ return this;
- },
+ }
- setAxisAngleFromRotationMatrix: function ( m ) {
+ setFromAxisAngle( axis, angle ) {
- // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm
+ // http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm
- // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
+ // assumes axis is normalized
- var angle, x, y, z, // variables for result
- epsilon = 0.01, // margin to allow for rounding errors
- epsilon2 = 0.1, // margin to distinguish between 0 and 180 degrees
+ const halfAngle = angle / 2, s = Math.sin( halfAngle );
- te = m.elements,
+ this._x = axis.x * s;
+ this._y = axis.y * s;
+ this._z = axis.z * s;
+ this._w = Math.cos( halfAngle );
- m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ],
- m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ],
- m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ];
+ this._onChangeCallback();
- if ( ( Math.abs( m12 - m21 ) < epsilon ) &&
- ( Math.abs( m13 - m31 ) < epsilon ) &&
- ( Math.abs( m23 - m32 ) < epsilon ) ) {
+ return this;
- // singularity found
- // first check for identity matrix which must have +1 for all terms
- // in leading diagonal and zero in other terms
+ }
- if ( ( Math.abs( m12 + m21 ) < epsilon2 ) &&
- ( Math.abs( m13 + m31 ) < epsilon2 ) &&
- ( Math.abs( m23 + m32 ) < epsilon2 ) &&
- ( Math.abs( m11 + m22 + m33 - 3 ) < epsilon2 ) ) {
+ setFromRotationMatrix( m ) {
- // this singularity is identity matrix so angle = 0
+ // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm
- this.set( 1, 0, 0, 0 );
+ // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
- return this; // zero angle, arbitrary axis
+ const te = m.elements,
- }
+ m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ],
+ m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ],
+ m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ],
- // otherwise this singularity is angle = 180
+ trace = m11 + m22 + m33;
- angle = Math.PI;
+ if ( trace > 0 ) {
- var xx = ( m11 + 1 ) / 2;
- var yy = ( m22 + 1 ) / 2;
- var zz = ( m33 + 1 ) / 2;
- var xy = ( m12 + m21 ) / 4;
- var xz = ( m13 + m31 ) / 4;
- var yz = ( m23 + m32 ) / 4;
+ const s = 0.5 / Math.sqrt( trace + 1.0 );
- if ( ( xx > yy ) && ( xx > zz ) ) {
+ this._w = 0.25 / s;
+ this._x = ( m32 - m23 ) * s;
+ this._y = ( m13 - m31 ) * s;
+ this._z = ( m21 - m12 ) * s;
- // m11 is the largest diagonal term
+ } else if ( m11 > m22 && m11 > m33 ) {
- if ( xx < epsilon ) {
+ const s = 2.0 * Math.sqrt( 1.0 + m11 - m22 - m33 );
- x = 0;
- y = 0.707106781;
- z = 0.707106781;
+ this._w = ( m32 - m23 ) / s;
+ this._x = 0.25 * s;
+ this._y = ( m12 + m21 ) / s;
+ this._z = ( m13 + m31 ) / s;
- } else {
+ } else if ( m22 > m33 ) {
- x = Math.sqrt( xx );
- y = xy / x;
- z = xz / x;
+ const s = 2.0 * Math.sqrt( 1.0 + m22 - m11 - m33 );
- }
+ this._w = ( m13 - m31 ) / s;
+ this._x = ( m12 + m21 ) / s;
+ this._y = 0.25 * s;
+ this._z = ( m23 + m32 ) / s;
- } else if ( yy > zz ) {
+ } else {
- // m22 is the largest diagonal term
+ const s = 2.0 * Math.sqrt( 1.0 + m33 - m11 - m22 );
- if ( yy < epsilon ) {
+ this._w = ( m21 - m12 ) / s;
+ this._x = ( m13 + m31 ) / s;
+ this._y = ( m23 + m32 ) / s;
+ this._z = 0.25 * s;
- x = 0.707106781;
- y = 0;
- z = 0.707106781;
+ }
- } else {
+ this._onChangeCallback();
- y = Math.sqrt( yy );
- x = xy / y;
- z = yz / y;
+ return this;
- }
+ }
- } else {
+ setFromUnitVectors( vFrom, vTo ) {
- // m33 is the largest diagonal term so base result on this
+ // assumes direction vectors vFrom and vTo are normalized
- if ( zz < epsilon ) {
+ let r = vFrom.dot( vTo ) + 1;
- x = 0.707106781;
- y = 0.707106781;
- z = 0;
+ if ( r < Number.EPSILON ) {
- } else {
+ // vFrom and vTo point in opposite directions
- z = Math.sqrt( zz );
- x = xz / z;
- y = yz / z;
+ r = 0;
- }
+ if ( Math.abs( vFrom.x ) > Math.abs( vFrom.z ) ) {
- }
+ this._x = - vFrom.y;
+ this._y = vFrom.x;
+ this._z = 0;
+ this._w = r;
- this.set( x, y, z, angle );
+ } else {
- return this; // return 180 deg rotation
+ this._x = 0;
+ this._y = - vFrom.z;
+ this._z = vFrom.y;
+ this._w = r;
}
- // as we have reached here there are no singularities so we can handle normally
+ } else {
- var s = Math.sqrt( ( m32 - m23 ) * ( m32 - m23 ) +
- ( m13 - m31 ) * ( m13 - m31 ) +
- ( m21 - m12 ) * ( m21 - m12 ) ); // used to normalize
+ // crossVectors( vFrom, vTo ); // inlined to avoid cyclic dependency on Vector3
- if ( Math.abs( s ) < 0.001 ) s = 1;
+ this._x = vFrom.y * vTo.z - vFrom.z * vTo.y;
+ this._y = vFrom.z * vTo.x - vFrom.x * vTo.z;
+ this._z = vFrom.x * vTo.y - vFrom.y * vTo.x;
+ this._w = r;
- // prevent divide by zero, should not happen if matrix is orthogonal and should be
- // caught by singularity test above, but I've left it in just in case
+ }
- this.x = ( m32 - m23 ) / s;
- this.y = ( m13 - m31 ) / s;
- this.z = ( m21 - m12 ) / s;
- this.w = Math.acos( ( m11 + m22 + m33 - 1 ) / 2 );
+ return this.normalize();
- return this;
+ }
- },
+ angleTo( q ) {
- min: function ( v ) {
+ return 2 * Math.acos( Math.abs( clamp( this.dot( q ), - 1, 1 ) ) );
- this.x = Math.min( this.x, v.x );
- this.y = Math.min( this.y, v.y );
- this.z = Math.min( this.z, v.z );
- this.w = Math.min( this.w, v.w );
+ }
- return this;
+ rotateTowards( q, step ) {
- },
+ const angle = this.angleTo( q );
- max: function ( v ) {
+ if ( angle === 0 ) return this;
- this.x = Math.max( this.x, v.x );
- this.y = Math.max( this.y, v.y );
- this.z = Math.max( this.z, v.z );
- this.w = Math.max( this.w, v.w );
+ const t = Math.min( 1, step / angle );
- return this;
+ this.slerp( q, t );
- },
+ return this;
- clamp: function ( min, max ) {
+ }
- // assumes min < max, componentwise
+ identity() {
- this.x = Math.max( min.x, Math.min( max.x, this.x ) );
- this.y = Math.max( min.y, Math.min( max.y, this.y ) );
- this.z = Math.max( min.z, Math.min( max.z, this.z ) );
- this.w = Math.max( min.w, Math.min( max.w, this.w ) );
+ return this.set( 0, 0, 0, 1 );
- return this;
+ }
- },
+ invert() {
- clampScalar: function ( minVal, maxVal ) {
+ // quaternion is assumed to have unit length
- this.x = Math.max( minVal, Math.min( maxVal, this.x ) );
- this.y = Math.max( minVal, Math.min( maxVal, this.y ) );
- this.z = Math.max( minVal, Math.min( maxVal, this.z ) );
- this.w = Math.max( minVal, Math.min( maxVal, this.w ) );
+ return this.conjugate();
- return this;
+ }
- },
+ conjugate() {
- clampLength: function ( min, max ) {
+ this._x *= - 1;
+ this._y *= - 1;
+ this._z *= - 1;
- var length = this.length();
+ this._onChangeCallback();
- return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );
+ return this;
- },
+ }
- floor: function () {
+ dot( v ) {
- this.x = Math.floor( this.x );
- this.y = Math.floor( this.y );
- this.z = Math.floor( this.z );
- this.w = Math.floor( this.w );
+ return this._x * v._x + this._y * v._y + this._z * v._z + this._w * v._w;
- return this;
+ }
- },
+ lengthSq() {
- ceil: function () {
+ return this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w;
- this.x = Math.ceil( this.x );
- this.y = Math.ceil( this.y );
- this.z = Math.ceil( this.z );
- this.w = Math.ceil( this.w );
+ }
- return this;
+ length() {
- },
+ return Math.sqrt( this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w );
- round: function () {
+ }
- this.x = Math.round( this.x );
- this.y = Math.round( this.y );
- this.z = Math.round( this.z );
- this.w = Math.round( this.w );
+ normalize() {
- return this;
+ let l = this.length();
- },
+ if ( l === 0 ) {
- roundToZero: function () {
+ this._x = 0;
+ this._y = 0;
+ this._z = 0;
+ this._w = 1;
- this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );
- this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );
- this.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z );
- this.w = ( this.w < 0 ) ? Math.ceil( this.w ) : Math.floor( this.w );
+ } else {
- return this;
+ l = 1 / l;
- },
+ this._x = this._x * l;
+ this._y = this._y * l;
+ this._z = this._z * l;
+ this._w = this._w * l;
- negate: function () {
+ }
- this.x = - this.x;
- this.y = - this.y;
- this.z = - this.z;
- this.w = - this.w;
+ this._onChangeCallback();
- return this;
+ return this;
- },
+ }
- dot: function ( v ) {
+ multiply( q ) {
- return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w;
+ return this.multiplyQuaternions( this, q );
- },
+ }
- lengthSq: function () {
+ premultiply( q ) {
- return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w;
+ return this.multiplyQuaternions( q, this );
- },
+ }
- length: function () {
+ multiplyQuaternions( a, b ) {
- return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w );
+ // from http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm
- },
+ const qax = a._x, qay = a._y, qaz = a._z, qaw = a._w;
+ const qbx = b._x, qby = b._y, qbz = b._z, qbw = b._w;
- manhattanLength: function () {
+ this._x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby;
+ this._y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz;
+ this._z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx;
+ this._w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz;
- return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ) + Math.abs( this.w );
+ this._onChangeCallback();
- },
+ return this;
+
+ }
- normalize: function () {
+ slerp( qb, t ) {
- return this.divideScalar( this.length() || 1 );
+ if ( t === 0 ) return this;
+ if ( t === 1 ) return this.copy( qb );
- },
+ const x = this._x, y = this._y, z = this._z, w = this._w;
- setLength: function ( length ) {
+ // http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/
- return this.normalize().multiplyScalar( length );
+ let cosHalfTheta = w * qb._w + x * qb._x + y * qb._y + z * qb._z;
- },
+ if ( cosHalfTheta < 0 ) {
- lerp: function ( v, alpha ) {
+ this._w = - qb._w;
+ this._x = - qb._x;
+ this._y = - qb._y;
+ this._z = - qb._z;
- this.x += ( v.x - this.x ) * alpha;
- this.y += ( v.y - this.y ) * alpha;
- this.z += ( v.z - this.z ) * alpha;
- this.w += ( v.w - this.w ) * alpha;
+ cosHalfTheta = - cosHalfTheta;
- return this;
+ } else {
- },
+ this.copy( qb );
- lerpVectors: function ( v1, v2, alpha ) {
+ }
- return this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 );
+ if ( cosHalfTheta >= 1.0 ) {
- },
+ this._w = w;
+ this._x = x;
+ this._y = y;
+ this._z = z;
- equals: function ( v ) {
+ return this;
- return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) && ( v.w === this.w ) );
+ }
- },
+ const sqrSinHalfTheta = 1.0 - cosHalfTheta * cosHalfTheta;
- fromArray: function ( array, offset ) {
+ if ( sqrSinHalfTheta <= Number.EPSILON ) {
- if ( offset === undefined ) offset = 0;
+ const s = 1 - t;
+ this._w = s * w + t * this._w;
+ this._x = s * x + t * this._x;
+ this._y = s * y + t * this._y;
+ this._z = s * z + t * this._z;
- this.x = array[ offset ];
- this.y = array[ offset + 1 ];
- this.z = array[ offset + 2 ];
- this.w = array[ offset + 3 ];
+ this.normalize();
+ this._onChangeCallback();
return this;
- },
-
- toArray: function ( array, offset ) {
+ }
- if ( array === undefined ) array = [];
- if ( offset === undefined ) offset = 0;
+ const sinHalfTheta = Math.sqrt( sqrSinHalfTheta );
+ const halfTheta = Math.atan2( sinHalfTheta, cosHalfTheta );
+ const ratioA = Math.sin( ( 1 - t ) * halfTheta ) / sinHalfTheta,
+ ratioB = Math.sin( t * halfTheta ) / sinHalfTheta;
- array[ offset ] = this.x;
- array[ offset + 1 ] = this.y;
- array[ offset + 2 ] = this.z;
- array[ offset + 3 ] = this.w;
+ this._w = ( w * ratioA + this._w * ratioB );
+ this._x = ( x * ratioA + this._x * ratioB );
+ this._y = ( y * ratioA + this._y * ratioB );
+ this._z = ( z * ratioA + this._z * ratioB );
- return array;
+ this._onChangeCallback();
- },
+ return this;
- fromBufferAttribute: function ( attribute, index, offset ) {
+ }
- if ( offset !== undefined ) {
+ slerpQuaternions( qa, qb, t ) {
- console.warn( 'THREE.Vector4: offset has been removed from .fromBufferAttribute().' );
+ return this.copy( qa ).slerp( qb, t );
- }
+ }
- this.x = attribute.getX( index );
- this.y = attribute.getY( index );
- this.z = attribute.getZ( index );
- this.w = attribute.getW( index );
+ random() {
- return this;
+ // Derived from http://planning.cs.uiuc.edu/node198.html
+ // Note, this source uses w, x, y, z ordering,
+ // so we swap the order below.
- }
+ const u1 = Math.random();
+ const sqrt1u1 = Math.sqrt( 1 - u1 );
+ const sqrtu1 = Math.sqrt( u1 );
- } );
+ const u2 = 2 * Math.PI * Math.random();
- /**
- * @author szimek / https://github.com/szimek/
- * @author alteredq / http://alteredqualia.com/
- * @author Marius Kintel / https://github.com/kintel
- */
+ const u3 = 2 * Math.PI * Math.random();
- /*
- In options, we can specify:
- * Texture parameters for an auto-generated target texture
- * depthBuffer/stencilBuffer: Booleans to indicate if we should generate these buffers
- */
- function WebGLRenderTarget( width, height, options ) {
+ return this.set(
+ sqrt1u1 * Math.cos( u2 ),
+ sqrtu1 * Math.sin( u3 ),
+ sqrtu1 * Math.cos( u3 ),
+ sqrt1u1 * Math.sin( u2 ),
+ );
- this.width = width;
- this.height = height;
+ }
- this.scissor = new Vector4( 0, 0, width, height );
- this.scissorTest = false;
+ equals( quaternion ) {
- this.viewport = new Vector4( 0, 0, width, height );
+ return ( quaternion._x === this._x ) && ( quaternion._y === this._y ) && ( quaternion._z === this._z ) && ( quaternion._w === this._w );
- options = options || {};
+ }
- this.texture = new Texture( undefined, undefined, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding );
+ fromArray( array, offset = 0 ) {
- this.texture.image = {};
- this.texture.image.width = width;
- this.texture.image.height = height;
+ this._x = array[ offset ];
+ this._y = array[ offset + 1 ];
+ this._z = array[ offset + 2 ];
+ this._w = array[ offset + 3 ];
- this.texture.generateMipmaps = options.generateMipmaps !== undefined ? options.generateMipmaps : false;
- this.texture.minFilter = options.minFilter !== undefined ? options.minFilter : LinearFilter;
+ this._onChangeCallback();
- this.depthBuffer = options.depthBuffer !== undefined ? options.depthBuffer : true;
- this.stencilBuffer = options.stencilBuffer !== undefined ? options.stencilBuffer : true;
- this.depthTexture = options.depthTexture !== undefined ? options.depthTexture : null;
+ return this;
}
- WebGLRenderTarget.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
+ toArray( array = [], offset = 0 ) {
- constructor: WebGLRenderTarget,
+ array[ offset ] = this._x;
+ array[ offset + 1 ] = this._y;
+ array[ offset + 2 ] = this._z;
+ array[ offset + 3 ] = this._w;
- isWebGLRenderTarget: true,
+ return array;
- setSize: function ( width, height ) {
+ }
- if ( this.width !== width || this.height !== height ) {
+ fromBufferAttribute( attribute, index ) {
- this.width = width;
- this.height = height;
+ this._x = attribute.getX( index );
+ this._y = attribute.getY( index );
+ this._z = attribute.getZ( index );
+ this._w = attribute.getW( index );
- this.texture.image.width = width;
- this.texture.image.height = height;
+ return this;
- this.dispose();
+ }
- }
+ toJSON() {
- this.viewport.set( 0, 0, width, height );
- this.scissor.set( 0, 0, width, height );
+ return this.toArray();
- },
+ }
- clone: function () {
+ _onChange( callback ) {
- return new this.constructor().copy( this );
+ this._onChangeCallback = callback;
- },
+ return this;
- copy: function ( source ) {
+ }
- this.width = source.width;
- this.height = source.height;
+ _onChangeCallback() {}
- this.viewport.copy( source.viewport );
+ *[ Symbol.iterator ]() {
- this.texture = source.texture.clone();
+ yield this._x;
+ yield this._y;
+ yield this._z;
+ yield this._w;
- this.depthBuffer = source.depthBuffer;
- this.stencilBuffer = source.stencilBuffer;
- this.depthTexture = source.depthTexture;
+ }
- return this;
+}
- },
+class Vector3 {
- dispose: function () {
+ constructor( x = 0, y = 0, z = 0 ) {
- this.dispatchEvent( { type: 'dispose' } );
+ Vector3.prototype.isVector3 = true;
- }
+ this.x = x;
+ this.y = y;
+ this.z = z;
- } );
+ }
- /**
- * @author Mugen87 / https://github.com/Mugen87
- * @author Matt DesLauriers / @mattdesl
- */
+ set( x, y, z ) {
- function WebGLMultisampleRenderTarget( width, height, options ) {
+ if ( z === undefined ) z = this.z; // sprite.scale.set(x,y)
- WebGLRenderTarget.call( this, width, height, options );
+ this.x = x;
+ this.y = y;
+ this.z = z;
- this.samples = 4;
+ return this;
}
- WebGLMultisampleRenderTarget.prototype = Object.assign( Object.create( WebGLRenderTarget.prototype ), {
+ setScalar( scalar ) {
- constructor: WebGLMultisampleRenderTarget,
+ this.x = scalar;
+ this.y = scalar;
+ this.z = scalar;
- isWebGLMultisampleRenderTarget: true,
+ return this;
- copy: function ( source ) {
+ }
- WebGLRenderTarget.prototype.copy.call( this, source );
+ setX( x ) {
- this.samples = source.samples;
+ this.x = x;
- return this;
+ return this;
- }
+ }
- } );
+ setY( y ) {
- var _v1 = new Vector3();
- var _m1 = new Matrix4();
- var _zero = new Vector3( 0, 0, 0 );
- var _one = new Vector3( 1, 1, 1 );
- var _x = new Vector3();
- var _y = new Vector3();
- var _z = new Vector3();
+ this.y = y;
- /**
- * @author mrdoob / http://mrdoob.com/
- * @author supereggbert / http://www.paulbrunt.co.uk/
- * @author philogb / http://blog.thejit.org/
- * @author jordi_ros / http://plattsoft.com
- * @author D1plo1d / http://github.com/D1plo1d
- * @author alteredq / http://alteredqualia.com/
- * @author mikael emtinger / http://gomo.se/
- * @author timknip / http://www.floorplanner.com/
- * @author bhouston / http://clara.io
- * @author WestLangley / http://github.com/WestLangley
- */
+ return this;
- function Matrix4() {
+ }
- this.elements = [
+ setZ( z ) {
- 1, 0, 0, 0,
- 0, 1, 0, 0,
- 0, 0, 1, 0,
- 0, 0, 0, 1
+ this.z = z;
- ];
+ return this;
- if ( arguments.length > 0 ) {
+ }
+
+ setComponent( index, value ) {
- console.error( 'THREE.Matrix4: the constructor no longer reads arguments. use .set() instead.' );
+ switch ( index ) {
+
+ case 0: this.x = value; break;
+ case 1: this.y = value; break;
+ case 2: this.z = value; break;
+ default: throw new Error( 'index is out of range: ' + index );
}
+ return this;
+
}
- Object.assign( Matrix4.prototype, {
+ getComponent( index ) {
- isMatrix4: true,
+ switch ( index ) {
- set: function ( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) {
+ case 0: return this.x;
+ case 1: return this.y;
+ case 2: return this.z;
+ default: throw new Error( 'index is out of range: ' + index );
- var te = this.elements;
+ }
- te[ 0 ] = n11; te[ 4 ] = n12; te[ 8 ] = n13; te[ 12 ] = n14;
- te[ 1 ] = n21; te[ 5 ] = n22; te[ 9 ] = n23; te[ 13 ] = n24;
- te[ 2 ] = n31; te[ 6 ] = n32; te[ 10 ] = n33; te[ 14 ] = n34;
- te[ 3 ] = n41; te[ 7 ] = n42; te[ 11 ] = n43; te[ 15 ] = n44;
+ }
- return this;
+ clone() {
- },
+ return new this.constructor( this.x, this.y, this.z );
- identity: function () {
+ }
- this.set(
+ copy( v ) {
- 1, 0, 0, 0,
- 0, 1, 0, 0,
- 0, 0, 1, 0,
- 0, 0, 0, 1
+ this.x = v.x;
+ this.y = v.y;
+ this.z = v.z;
- );
+ return this;
- return this;
+ }
- },
+ add( v ) {
- clone: function () {
+ this.x += v.x;
+ this.y += v.y;
+ this.z += v.z;
- return new Matrix4().fromArray( this.elements );
+ return this;
- },
+ }
- copy: function ( m ) {
+ addScalar( s ) {
- var te = this.elements;
- var me = m.elements;
+ this.x += s;
+ this.y += s;
+ this.z += s;
- te[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ]; te[ 3 ] = me[ 3 ];
- te[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ]; te[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ];
- te[ 8 ] = me[ 8 ]; te[ 9 ] = me[ 9 ]; te[ 10 ] = me[ 10 ]; te[ 11 ] = me[ 11 ];
- te[ 12 ] = me[ 12 ]; te[ 13 ] = me[ 13 ]; te[ 14 ] = me[ 14 ]; te[ 15 ] = me[ 15 ];
+ return this;
- return this;
+ }
- },
+ addVectors( a, b ) {
- copyPosition: function ( m ) {
+ this.x = a.x + b.x;
+ this.y = a.y + b.y;
+ this.z = a.z + b.z;
- var te = this.elements, me = m.elements;
+ return this;
- te[ 12 ] = me[ 12 ];
- te[ 13 ] = me[ 13 ];
- te[ 14 ] = me[ 14 ];
+ }
- return this;
+ addScaledVector( v, s ) {
- },
+ this.x += v.x * s;
+ this.y += v.y * s;
+ this.z += v.z * s;
- extractBasis: function ( xAxis, yAxis, zAxis ) {
+ return this;
- xAxis.setFromMatrixColumn( this, 0 );
- yAxis.setFromMatrixColumn( this, 1 );
- zAxis.setFromMatrixColumn( this, 2 );
+ }
- return this;
+ sub( v ) {
- },
+ this.x -= v.x;
+ this.y -= v.y;
+ this.z -= v.z;
- makeBasis: function ( xAxis, yAxis, zAxis ) {
+ return this;
- this.set(
- xAxis.x, yAxis.x, zAxis.x, 0,
- xAxis.y, yAxis.y, zAxis.y, 0,
- xAxis.z, yAxis.z, zAxis.z, 0,
- 0, 0, 0, 1
- );
+ }
- return this;
+ subScalar( s ) {
- },
+ this.x -= s;
+ this.y -= s;
+ this.z -= s;
- extractRotation: function ( m ) {
+ return this;
- // this method does not support reflection matrices
+ }
- var te = this.elements;
- var me = m.elements;
+ subVectors( a, b ) {
- var scaleX = 1 / _v1.setFromMatrixColumn( m, 0 ).length();
- var scaleY = 1 / _v1.setFromMatrixColumn( m, 1 ).length();
- var scaleZ = 1 / _v1.setFromMatrixColumn( m, 2 ).length();
+ this.x = a.x - b.x;
+ this.y = a.y - b.y;
+ this.z = a.z - b.z;
- te[ 0 ] = me[ 0 ] * scaleX;
- te[ 1 ] = me[ 1 ] * scaleX;
- te[ 2 ] = me[ 2 ] * scaleX;
- te[ 3 ] = 0;
+ return this;
- te[ 4 ] = me[ 4 ] * scaleY;
- te[ 5 ] = me[ 5 ] * scaleY;
- te[ 6 ] = me[ 6 ] * scaleY;
- te[ 7 ] = 0;
+ }
- te[ 8 ] = me[ 8 ] * scaleZ;
- te[ 9 ] = me[ 9 ] * scaleZ;
- te[ 10 ] = me[ 10 ] * scaleZ;
- te[ 11 ] = 0;
+ multiply( v ) {
- te[ 12 ] = 0;
- te[ 13 ] = 0;
- te[ 14 ] = 0;
- te[ 15 ] = 1;
+ this.x *= v.x;
+ this.y *= v.y;
+ this.z *= v.z;
- return this;
+ return this;
- },
+ }
- makeRotationFromEuler: function ( euler ) {
+ multiplyScalar( scalar ) {
- if ( ! ( euler && euler.isEuler ) ) {
+ this.x *= scalar;
+ this.y *= scalar;
+ this.z *= scalar;
- console.error( 'THREE.Matrix4: .makeRotationFromEuler() now expects a Euler rotation rather than a Vector3 and order.' );
+ return this;
- }
+ }
- var te = this.elements;
+ multiplyVectors( a, b ) {
- var x = euler.x, y = euler.y, z = euler.z;
- var a = Math.cos( x ), b = Math.sin( x );
- var c = Math.cos( y ), d = Math.sin( y );
- var e = Math.cos( z ), f = Math.sin( z );
+ this.x = a.x * b.x;
+ this.y = a.y * b.y;
+ this.z = a.z * b.z;
- if ( euler.order === 'XYZ' ) {
+ return this;
- var ae = a * e, af = a * f, be = b * e, bf = b * f;
+ }
- te[ 0 ] = c * e;
- te[ 4 ] = - c * f;
- te[ 8 ] = d;
+ applyEuler( euler ) {
- te[ 1 ] = af + be * d;
- te[ 5 ] = ae - bf * d;
- te[ 9 ] = - b * c;
+ return this.applyQuaternion( _quaternion$4.setFromEuler( euler ) );
- te[ 2 ] = bf - ae * d;
- te[ 6 ] = be + af * d;
- te[ 10 ] = a * c;
+ }
- } else if ( euler.order === 'YXZ' ) {
+ applyAxisAngle( axis, angle ) {
- var ce = c * e, cf = c * f, de = d * e, df = d * f;
+ return this.applyQuaternion( _quaternion$4.setFromAxisAngle( axis, angle ) );
- te[ 0 ] = ce + df * b;
- te[ 4 ] = de * b - cf;
- te[ 8 ] = a * d;
+ }
- te[ 1 ] = a * f;
- te[ 5 ] = a * e;
- te[ 9 ] = - b;
+ applyMatrix3( m ) {
- te[ 2 ] = cf * b - de;
- te[ 6 ] = df + ce * b;
- te[ 10 ] = a * c;
+ const x = this.x, y = this.y, z = this.z;
+ const e = m.elements;
- } else if ( euler.order === 'ZXY' ) {
+ this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ] * z;
+ this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ] * z;
+ this.z = e[ 2 ] * x + e[ 5 ] * y + e[ 8 ] * z;
- var ce = c * e, cf = c * f, de = d * e, df = d * f;
+ return this;
- te[ 0 ] = ce - df * b;
- te[ 4 ] = - a * f;
- te[ 8 ] = de + cf * b;
+ }
- te[ 1 ] = cf + de * b;
- te[ 5 ] = a * e;
- te[ 9 ] = df - ce * b;
+ applyNormalMatrix( m ) {
- te[ 2 ] = - a * d;
- te[ 6 ] = b;
- te[ 10 ] = a * c;
+ return this.applyMatrix3( m ).normalize();
- } else if ( euler.order === 'ZYX' ) {
+ }
- var ae = a * e, af = a * f, be = b * e, bf = b * f;
+ applyMatrix4( m ) {
- te[ 0 ] = c * e;
- te[ 4 ] = be * d - af;
- te[ 8 ] = ae * d + bf;
+ const x = this.x, y = this.y, z = this.z;
+ const e = m.elements;
- te[ 1 ] = c * f;
- te[ 5 ] = bf * d + ae;
- te[ 9 ] = af * d - be;
+ const w = 1 / ( e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] );
- te[ 2 ] = - d;
- te[ 6 ] = b * c;
- te[ 10 ] = a * c;
+ this.x = ( e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] ) * w;
+ this.y = ( e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] ) * w;
+ this.z = ( e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] ) * w;
- } else if ( euler.order === 'YZX' ) {
+ return this;
- var ac = a * c, ad = a * d, bc = b * c, bd = b * d;
+ }
- te[ 0 ] = c * e;
- te[ 4 ] = bd - ac * f;
- te[ 8 ] = bc * f + ad;
+ applyQuaternion( q ) {
- te[ 1 ] = f;
- te[ 5 ] = a * e;
- te[ 9 ] = - b * e;
+ const x = this.x, y = this.y, z = this.z;
+ const qx = q.x, qy = q.y, qz = q.z, qw = q.w;
- te[ 2 ] = - d * e;
- te[ 6 ] = ad * f + bc;
- te[ 10 ] = ac - bd * f;
+ // calculate quat * vector
- } else if ( euler.order === 'XZY' ) {
+ const ix = qw * x + qy * z - qz * y;
+ const iy = qw * y + qz * x - qx * z;
+ const iz = qw * z + qx * y - qy * x;
+ const iw = - qx * x - qy * y - qz * z;
- var ac = a * c, ad = a * d, bc = b * c, bd = b * d;
+ // calculate result * inverse quat
- te[ 0 ] = c * e;
- te[ 4 ] = - f;
- te[ 8 ] = d * e;
+ this.x = ix * qw + iw * - qx + iy * - qz - iz * - qy;
+ this.y = iy * qw + iw * - qy + iz * - qx - ix * - qz;
+ this.z = iz * qw + iw * - qz + ix * - qy - iy * - qx;
- te[ 1 ] = ac * f + bd;
- te[ 5 ] = a * e;
- te[ 9 ] = ad * f - bc;
+ return this;
- te[ 2 ] = bc * f - ad;
- te[ 6 ] = b * e;
- te[ 10 ] = bd * f + ac;
+ }
- }
+ project( camera ) {
- // bottom row
- te[ 3 ] = 0;
- te[ 7 ] = 0;
- te[ 11 ] = 0;
+ return this.applyMatrix4( camera.matrixWorldInverse ).applyMatrix4( camera.projectionMatrix );
- // last column
- te[ 12 ] = 0;
- te[ 13 ] = 0;
- te[ 14 ] = 0;
- te[ 15 ] = 1;
+ }
- return this;
+ unproject( camera ) {
- },
+ return this.applyMatrix4( camera.projectionMatrixInverse ).applyMatrix4( camera.matrixWorld );
- makeRotationFromQuaternion: function ( q ) {
+ }
- return this.compose( _zero, q, _one );
+ transformDirection( m ) {
- },
+ // input: THREE.Matrix4 affine matrix
+ // vector interpreted as a direction
- lookAt: function ( eye, target, up ) {
+ const x = this.x, y = this.y, z = this.z;
+ const e = m.elements;
- var te = this.elements;
+ this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z;
+ this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z;
+ this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z;
- _z.subVectors( eye, target );
+ return this.normalize();
- if ( _z.lengthSq() === 0 ) {
+ }
- // eye and target are in the same position
+ divide( v ) {
- _z.z = 1;
+ this.x /= v.x;
+ this.y /= v.y;
+ this.z /= v.z;
- }
+ return this;
- _z.normalize();
- _x.crossVectors( up, _z );
+ }
- if ( _x.lengthSq() === 0 ) {
+ divideScalar( scalar ) {
- // up and z are parallel
+ return this.multiplyScalar( 1 / scalar );
- if ( Math.abs( up.z ) === 1 ) {
+ }
- _z.x += 0.0001;
+ min( v ) {
- } else {
+ this.x = Math.min( this.x, v.x );
+ this.y = Math.min( this.y, v.y );
+ this.z = Math.min( this.z, v.z );
- _z.z += 0.0001;
+ return this;
- }
+ }
- _z.normalize();
- _x.crossVectors( up, _z );
+ max( v ) {
- }
+ this.x = Math.max( this.x, v.x );
+ this.y = Math.max( this.y, v.y );
+ this.z = Math.max( this.z, v.z );
- _x.normalize();
- _y.crossVectors( _z, _x );
+ return this;
- te[ 0 ] = _x.x; te[ 4 ] = _y.x; te[ 8 ] = _z.x;
- te[ 1 ] = _x.y; te[ 5 ] = _y.y; te[ 9 ] = _z.y;
- te[ 2 ] = _x.z; te[ 6 ] = _y.z; te[ 10 ] = _z.z;
+ }
- return this;
+ clamp( min, max ) {
- },
+ // assumes min < max, componentwise
- multiply: function ( m, n ) {
+ this.x = Math.max( min.x, Math.min( max.x, this.x ) );
+ this.y = Math.max( min.y, Math.min( max.y, this.y ) );
+ this.z = Math.max( min.z, Math.min( max.z, this.z ) );
- if ( n !== undefined ) {
+ return this;
- console.warn( 'THREE.Matrix4: .multiply() now only accepts one argument. Use .multiplyMatrices( a, b ) instead.' );
- return this.multiplyMatrices( m, n );
+ }
- }
+ clampScalar( minVal, maxVal ) {
- return this.multiplyMatrices( this, m );
+ this.x = Math.max( minVal, Math.min( maxVal, this.x ) );
+ this.y = Math.max( minVal, Math.min( maxVal, this.y ) );
+ this.z = Math.max( minVal, Math.min( maxVal, this.z ) );
- },
+ return this;
- premultiply: function ( m ) {
+ }
- return this.multiplyMatrices( m, this );
+ clampLength( min, max ) {
- },
+ const length = this.length();
- multiplyMatrices: function ( a, b ) {
+ return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );
- var ae = a.elements;
- var be = b.elements;
- var te = this.elements;
+ }
- var a11 = ae[ 0 ], a12 = ae[ 4 ], a13 = ae[ 8 ], a14 = ae[ 12 ];
- var a21 = ae[ 1 ], a22 = ae[ 5 ], a23 = ae[ 9 ], a24 = ae[ 13 ];
- var a31 = ae[ 2 ], a32 = ae[ 6 ], a33 = ae[ 10 ], a34 = ae[ 14 ];
- var a41 = ae[ 3 ], a42 = ae[ 7 ], a43 = ae[ 11 ], a44 = ae[ 15 ];
+ floor() {
- var b11 = be[ 0 ], b12 = be[ 4 ], b13 = be[ 8 ], b14 = be[ 12 ];
- var b21 = be[ 1 ], b22 = be[ 5 ], b23 = be[ 9 ], b24 = be[ 13 ];
- var b31 = be[ 2 ], b32 = be[ 6 ], b33 = be[ 10 ], b34 = be[ 14 ];
- var b41 = be[ 3 ], b42 = be[ 7 ], b43 = be[ 11 ], b44 = be[ 15 ];
+ this.x = Math.floor( this.x );
+ this.y = Math.floor( this.y );
+ this.z = Math.floor( this.z );
- te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41;
- te[ 4 ] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42;
- te[ 8 ] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43;
- te[ 12 ] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44;
+ return this;
- te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41;
- te[ 5 ] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42;
- te[ 9 ] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43;
- te[ 13 ] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44;
+ }
- te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41;
- te[ 6 ] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42;
- te[ 10 ] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43;
- te[ 14 ] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44;
+ ceil() {
- te[ 3 ] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41;
- te[ 7 ] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42;
- te[ 11 ] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43;
- te[ 15 ] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44;
+ this.x = Math.ceil( this.x );
+ this.y = Math.ceil( this.y );
+ this.z = Math.ceil( this.z );
- return this;
+ return this;
- },
+ }
- multiplyScalar: function ( s ) {
+ round() {
- var te = this.elements;
+ this.x = Math.round( this.x );
+ this.y = Math.round( this.y );
+ this.z = Math.round( this.z );
- te[ 0 ] *= s; te[ 4 ] *= s; te[ 8 ] *= s; te[ 12 ] *= s;
- te[ 1 ] *= s; te[ 5 ] *= s; te[ 9 ] *= s; te[ 13 ] *= s;
- te[ 2 ] *= s; te[ 6 ] *= s; te[ 10 ] *= s; te[ 14 ] *= s;
- te[ 3 ] *= s; te[ 7 ] *= s; te[ 11 ] *= s; te[ 15 ] *= s;
+ return this;
- return this;
+ }
- },
+ roundToZero() {
- applyToBufferAttribute: function ( attribute ) {
+ this.x = Math.trunc( this.x );
+ this.y = Math.trunc( this.y );
+ this.z = Math.trunc( this.z );
- for ( var i = 0, l = attribute.count; i < l; i ++ ) {
+ return this;
- _v1.x = attribute.getX( i );
- _v1.y = attribute.getY( i );
- _v1.z = attribute.getZ( i );
+ }
- _v1.applyMatrix4( this );
+ negate() {
- attribute.setXYZ( i, _v1.x, _v1.y, _v1.z );
+ this.x = - this.x;
+ this.y = - this.y;
+ this.z = - this.z;
- }
+ return this;
- return attribute;
+ }
- },
+ dot( v ) {
- determinant: function () {
-
- var te = this.elements;
-
- var n11 = te[ 0 ], n12 = te[ 4 ], n13 = te[ 8 ], n14 = te[ 12 ];
- var n21 = te[ 1 ], n22 = te[ 5 ], n23 = te[ 9 ], n24 = te[ 13 ];
- var n31 = te[ 2 ], n32 = te[ 6 ], n33 = te[ 10 ], n34 = te[ 14 ];
- var n41 = te[ 3 ], n42 = te[ 7 ], n43 = te[ 11 ], n44 = te[ 15 ];
-
- //TODO: make this more efficient
- //( based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm )
-
- return (
- n41 * (
- + n14 * n23 * n32
- - n13 * n24 * n32
- - n14 * n22 * n33
- + n12 * n24 * n33
- + n13 * n22 * n34
- - n12 * n23 * n34
- ) +
- n42 * (
- + n11 * n23 * n34
- - n11 * n24 * n33
- + n14 * n21 * n33
- - n13 * n21 * n34
- + n13 * n24 * n31
- - n14 * n23 * n31
- ) +
- n43 * (
- + n11 * n24 * n32
- - n11 * n22 * n34
- - n14 * n21 * n32
- + n12 * n21 * n34
- + n14 * n22 * n31
- - n12 * n24 * n31
- ) +
- n44 * (
- - n13 * n22 * n31
- - n11 * n23 * n32
- + n11 * n22 * n33
- + n13 * n21 * n32
- - n12 * n21 * n33
- + n12 * n23 * n31
- )
+ return this.x * v.x + this.y * v.y + this.z * v.z;
- );
+ }
- },
+ // TODO lengthSquared?
- transpose: function () {
+ lengthSq() {
- var te = this.elements;
- var tmp;
+ return this.x * this.x + this.y * this.y + this.z * this.z;
- tmp = te[ 1 ]; te[ 1 ] = te[ 4 ]; te[ 4 ] = tmp;
- tmp = te[ 2 ]; te[ 2 ] = te[ 8 ]; te[ 8 ] = tmp;
- tmp = te[ 6 ]; te[ 6 ] = te[ 9 ]; te[ 9 ] = tmp;
+ }
- tmp = te[ 3 ]; te[ 3 ] = te[ 12 ]; te[ 12 ] = tmp;
- tmp = te[ 7 ]; te[ 7 ] = te[ 13 ]; te[ 13 ] = tmp;
- tmp = te[ 11 ]; te[ 11 ] = te[ 14 ]; te[ 14 ] = tmp;
+ length() {
- return this;
+ return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z );
- },
+ }
- setPosition: function ( x, y, z ) {
+ manhattanLength() {
- var te = this.elements;
+ return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z );
- if ( x.isVector3 ) {
+ }
- te[ 12 ] = x.x;
- te[ 13 ] = x.y;
- te[ 14 ] = x.z;
+ normalize() {
- } else {
+ return this.divideScalar( this.length() || 1 );
- te[ 12 ] = x;
- te[ 13 ] = y;
- te[ 14 ] = z;
+ }
- }
+ setLength( length ) {
- return this;
+ return this.normalize().multiplyScalar( length );
- },
+ }
- getInverse: function ( m, throwOnDegenerate ) {
+ lerp( v, alpha ) {
- // based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm
- var te = this.elements,
- me = m.elements,
+ this.x += ( v.x - this.x ) * alpha;
+ this.y += ( v.y - this.y ) * alpha;
+ this.z += ( v.z - this.z ) * alpha;
- n11 = me[ 0 ], n21 = me[ 1 ], n31 = me[ 2 ], n41 = me[ 3 ],
- n12 = me[ 4 ], n22 = me[ 5 ], n32 = me[ 6 ], n42 = me[ 7 ],
- n13 = me[ 8 ], n23 = me[ 9 ], n33 = me[ 10 ], n43 = me[ 11 ],
- n14 = me[ 12 ], n24 = me[ 13 ], n34 = me[ 14 ], n44 = me[ 15 ],
+ return this;
- t11 = n23 * n34 * n42 - n24 * n33 * n42 + n24 * n32 * n43 - n22 * n34 * n43 - n23 * n32 * n44 + n22 * n33 * n44,
- t12 = n14 * n33 * n42 - n13 * n34 * n42 - n14 * n32 * n43 + n12 * n34 * n43 + n13 * n32 * n44 - n12 * n33 * n44,
- t13 = n13 * n24 * n42 - n14 * n23 * n42 + n14 * n22 * n43 - n12 * n24 * n43 - n13 * n22 * n44 + n12 * n23 * n44,
- t14 = n14 * n23 * n32 - n13 * n24 * n32 - n14 * n22 * n33 + n12 * n24 * n33 + n13 * n22 * n34 - n12 * n23 * n34;
+ }
- var det = n11 * t11 + n21 * t12 + n31 * t13 + n41 * t14;
+ lerpVectors( v1, v2, alpha ) {
- if ( det === 0 ) {
+ this.x = v1.x + ( v2.x - v1.x ) * alpha;
+ this.y = v1.y + ( v2.y - v1.y ) * alpha;
+ this.z = v1.z + ( v2.z - v1.z ) * alpha;
- var msg = "THREE.Matrix4: .getInverse() can't invert matrix, determinant is 0";
+ return this;
- if ( throwOnDegenerate === true ) {
+ }
- throw new Error( msg );
+ cross( v ) {
- } else {
+ return this.crossVectors( this, v );
- console.warn( msg );
+ }
- }
+ crossVectors( a, b ) {
- return this.identity();
+ const ax = a.x, ay = a.y, az = a.z;
+ const bx = b.x, by = b.y, bz = b.z;
- }
+ this.x = ay * bz - az * by;
+ this.y = az * bx - ax * bz;
+ this.z = ax * by - ay * bx;
- var detInv = 1 / det;
+ return this;
- te[ 0 ] = t11 * detInv;
- te[ 1 ] = ( n24 * n33 * n41 - n23 * n34 * n41 - n24 * n31 * n43 + n21 * n34 * n43 + n23 * n31 * n44 - n21 * n33 * n44 ) * detInv;
- te[ 2 ] = ( n22 * n34 * n41 - n24 * n32 * n41 + n24 * n31 * n42 - n21 * n34 * n42 - n22 * n31 * n44 + n21 * n32 * n44 ) * detInv;
- te[ 3 ] = ( n23 * n32 * n41 - n22 * n33 * n41 - n23 * n31 * n42 + n21 * n33 * n42 + n22 * n31 * n43 - n21 * n32 * n43 ) * detInv;
+ }
- te[ 4 ] = t12 * detInv;
- te[ 5 ] = ( n13 * n34 * n41 - n14 * n33 * n41 + n14 * n31 * n43 - n11 * n34 * n43 - n13 * n31 * n44 + n11 * n33 * n44 ) * detInv;
- te[ 6 ] = ( n14 * n32 * n41 - n12 * n34 * n41 - n14 * n31 * n42 + n11 * n34 * n42 + n12 * n31 * n44 - n11 * n32 * n44 ) * detInv;
- te[ 7 ] = ( n12 * n33 * n41 - n13 * n32 * n41 + n13 * n31 * n42 - n11 * n33 * n42 - n12 * n31 * n43 + n11 * n32 * n43 ) * detInv;
+ projectOnVector( v ) {
- te[ 8 ] = t13 * detInv;
- te[ 9 ] = ( n14 * n23 * n41 - n13 * n24 * n41 - n14 * n21 * n43 + n11 * n24 * n43 + n13 * n21 * n44 - n11 * n23 * n44 ) * detInv;
- te[ 10 ] = ( n12 * n24 * n41 - n14 * n22 * n41 + n14 * n21 * n42 - n11 * n24 * n42 - n12 * n21 * n44 + n11 * n22 * n44 ) * detInv;
- te[ 11 ] = ( n13 * n22 * n41 - n12 * n23 * n41 - n13 * n21 * n42 + n11 * n23 * n42 + n12 * n21 * n43 - n11 * n22 * n43 ) * detInv;
+ const denominator = v.lengthSq();
- te[ 12 ] = t14 * detInv;
- te[ 13 ] = ( n13 * n24 * n31 - n14 * n23 * n31 + n14 * n21 * n33 - n11 * n24 * n33 - n13 * n21 * n34 + n11 * n23 * n34 ) * detInv;
- te[ 14 ] = ( n14 * n22 * n31 - n12 * n24 * n31 - n14 * n21 * n32 + n11 * n24 * n32 + n12 * n21 * n34 - n11 * n22 * n34 ) * detInv;
- te[ 15 ] = ( n12 * n23 * n31 - n13 * n22 * n31 + n13 * n21 * n32 - n11 * n23 * n32 - n12 * n21 * n33 + n11 * n22 * n33 ) * detInv;
+ if ( denominator === 0 ) return this.set( 0, 0, 0 );
- return this;
+ const scalar = v.dot( this ) / denominator;
- },
+ return this.copy( v ).multiplyScalar( scalar );
- scale: function ( v ) {
+ }
- var te = this.elements;
- var x = v.x, y = v.y, z = v.z;
+ projectOnPlane( planeNormal ) {
- te[ 0 ] *= x; te[ 4 ] *= y; te[ 8 ] *= z;
- te[ 1 ] *= x; te[ 5 ] *= y; te[ 9 ] *= z;
- te[ 2 ] *= x; te[ 6 ] *= y; te[ 10 ] *= z;
- te[ 3 ] *= x; te[ 7 ] *= y; te[ 11 ] *= z;
+ _vector$b.copy( this ).projectOnVector( planeNormal );
- return this;
+ return this.sub( _vector$b );
- },
+ }
- getMaxScaleOnAxis: function () {
+ reflect( normal ) {
- var te = this.elements;
+ // reflect incident vector off plane orthogonal to normal
+ // normal is assumed to have unit length
- var scaleXSq = te[ 0 ] * te[ 0 ] + te[ 1 ] * te[ 1 ] + te[ 2 ] * te[ 2 ];
- var scaleYSq = te[ 4 ] * te[ 4 ] + te[ 5 ] * te[ 5 ] + te[ 6 ] * te[ 6 ];
- var scaleZSq = te[ 8 ] * te[ 8 ] + te[ 9 ] * te[ 9 ] + te[ 10 ] * te[ 10 ];
+ return this.sub( _vector$b.copy( normal ).multiplyScalar( 2 * this.dot( normal ) ) );
- return Math.sqrt( Math.max( scaleXSq, scaleYSq, scaleZSq ) );
+ }
- },
+ angleTo( v ) {
- makeTranslation: function ( x, y, z ) {
+ const denominator = Math.sqrt( this.lengthSq() * v.lengthSq() );
- this.set(
+ if ( denominator === 0 ) return Math.PI / 2;
- 1, 0, 0, x,
- 0, 1, 0, y,
- 0, 0, 1, z,
- 0, 0, 0, 1
+ const theta = this.dot( v ) / denominator;
- );
+ // clamp, to handle numerical problems
- return this;
+ return Math.acos( clamp( theta, - 1, 1 ) );
- },
+ }
- makeRotationX: function ( theta ) {
+ distanceTo( v ) {
- var c = Math.cos( theta ), s = Math.sin( theta );
+ return Math.sqrt( this.distanceToSquared( v ) );
- this.set(
+ }
- 1, 0, 0, 0,
- 0, c, - s, 0,
- 0, s, c, 0,
- 0, 0, 0, 1
+ distanceToSquared( v ) {
- );
+ const dx = this.x - v.x, dy = this.y - v.y, dz = this.z - v.z;
- return this;
+ return dx * dx + dy * dy + dz * dz;
- },
+ }
- makeRotationY: function ( theta ) {
+ manhattanDistanceTo( v ) {
- var c = Math.cos( theta ), s = Math.sin( theta );
+ return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y ) + Math.abs( this.z - v.z );
- this.set(
+ }
- c, 0, s, 0,
- 0, 1, 0, 0,
- - s, 0, c, 0,
- 0, 0, 0, 1
+ setFromSpherical( s ) {
- );
+ return this.setFromSphericalCoords( s.radius, s.phi, s.theta );
- return this;
+ }
- },
+ setFromSphericalCoords( radius, phi, theta ) {
- makeRotationZ: function ( theta ) {
+ const sinPhiRadius = Math.sin( phi ) * radius;
- var c = Math.cos( theta ), s = Math.sin( theta );
+ this.x = sinPhiRadius * Math.sin( theta );
+ this.y = Math.cos( phi ) * radius;
+ this.z = sinPhiRadius * Math.cos( theta );
- this.set(
+ return this;
- c, - s, 0, 0,
- s, c, 0, 0,
- 0, 0, 1, 0,
- 0, 0, 0, 1
+ }
- );
+ setFromCylindrical( c ) {
- return this;
+ return this.setFromCylindricalCoords( c.radius, c.theta, c.y );
- },
+ }
- makeRotationAxis: function ( axis, angle ) {
+ setFromCylindricalCoords( radius, theta, y ) {
- // Based on http://www.gamedev.net/reference/articles/article1199.asp
+ this.x = radius * Math.sin( theta );
+ this.y = y;
+ this.z = radius * Math.cos( theta );
- var c = Math.cos( angle );
- var s = Math.sin( angle );
- var t = 1 - c;
- var x = axis.x, y = axis.y, z = axis.z;
- var tx = t * x, ty = t * y;
+ return this;
- this.set(
+ }
- tx * x + c, tx * y - s * z, tx * z + s * y, 0,
- tx * y + s * z, ty * y + c, ty * z - s * x, 0,
- tx * z - s * y, ty * z + s * x, t * z * z + c, 0,
- 0, 0, 0, 1
+ setFromMatrixPosition( m ) {
- );
+ const e = m.elements;
- return this;
+ this.x = e[ 12 ];
+ this.y = e[ 13 ];
+ this.z = e[ 14 ];
- },
+ return this;
- makeScale: function ( x, y, z ) {
+ }
- this.set(
+ setFromMatrixScale( m ) {
- x, 0, 0, 0,
- 0, y, 0, 0,
- 0, 0, z, 0,
- 0, 0, 0, 1
+ const sx = this.setFromMatrixColumn( m, 0 ).length();
+ const sy = this.setFromMatrixColumn( m, 1 ).length();
+ const sz = this.setFromMatrixColumn( m, 2 ).length();
- );
+ this.x = sx;
+ this.y = sy;
+ this.z = sz;
- return this;
+ return this;
- },
+ }
- makeShear: function ( x, y, z ) {
+ setFromMatrixColumn( m, index ) {
- this.set(
+ return this.fromArray( m.elements, index * 4 );
- 1, y, z, 0,
- x, 1, z, 0,
- x, y, 1, 0,
- 0, 0, 0, 1
+ }
- );
+ setFromMatrix3Column( m, index ) {
- return this;
+ return this.fromArray( m.elements, index * 3 );
- },
+ }
- compose: function ( position, quaternion, scale ) {
+ setFromEuler( e ) {
- var te = this.elements;
+ this.x = e._x;
+ this.y = e._y;
+ this.z = e._z;
- var x = quaternion._x, y = quaternion._y, z = quaternion._z, w = quaternion._w;
- var x2 = x + x, y2 = y + y, z2 = z + z;
- var xx = x * x2, xy = x * y2, xz = x * z2;
- var yy = y * y2, yz = y * z2, zz = z * z2;
- var wx = w * x2, wy = w * y2, wz = w * z2;
+ return this;
- var sx = scale.x, sy = scale.y, sz = scale.z;
+ }
- te[ 0 ] = ( 1 - ( yy + zz ) ) * sx;
- te[ 1 ] = ( xy + wz ) * sx;
- te[ 2 ] = ( xz - wy ) * sx;
- te[ 3 ] = 0;
+ setFromColor( c ) {
- te[ 4 ] = ( xy - wz ) * sy;
- te[ 5 ] = ( 1 - ( xx + zz ) ) * sy;
- te[ 6 ] = ( yz + wx ) * sy;
- te[ 7 ] = 0;
+ this.x = c.r;
+ this.y = c.g;
+ this.z = c.b;
- te[ 8 ] = ( xz + wy ) * sz;
- te[ 9 ] = ( yz - wx ) * sz;
- te[ 10 ] = ( 1 - ( xx + yy ) ) * sz;
- te[ 11 ] = 0;
+ return this;
- te[ 12 ] = position.x;
- te[ 13 ] = position.y;
- te[ 14 ] = position.z;
- te[ 15 ] = 1;
+ }
- return this;
+ equals( v ) {
- },
+ return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) );
- decompose: function ( position, quaternion, scale ) {
+ }
- var te = this.elements;
+ fromArray( array, offset = 0 ) {
- var sx = _v1.set( te[ 0 ], te[ 1 ], te[ 2 ] ).length();
- var sy = _v1.set( te[ 4 ], te[ 5 ], te[ 6 ] ).length();
- var sz = _v1.set( te[ 8 ], te[ 9 ], te[ 10 ] ).length();
+ this.x = array[ offset ];
+ this.y = array[ offset + 1 ];
+ this.z = array[ offset + 2 ];
- // if determine is negative, we need to invert one scale
- var det = this.determinant();
- if ( det < 0 ) sx = - sx;
+ return this;
- position.x = te[ 12 ];
- position.y = te[ 13 ];
- position.z = te[ 14 ];
+ }
- // scale the rotation part
- _m1.copy( this );
+ toArray( array = [], offset = 0 ) {
- var invSX = 1 / sx;
- var invSY = 1 / sy;
- var invSZ = 1 / sz;
+ array[ offset ] = this.x;
+ array[ offset + 1 ] = this.y;
+ array[ offset + 2 ] = this.z;
- _m1.elements[ 0 ] *= invSX;
- _m1.elements[ 1 ] *= invSX;
- _m1.elements[ 2 ] *= invSX;
+ return array;
- _m1.elements[ 4 ] *= invSY;
- _m1.elements[ 5 ] *= invSY;
- _m1.elements[ 6 ] *= invSY;
+ }
- _m1.elements[ 8 ] *= invSZ;
- _m1.elements[ 9 ] *= invSZ;
- _m1.elements[ 10 ] *= invSZ;
+ fromBufferAttribute( attribute, index ) {
- quaternion.setFromRotationMatrix( _m1 );
+ this.x = attribute.getX( index );
+ this.y = attribute.getY( index );
+ this.z = attribute.getZ( index );
- scale.x = sx;
- scale.y = sy;
- scale.z = sz;
+ return this;
- return this;
+ }
- },
+ random() {
- makePerspective: function ( left, right, top, bottom, near, far ) {
+ this.x = Math.random();
+ this.y = Math.random();
+ this.z = Math.random();
- if ( far === undefined ) {
+ return this;
- console.warn( 'THREE.Matrix4: .makePerspective() has been redefined and has a new signature. Please check the docs.' );
+ }
- }
+ randomDirection() {
- var te = this.elements;
- var x = 2 * near / ( right - left );
- var y = 2 * near / ( top - bottom );
+ // Derived from https://mathworld.wolfram.com/SpherePointPicking.html
- var a = ( right + left ) / ( right - left );
- var b = ( top + bottom ) / ( top - bottom );
- var c = - ( far + near ) / ( far - near );
- var d = - 2 * far * near / ( far - near );
+ const u = ( Math.random() - 0.5 ) * 2;
+ const t = Math.random() * Math.PI * 2;
+ const f = Math.sqrt( 1 - u ** 2 );
- te[ 0 ] = x; te[ 4 ] = 0; te[ 8 ] = a; te[ 12 ] = 0;
- te[ 1 ] = 0; te[ 5 ] = y; te[ 9 ] = b; te[ 13 ] = 0;
- te[ 2 ] = 0; te[ 6 ] = 0; te[ 10 ] = c; te[ 14 ] = d;
- te[ 3 ] = 0; te[ 7 ] = 0; te[ 11 ] = - 1; te[ 15 ] = 0;
+ this.x = f * Math.cos( t );
+ this.y = f * Math.sin( t );
+ this.z = u;
- return this;
+ return this;
- },
+ }
- makeOrthographic: function ( left, right, top, bottom, near, far ) {
+ *[ Symbol.iterator ]() {
- var te = this.elements;
- var w = 1.0 / ( right - left );
- var h = 1.0 / ( top - bottom );
- var p = 1.0 / ( far - near );
+ yield this.x;
+ yield this.y;
+ yield this.z;
- var x = ( right + left ) * w;
- var y = ( top + bottom ) * h;
- var z = ( far + near ) * p;
+ }
- te[ 0 ] = 2 * w; te[ 4 ] = 0; te[ 8 ] = 0; te[ 12 ] = - x;
- te[ 1 ] = 0; te[ 5 ] = 2 * h; te[ 9 ] = 0; te[ 13 ] = - y;
- te[ 2 ] = 0; te[ 6 ] = 0; te[ 10 ] = - 2 * p; te[ 14 ] = - z;
- te[ 3 ] = 0; te[ 7 ] = 0; te[ 11 ] = 0; te[ 15 ] = 1;
+}
- return this;
+const _vector$b = /*@__PURE__*/ new Vector3();
+const _quaternion$4 = /*@__PURE__*/ new Quaternion();
- },
+class Box3 {
- equals: function ( matrix ) {
+ constructor( min = new Vector3( + Infinity, + Infinity, + Infinity ), max = new Vector3( - Infinity, - Infinity, - Infinity ) ) {
- var te = this.elements;
- var me = matrix.elements;
+ this.isBox3 = true;
- for ( var i = 0; i < 16; i ++ ) {
+ this.min = min;
+ this.max = max;
- if ( te[ i ] !== me[ i ] ) return false;
+ }
- }
+ set( min, max ) {
- return true;
+ this.min.copy( min );
+ this.max.copy( max );
- },
+ return this;
- fromArray: function ( array, offset ) {
+ }
- if ( offset === undefined ) offset = 0;
+ setFromArray( array ) {
- for ( var i = 0; i < 16; i ++ ) {
+ this.makeEmpty();
- this.elements[ i ] = array[ i + offset ];
+ for ( let i = 0, il = array.length; i < il; i += 3 ) {
- }
+ this.expandByPoint( _vector$a.fromArray( array, i ) );
- return this;
+ }
- },
+ return this;
- toArray: function ( array, offset ) {
+ }
- if ( array === undefined ) array = [];
- if ( offset === undefined ) offset = 0;
+ setFromBufferAttribute( attribute ) {
- var te = this.elements;
+ this.makeEmpty();
- array[ offset ] = te[ 0 ];
- array[ offset + 1 ] = te[ 1 ];
- array[ offset + 2 ] = te[ 2 ];
- array[ offset + 3 ] = te[ 3 ];
+ for ( let i = 0, il = attribute.count; i < il; i ++ ) {
- array[ offset + 4 ] = te[ 4 ];
- array[ offset + 5 ] = te[ 5 ];
- array[ offset + 6 ] = te[ 6 ];
- array[ offset + 7 ] = te[ 7 ];
+ this.expandByPoint( _vector$a.fromBufferAttribute( attribute, i ) );
- array[ offset + 8 ] = te[ 8 ];
- array[ offset + 9 ] = te[ 9 ];
- array[ offset + 10 ] = te[ 10 ];
- array[ offset + 11 ] = te[ 11 ];
+ }
- array[ offset + 12 ] = te[ 12 ];
- array[ offset + 13 ] = te[ 13 ];
- array[ offset + 14 ] = te[ 14 ];
- array[ offset + 15 ] = te[ 15 ];
+ return this;
- return array;
+ }
- }
+ setFromPoints( points ) {
- } );
+ this.makeEmpty();
- /**
- * @author mrdoob / http://mrdoob.com/
- * @author WestLangley / http://github.com/WestLangley
- * @author bhouston / http://clara.io
- */
+ for ( let i = 0, il = points.length; i < il; i ++ ) {
- var _matrix = new Matrix4();
- var _quaternion$1 = new Quaternion();
+ this.expandByPoint( points[ i ] );
- function Euler( x, y, z, order ) {
+ }
- this._x = x || 0;
- this._y = y || 0;
- this._z = z || 0;
- this._order = order || Euler.DefaultOrder;
+ return this;
}
- Euler.RotationOrders = [ 'XYZ', 'YZX', 'ZXY', 'XZY', 'YXZ', 'ZYX' ];
+ setFromCenterAndSize( center, size ) {
- Euler.DefaultOrder = 'XYZ';
+ const halfSize = _vector$a.copy( size ).multiplyScalar( 0.5 );
- Object.defineProperties( Euler.prototype, {
+ this.min.copy( center ).sub( halfSize );
+ this.max.copy( center ).add( halfSize );
- x: {
+ return this;
- get: function () {
+ }
- return this._x;
+ setFromObject( object, precise = false ) {
- },
+ this.makeEmpty();
- set: function ( value ) {
+ return this.expandByObject( object, precise );
- this._x = value;
- this._onChangeCallback();
+ }
- }
+ clone() {
- },
+ return new this.constructor().copy( this );
- y: {
+ }
- get: function () {
+ copy( box ) {
- return this._y;
+ this.min.copy( box.min );
+ this.max.copy( box.max );
- },
+ return this;
- set: function ( value ) {
+ }
- this._y = value;
- this._onChangeCallback();
+ makeEmpty() {
- }
+ this.min.x = this.min.y = this.min.z = + Infinity;
+ this.max.x = this.max.y = this.max.z = - Infinity;
- },
+ return this;
- z: {
+ }
- get: function () {
+ isEmpty() {
- return this._z;
+ // this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes
- },
+ return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y ) || ( this.max.z < this.min.z );
- set: function ( value ) {
+ }
- this._z = value;
- this._onChangeCallback();
+ getCenter( target ) {
- }
+ return this.isEmpty() ? target.set( 0, 0, 0 ) : target.addVectors( this.min, this.max ).multiplyScalar( 0.5 );
- },
+ }
- order: {
+ getSize( target ) {
- get: function () {
+ return this.isEmpty() ? target.set( 0, 0, 0 ) : target.subVectors( this.max, this.min );
- return this._order;
+ }
- },
+ expandByPoint( point ) {
- set: function ( value ) {
+ this.min.min( point );
+ this.max.max( point );
- this._order = value;
- this._onChangeCallback();
+ return this;
- }
+ }
- }
+ expandByVector( vector ) {
- } );
+ this.min.sub( vector );
+ this.max.add( vector );
- Object.assign( Euler.prototype, {
+ return this;
- isEuler: true,
+ }
- set: function ( x, y, z, order ) {
+ expandByScalar( scalar ) {
- this._x = x;
- this._y = y;
- this._z = z;
- this._order = order || this._order;
+ this.min.addScalar( - scalar );
+ this.max.addScalar( scalar );
- this._onChangeCallback();
+ return this;
- return this;
+ }
- },
+ expandByObject( object, precise = false ) {
- clone: function () {
+ // Computes the world-axis-aligned bounding box of an object (including its children),
+ // accounting for both the object's, and children's, world transforms
- return new this.constructor( this._x, this._y, this._z, this._order );
+ object.updateWorldMatrix( false, false );
- },
+ if ( object.boundingBox !== undefined ) {
- copy: function ( euler ) {
+ if ( object.boundingBox === null ) {
- this._x = euler._x;
- this._y = euler._y;
- this._z = euler._z;
- this._order = euler._order;
+ object.computeBoundingBox();
- this._onChangeCallback();
+ }
- return this;
+ _box$3.copy( object.boundingBox );
+ _box$3.applyMatrix4( object.matrixWorld );
- },
+ this.union( _box$3 );
+
+ } else {
- setFromRotationMatrix: function ( m, order, update ) {
+ const geometry = object.geometry;
- var clamp = _Math.clamp;
+ if ( geometry !== undefined ) {
- // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
+ if ( precise && geometry.attributes !== undefined && geometry.attributes.position !== undefined ) {
- var te = m.elements;
- var m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ];
- var m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ];
- var m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ];
+ const position = geometry.attributes.position;
+ for ( let i = 0, l = position.count; i < l; i ++ ) {
- order = order || this._order;
+ _vector$a.fromBufferAttribute( position, i ).applyMatrix4( object.matrixWorld );
+ this.expandByPoint( _vector$a );
- if ( order === 'XYZ' ) {
+ }
- this._y = Math.asin( clamp( m13, - 1, 1 ) );
+ } else {
- if ( Math.abs( m13 ) < 0.9999999 ) {
+ if ( geometry.boundingBox === null ) {
- this._x = Math.atan2( - m23, m33 );
- this._z = Math.atan2( - m12, m11 );
+ geometry.computeBoundingBox();
- } else {
+ }
- this._x = Math.atan2( m32, m22 );
- this._z = 0;
+ _box$3.copy( geometry.boundingBox );
+ _box$3.applyMatrix4( object.matrixWorld );
+
+ this.union( _box$3 );
}
- } else if ( order === 'YXZ' ) {
+ }
- this._x = Math.asin( - clamp( m23, - 1, 1 ) );
+ }
- if ( Math.abs( m23 ) < 0.9999999 ) {
+ const children = object.children;
- this._y = Math.atan2( m13, m33 );
- this._z = Math.atan2( m21, m22 );
+ for ( let i = 0, l = children.length; i < l; i ++ ) {
- } else {
+ this.expandByObject( children[ i ], precise );
- this._y = Math.atan2( - m31, m11 );
- this._z = 0;
+ }
- }
+ return this;
- } else if ( order === 'ZXY' ) {
+ }
- this._x = Math.asin( clamp( m32, - 1, 1 ) );
+ containsPoint( point ) {
- if ( Math.abs( m32 ) < 0.9999999 ) {
+ return point.x < this.min.x || point.x > this.max.x ||
+ point.y < this.min.y || point.y > this.max.y ||
+ point.z < this.min.z || point.z > this.max.z ? false : true;
- this._y = Math.atan2( - m31, m33 );
- this._z = Math.atan2( - m12, m22 );
+ }
- } else {
+ containsBox( box ) {
- this._y = 0;
- this._z = Math.atan2( m21, m11 );
+ return this.min.x <= box.min.x && box.max.x <= this.max.x &&
+ this.min.y <= box.min.y && box.max.y <= this.max.y &&
+ this.min.z <= box.min.z && box.max.z <= this.max.z;
- }
+ }
- } else if ( order === 'ZYX' ) {
+ getParameter( point, target ) {
- this._y = Math.asin( - clamp( m31, - 1, 1 ) );
+ // This can potentially have a divide by zero if the box
+ // has a size dimension of 0.
- if ( Math.abs( m31 ) < 0.9999999 ) {
+ return target.set(
+ ( point.x - this.min.x ) / ( this.max.x - this.min.x ),
+ ( point.y - this.min.y ) / ( this.max.y - this.min.y ),
+ ( point.z - this.min.z ) / ( this.max.z - this.min.z )
+ );
- this._x = Math.atan2( m32, m33 );
- this._z = Math.atan2( m21, m11 );
+ }
- } else {
+ intersectsBox( box ) {
- this._x = 0;
- this._z = Math.atan2( - m12, m22 );
+ // using 6 splitting planes to rule out intersections.
+ return box.max.x < this.min.x || box.min.x > this.max.x ||
+ box.max.y < this.min.y || box.min.y > this.max.y ||
+ box.max.z < this.min.z || box.min.z > this.max.z ? false : true;
- }
+ }
- } else if ( order === 'YZX' ) {
+ intersectsSphere( sphere ) {
- this._z = Math.asin( clamp( m21, - 1, 1 ) );
+ // Find the point on the AABB closest to the sphere center.
+ this.clampPoint( sphere.center, _vector$a );
- if ( Math.abs( m21 ) < 0.9999999 ) {
+ // If that point is inside the sphere, the AABB and sphere intersect.
+ return _vector$a.distanceToSquared( sphere.center ) <= ( sphere.radius * sphere.radius );
- this._x = Math.atan2( - m23, m22 );
- this._y = Math.atan2( - m31, m11 );
+ }
- } else {
+ intersectsPlane( plane ) {
- this._x = 0;
- this._y = Math.atan2( m13, m33 );
+ // We compute the minimum and maximum dot product values. If those values
+ // are on the same side (back or front) of the plane, then there is no intersection.
- }
+ let min, max;
- } else if ( order === 'XZY' ) {
+ if ( plane.normal.x > 0 ) {
- this._z = Math.asin( - clamp( m12, - 1, 1 ) );
+ min = plane.normal.x * this.min.x;
+ max = plane.normal.x * this.max.x;
- if ( Math.abs( m12 ) < 0.9999999 ) {
+ } else {
- this._x = Math.atan2( m32, m22 );
- this._y = Math.atan2( m13, m11 );
+ min = plane.normal.x * this.max.x;
+ max = plane.normal.x * this.min.x;
- } else {
+ }
- this._x = Math.atan2( - m23, m33 );
- this._y = 0;
+ if ( plane.normal.y > 0 ) {
- }
+ min += plane.normal.y * this.min.y;
+ max += plane.normal.y * this.max.y;
- } else {
+ } else {
- console.warn( 'THREE.Euler: .setFromRotationMatrix() given unsupported order: ' + order );
+ min += plane.normal.y * this.max.y;
+ max += plane.normal.y * this.min.y;
- }
+ }
- this._order = order;
+ if ( plane.normal.z > 0 ) {
- if ( update !== false ) this._onChangeCallback();
+ min += plane.normal.z * this.min.z;
+ max += plane.normal.z * this.max.z;
- return this;
+ } else {
- },
+ min += plane.normal.z * this.max.z;
+ max += plane.normal.z * this.min.z;
- setFromQuaternion: function ( q, order, update ) {
+ }
- _matrix.makeRotationFromQuaternion( q );
+ return ( min <= - plane.constant && max >= - plane.constant );
- return this.setFromRotationMatrix( _matrix, order, update );
+ }
- },
+ intersectsTriangle( triangle ) {
- setFromVector3: function ( v, order ) {
+ if ( this.isEmpty() ) {
- return this.set( v.x, v.y, v.z, order || this._order );
+ return false;
- },
+ }
+
+ // compute box center and extents
+ this.getCenter( _center );
+ _extents.subVectors( this.max, _center );
- reorder: function ( newOrder ) {
+ // translate triangle to aabb origin
+ _v0$2.subVectors( triangle.a, _center );
+ _v1$7.subVectors( triangle.b, _center );
+ _v2$4.subVectors( triangle.c, _center );
- // WARNING: this discards revolution information -bhouston
+ // compute edge vectors for triangle
+ _f0.subVectors( _v1$7, _v0$2 );
+ _f1.subVectors( _v2$4, _v1$7 );
+ _f2.subVectors( _v0$2, _v2$4 );
- _quaternion$1.setFromEuler( this );
+ // test against axes that are given by cross product combinations of the edges of the triangle and the edges of the aabb
+ // make an axis testing of each of the 3 sides of the aabb against each of the 3 sides of the triangle = 9 axis of separation
+ // axis_ij = u_i x f_j (u0, u1, u2 = face normals of aabb = x,y,z axes vectors since aabb is axis aligned)
+ let axes = [
+ 0, - _f0.z, _f0.y, 0, - _f1.z, _f1.y, 0, - _f2.z, _f2.y,
+ _f0.z, 0, - _f0.x, _f1.z, 0, - _f1.x, _f2.z, 0, - _f2.x,
+ - _f0.y, _f0.x, 0, - _f1.y, _f1.x, 0, - _f2.y, _f2.x, 0
+ ];
+ if ( ! satForAxes( axes, _v0$2, _v1$7, _v2$4, _extents ) ) {
- return this.setFromQuaternion( _quaternion$1, newOrder );
+ return false;
- },
+ }
- equals: function ( euler ) {
+ // test 3 face normals from the aabb
+ axes = [ 1, 0, 0, 0, 1, 0, 0, 0, 1 ];
+ if ( ! satForAxes( axes, _v0$2, _v1$7, _v2$4, _extents ) ) {
- return ( euler._x === this._x ) && ( euler._y === this._y ) && ( euler._z === this._z ) && ( euler._order === this._order );
+ return false;
- },
+ }
- fromArray: function ( array ) {
+ // finally testing the face normal of the triangle
+ // use already existing triangle edge vectors here
+ _triangleNormal.crossVectors( _f0, _f1 );
+ axes = [ _triangleNormal.x, _triangleNormal.y, _triangleNormal.z ];
- this._x = array[ 0 ];
- this._y = array[ 1 ];
- this._z = array[ 2 ];
- if ( array[ 3 ] !== undefined ) this._order = array[ 3 ];
+ return satForAxes( axes, _v0$2, _v1$7, _v2$4, _extents );
- this._onChangeCallback();
+ }
- return this;
+ clampPoint( point, target ) {
- },
+ return target.copy( point ).clamp( this.min, this.max );
- toArray: function ( array, offset ) {
+ }
- if ( array === undefined ) array = [];
- if ( offset === undefined ) offset = 0;
+ distanceToPoint( point ) {
- array[ offset ] = this._x;
- array[ offset + 1 ] = this._y;
- array[ offset + 2 ] = this._z;
- array[ offset + 3 ] = this._order;
+ return this.clampPoint( point, _vector$a ).distanceTo( point );
- return array;
+ }
- },
+ getBoundingSphere( target ) {
- toVector3: function ( optionalResult ) {
+ if ( this.isEmpty() ) {
- if ( optionalResult ) {
+ target.makeEmpty();
- return optionalResult.set( this._x, this._y, this._z );
+ } else {
- } else {
+ this.getCenter( target.center );
- return new Vector3( this._x, this._y, this._z );
+ target.radius = this.getSize( _vector$a ).length() * 0.5;
- }
+ }
- },
+ return target;
- _onChange: function ( callback ) {
+ }
- this._onChangeCallback = callback;
+ intersect( box ) {
- return this;
+ this.min.max( box.min );
+ this.max.min( box.max );
- },
+ // ensure that if there is no overlap, the result is fully empty, not slightly empty with non-inf/+inf values that will cause subsequence intersects to erroneously return valid values.
+ if ( this.isEmpty() ) this.makeEmpty();
- _onChangeCallback: function () {}
+ return this;
- } );
+ }
- /**
- * @author mrdoob / http://mrdoob.com/
- */
+ union( box ) {
- function Layers() {
+ this.min.min( box.min );
+ this.max.max( box.max );
- this.mask = 1 | 0;
+ return this;
}
- Object.assign( Layers.prototype, {
+ applyMatrix4( matrix ) {
- set: function ( channel ) {
+ // transform of empty box is an empty box.
+ if ( this.isEmpty() ) return this;
- this.mask = 1 << channel | 0;
+ // NOTE: I am using a binary pattern to specify all 2^3 combinations below
+ _points[ 0 ].set( this.min.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 000
+ _points[ 1 ].set( this.min.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 001
+ _points[ 2 ].set( this.min.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 010
+ _points[ 3 ].set( this.min.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 011
+ _points[ 4 ].set( this.max.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 100
+ _points[ 5 ].set( this.max.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 101
+ _points[ 6 ].set( this.max.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 110
+ _points[ 7 ].set( this.max.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 111
- },
+ this.setFromPoints( _points );
- enable: function ( channel ) {
+ return this;
- this.mask |= 1 << channel | 0;
+ }
- },
+ translate( offset ) {
- enableAll: function () {
+ this.min.add( offset );
+ this.max.add( offset );
- this.mask = 0xffffffff | 0;
+ return this;
- },
+ }
- toggle: function ( channel ) {
+ equals( box ) {
- this.mask ^= 1 << channel | 0;
+ return box.min.equals( this.min ) && box.max.equals( this.max );
- },
+ }
- disable: function ( channel ) {
+}
- this.mask &= ~ ( 1 << channel | 0 );
+const _points = [
+ /*@__PURE__*/ new Vector3(),
+ /*@__PURE__*/ new Vector3(),
+ /*@__PURE__*/ new Vector3(),
+ /*@__PURE__*/ new Vector3(),
+ /*@__PURE__*/ new Vector3(),
+ /*@__PURE__*/ new Vector3(),
+ /*@__PURE__*/ new Vector3(),
+ /*@__PURE__*/ new Vector3()
+];
- },
+const _vector$a = /*@__PURE__*/ new Vector3();
- disableAll: function () {
+const _box$3 = /*@__PURE__*/ new Box3();
- this.mask = 0;
+// triangle centered vertices
- },
+const _v0$2 = /*@__PURE__*/ new Vector3();
+const _v1$7 = /*@__PURE__*/ new Vector3();
+const _v2$4 = /*@__PURE__*/ new Vector3();
- test: function ( layers ) {
+// triangle edge vectors
- return ( this.mask & layers.mask ) !== 0;
+const _f0 = /*@__PURE__*/ new Vector3();
+const _f1 = /*@__PURE__*/ new Vector3();
+const _f2 = /*@__PURE__*/ new Vector3();
- }
+const _center = /*@__PURE__*/ new Vector3();
+const _extents = /*@__PURE__*/ new Vector3();
+const _triangleNormal = /*@__PURE__*/ new Vector3();
+const _testAxis = /*@__PURE__*/ new Vector3();
- } );
+function satForAxes( axes, v0, v1, v2, extents ) {
- var _object3DId = 0;
+ for ( let i = 0, j = axes.length - 3; i <= j; i += 3 ) {
- var _v1$1 = new Vector3();
- var _q1 = new Quaternion();
- var _m1$1 = new Matrix4();
- var _target = new Vector3();
+ _testAxis.fromArray( axes, i );
+ // project the aabb onto the separating axis
+ const r = extents.x * Math.abs( _testAxis.x ) + extents.y * Math.abs( _testAxis.y ) + extents.z * Math.abs( _testAxis.z );
+ // project all 3 vertices of the triangle onto the separating axis
+ const p0 = v0.dot( _testAxis );
+ const p1 = v1.dot( _testAxis );
+ const p2 = v2.dot( _testAxis );
+ // actual test, basically see if either of the most extreme of the triangle points intersects r
+ if ( Math.max( - Math.max( p0, p1, p2 ), Math.min( p0, p1, p2 ) ) > r ) {
- var _position = new Vector3();
- var _scale = new Vector3();
- var _quaternion$2 = new Quaternion();
+ // points of the projected triangle are outside the projected half-length of the aabb
+ // the axis is separating and we can exit
+ return false;
- var _xAxis = new Vector3( 1, 0, 0 );
- var _yAxis = new Vector3( 0, 1, 0 );
- var _zAxis = new Vector3( 0, 0, 1 );
+ }
- var _addedEvent = { type: 'added' };
- var _removedEvent = { type: 'removed' };
+ }
- /**
- * @author mrdoob / http://mrdoob.com/
- * @author mikael emtinger / http://gomo.se/
- * @author alteredq / http://alteredqualia.com/
- * @author WestLangley / http://github.com/WestLangley
- * @author elephantatwork / www.elephantatwork.ch
- */
+ return true;
- function Object3D() {
+}
- Object.defineProperty( this, 'id', { value: _object3DId ++ } );
+const _box$2 = /*@__PURE__*/ new Box3();
+const _v1$6 = /*@__PURE__*/ new Vector3();
+const _v2$3 = /*@__PURE__*/ new Vector3();
- this.uuid = _Math.generateUUID();
+class Sphere {
- this.name = '';
- this.type = 'Object3D';
+ constructor( center = new Vector3(), radius = - 1 ) {
- this.parent = null;
- this.children = [];
+ this.center = center;
+ this.radius = radius;
- this.up = Object3D.DefaultUp.clone();
+ }
- var position = new Vector3();
- var rotation = new Euler();
- var quaternion = new Quaternion();
- var scale = new Vector3( 1, 1, 1 );
+ set( center, radius ) {
- function onRotationChange() {
+ this.center.copy( center );
+ this.radius = radius;
- quaternion.setFromEuler( rotation, false );
+ return this;
- }
+ }
- function onQuaternionChange() {
+ setFromPoints( points, optionalCenter ) {
- rotation.setFromQuaternion( quaternion, undefined, false );
+ const center = this.center;
- }
+ if ( optionalCenter !== undefined ) {
- rotation._onChange( onRotationChange );
- quaternion._onChange( onQuaternionChange );
+ center.copy( optionalCenter );
- Object.defineProperties( this, {
- position: {
- configurable: true,
- enumerable: true,
- value: position
- },
- rotation: {
- configurable: true,
- enumerable: true,
- value: rotation
- },
- quaternion: {
- configurable: true,
- enumerable: true,
- value: quaternion
- },
- scale: {
- configurable: true,
- enumerable: true,
- value: scale
- },
- modelViewMatrix: {
- value: new Matrix4()
- },
- normalMatrix: {
- value: new Matrix3()
- }
- } );
+ } else {
- this.matrix = new Matrix4();
- this.matrixWorld = new Matrix4();
+ _box$2.setFromPoints( points ).getCenter( center );
- this.matrixAutoUpdate = Object3D.DefaultMatrixAutoUpdate;
- this.matrixWorldNeedsUpdate = false;
+ }
- this.layers = new Layers();
- this.visible = true;
+ let maxRadiusSq = 0;
- this.castShadow = false;
- this.receiveShadow = false;
+ for ( let i = 0, il = points.length; i < il; i ++ ) {
- this.frustumCulled = true;
- this.renderOrder = 0;
+ maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( points[ i ] ) );
- this.userData = {};
+ }
+
+ this.radius = Math.sqrt( maxRadiusSq );
+
+ return this;
}
- Object3D.DefaultUp = new Vector3( 0, 1, 0 );
- Object3D.DefaultMatrixAutoUpdate = true;
+ copy( sphere ) {
- Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
+ this.center.copy( sphere.center );
+ this.radius = sphere.radius;
- constructor: Object3D,
+ return this;
- isObject3D: true,
+ }
- onBeforeRender: function () {},
- onAfterRender: function () {},
+ isEmpty() {
- applyMatrix: function ( matrix ) {
+ return ( this.radius < 0 );
- if ( this.matrixAutoUpdate ) this.updateMatrix();
+ }
- this.matrix.premultiply( matrix );
+ makeEmpty() {
- this.matrix.decompose( this.position, this.quaternion, this.scale );
+ this.center.set( 0, 0, 0 );
+ this.radius = - 1;
- },
+ return this;
- applyQuaternion: function ( q ) {
+ }
- this.quaternion.premultiply( q );
+ containsPoint( point ) {
- return this;
+ return ( point.distanceToSquared( this.center ) <= ( this.radius * this.radius ) );
- },
+ }
- setRotationFromAxisAngle: function ( axis, angle ) {
+ distanceToPoint( point ) {
- // assumes axis is normalized
+ return ( point.distanceTo( this.center ) - this.radius );
- this.quaternion.setFromAxisAngle( axis, angle );
+ }
- },
+ intersectsSphere( sphere ) {
- setRotationFromEuler: function ( euler ) {
+ const radiusSum = this.radius + sphere.radius;
- this.quaternion.setFromEuler( euler, true );
+ return sphere.center.distanceToSquared( this.center ) <= ( radiusSum * radiusSum );
- },
+ }
- setRotationFromMatrix: function ( m ) {
+ intersectsBox( box ) {
- // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
+ return box.intersectsSphere( this );
- this.quaternion.setFromRotationMatrix( m );
+ }
- },
+ intersectsPlane( plane ) {
- setRotationFromQuaternion: function ( q ) {
+ return Math.abs( plane.distanceToPoint( this.center ) ) <= this.radius;
- // assumes q is normalized
+ }
- this.quaternion.copy( q );
+ clampPoint( point, target ) {
- },
+ const deltaLengthSq = this.center.distanceToSquared( point );
- rotateOnAxis: function ( axis, angle ) {
+ target.copy( point );
- // rotate object on axis in object space
- // axis is assumed to be normalized
+ if ( deltaLengthSq > ( this.radius * this.radius ) ) {
- _q1.setFromAxisAngle( axis, angle );
+ target.sub( this.center ).normalize();
+ target.multiplyScalar( this.radius ).add( this.center );
- this.quaternion.multiply( _q1 );
+ }
- return this;
+ return target;
- },
+ }
- rotateOnWorldAxis: function ( axis, angle ) {
+ getBoundingBox( target ) {
- // rotate object on axis in world space
- // axis is assumed to be normalized
- // method assumes no rotated parent
+ if ( this.isEmpty() ) {
- _q1.setFromAxisAngle( axis, angle );
+ // Empty sphere produces empty bounding box
+ target.makeEmpty();
+ return target;
- this.quaternion.premultiply( _q1 );
+ }
- return this;
+ target.set( this.center, this.center );
+ target.expandByScalar( this.radius );
- },
+ return target;
- rotateX: function ( angle ) {
+ }
- return this.rotateOnAxis( _xAxis, angle );
+ applyMatrix4( matrix ) {
- },
+ this.center.applyMatrix4( matrix );
+ this.radius = this.radius * matrix.getMaxScaleOnAxis();
- rotateY: function ( angle ) {
+ return this;
- return this.rotateOnAxis( _yAxis, angle );
+ }
- },
+ translate( offset ) {
- rotateZ: function ( angle ) {
+ this.center.add( offset );
- return this.rotateOnAxis( _zAxis, angle );
+ return this;
- },
+ }
- translateOnAxis: function ( axis, distance ) {
+ expandByPoint( point ) {
- // translate object by distance along axis in object space
- // axis is assumed to be normalized
+ if ( this.isEmpty() ) {
- _v1$1.copy( axis ).applyQuaternion( this.quaternion );
+ this.center.copy( point );
- this.position.add( _v1$1.multiplyScalar( distance ) );
+ this.radius = 0;
return this;
- },
+ }
- translateX: function ( distance ) {
+ _v1$6.subVectors( point, this.center );
- return this.translateOnAxis( _xAxis, distance );
+ const lengthSq = _v1$6.lengthSq();
- },
+ if ( lengthSq > ( this.radius * this.radius ) ) {
- translateY: function ( distance ) {
+ // calculate the minimal sphere
- return this.translateOnAxis( _yAxis, distance );
+ const length = Math.sqrt( lengthSq );
- },
+ const delta = ( length - this.radius ) * 0.5;
- translateZ: function ( distance ) {
+ this.center.addScaledVector( _v1$6, delta / length );
- return this.translateOnAxis( _zAxis, distance );
+ this.radius += delta;
- },
+ }
- localToWorld: function ( vector ) {
+ return this;
- return vector.applyMatrix4( this.matrixWorld );
+ }
- },
+ union( sphere ) {
- worldToLocal: function ( vector ) {
+ if ( sphere.isEmpty() ) {
- return vector.applyMatrix4( _m1$1.getInverse( this.matrixWorld ) );
+ return this;
- },
+ }
- lookAt: function ( x, y, z ) {
+ if ( this.isEmpty() ) {
- // This method does not support objects having non-uniformly-scaled parent(s)
+ this.copy( sphere );
- if ( x.isVector3 ) {
+ return this;
- _target.copy( x );
+ }
- } else {
+ if ( this.center.equals( sphere.center ) === true ) {
- _target.set( x, y, z );
+ this.radius = Math.max( this.radius, sphere.radius );
- }
+ } else {
- var parent = this.parent;
+ _v2$3.subVectors( sphere.center, this.center ).setLength( sphere.radius );
- this.updateWorldMatrix( true, false );
+ this.expandByPoint( _v1$6.copy( sphere.center ).add( _v2$3 ) );
- _position.setFromMatrixPosition( this.matrixWorld );
+ this.expandByPoint( _v1$6.copy( sphere.center ).sub( _v2$3 ) );
- if ( this.isCamera || this.isLight ) {
+ }
- _m1$1.lookAt( _position, _target, this.up );
+ return this;
- } else {
+ }
- _m1$1.lookAt( _target, _position, this.up );
+ equals( sphere ) {
- }
+ return sphere.center.equals( this.center ) && ( sphere.radius === this.radius );
- this.quaternion.setFromRotationMatrix( _m1$1 );
+ }
- if ( parent ) {
+ clone() {
- _m1$1.extractRotation( parent.matrixWorld );
- _q1.setFromRotationMatrix( _m1$1 );
- this.quaternion.premultiply( _q1.inverse() );
+ return new this.constructor().copy( this );
- }
+ }
- },
+}
- add: function ( object ) {
+const _vector$9 = /*@__PURE__*/ new Vector3();
+const _segCenter = /*@__PURE__*/ new Vector3();
+const _segDir = /*@__PURE__*/ new Vector3();
+const _diff = /*@__PURE__*/ new Vector3();
- if ( arguments.length > 1 ) {
+const _edge1 = /*@__PURE__*/ new Vector3();
+const _edge2 = /*@__PURE__*/ new Vector3();
+const _normal$1 = /*@__PURE__*/ new Vector3();
- for ( var i = 0; i < arguments.length; i ++ ) {
+class Ray {
- this.add( arguments[ i ] );
+ constructor( origin = new Vector3(), direction = new Vector3( 0, 0, - 1 ) ) {
- }
+ this.origin = origin;
+ this.direction = direction;
- return this;
+ }
- }
+ set( origin, direction ) {
- if ( object === this ) {
+ this.origin.copy( origin );
+ this.direction.copy( direction );
- console.error( "THREE.Object3D.add: object can't be added as a child of itself.", object );
- return this;
+ return this;
- }
+ }
- if ( ( object && object.isObject3D ) ) {
+ copy( ray ) {
- if ( object.parent !== null ) {
+ this.origin.copy( ray.origin );
+ this.direction.copy( ray.direction );
- object.parent.remove( object );
+ return this;
- }
+ }
- object.parent = this;
- this.children.push( object );
+ at( t, target ) {
- object.dispatchEvent( _addedEvent );
+ return target.copy( this.origin ).addScaledVector( this.direction, t );
- } else {
+ }
- console.error( "THREE.Object3D.add: object not an instance of THREE.Object3D.", object );
+ lookAt( v ) {
- }
+ this.direction.copy( v ).sub( this.origin ).normalize();
- return this;
+ return this;
- },
+ }
- remove: function ( object ) {
+ recast( t ) {
- if ( arguments.length > 1 ) {
+ this.origin.copy( this.at( t, _vector$9 ) );
- for ( var i = 0; i < arguments.length; i ++ ) {
+ return this;
- this.remove( arguments[ i ] );
+ }
- }
+ closestPointToPoint( point, target ) {
- return this;
+ target.subVectors( point, this.origin );
- }
+ const directionDistance = target.dot( this.direction );
- var index = this.children.indexOf( object );
+ if ( directionDistance < 0 ) {
- if ( index !== - 1 ) {
+ return target.copy( this.origin );
- object.parent = null;
- this.children.splice( index, 1 );
+ }
- object.dispatchEvent( _removedEvent );
+ return target.copy( this.origin ).addScaledVector( this.direction, directionDistance );
- }
+ }
- return this;
+ distanceToPoint( point ) {
- },
+ return Math.sqrt( this.distanceSqToPoint( point ) );
- attach: function ( object ) {
+ }
- // adds object as a child of this, while maintaining the object's world transform
+ distanceSqToPoint( point ) {
- this.updateWorldMatrix( true, false );
+ const directionDistance = _vector$9.subVectors( point, this.origin ).dot( this.direction );
- _m1$1.getInverse( this.matrixWorld );
+ // point behind the ray
- if ( object.parent !== null ) {
+ if ( directionDistance < 0 ) {
- object.parent.updateWorldMatrix( true, false );
+ return this.origin.distanceToSquared( point );
- _m1$1.multiply( object.parent.matrixWorld );
+ }
- }
+ _vector$9.copy( this.origin ).addScaledVector( this.direction, directionDistance );
- object.applyMatrix( _m1$1 );
+ return _vector$9.distanceToSquared( point );
- object.updateWorldMatrix( false, false );
+ }
- this.add( object );
+ distanceSqToSegment( v0, v1, optionalPointOnRay, optionalPointOnSegment ) {
- return this;
+ // from https://github.com/pmjoniak/GeometricTools/blob/master/GTEngine/Include/Mathematics/GteDistRaySegment.h
+ // It returns the min distance between the ray and the segment
+ // defined by v0 and v1
+ // It can also set two optional targets :
+ // - The closest point on the ray
+ // - The closest point on the segment
- },
+ _segCenter.copy( v0 ).add( v1 ).multiplyScalar( 0.5 );
+ _segDir.copy( v1 ).sub( v0 ).normalize();
+ _diff.copy( this.origin ).sub( _segCenter );
- getObjectById: function ( id ) {
+ const segExtent = v0.distanceTo( v1 ) * 0.5;
+ const a01 = - this.direction.dot( _segDir );
+ const b0 = _diff.dot( this.direction );
+ const b1 = - _diff.dot( _segDir );
+ const c = _diff.lengthSq();
+ const det = Math.abs( 1 - a01 * a01 );
+ let s0, s1, sqrDist, extDet;
- return this.getObjectByProperty( 'id', id );
+ if ( det > 0 ) {
- },
+ // The ray and segment are not parallel.
- getObjectByName: function ( name ) {
+ s0 = a01 * b1 - b0;
+ s1 = a01 * b0 - b1;
+ extDet = segExtent * det;
- return this.getObjectByProperty( 'name', name );
+ if ( s0 >= 0 ) {
- },
+ if ( s1 >= - extDet ) {
- getObjectByProperty: function ( name, value ) {
+ if ( s1 <= extDet ) {
- if ( this[ name ] === value ) return this;
+ // region 0
+ // Minimum at interior points of ray and segment.
- for ( var i = 0, l = this.children.length; i < l; i ++ ) {
+ const invDet = 1 / det;
+ s0 *= invDet;
+ s1 *= invDet;
+ sqrDist = s0 * ( s0 + a01 * s1 + 2 * b0 ) + s1 * ( a01 * s0 + s1 + 2 * b1 ) + c;
- var child = this.children[ i ];
- var object = child.getObjectByProperty( name, value );
+ } else {
- if ( object !== undefined ) {
+ // region 1
- return object;
+ s1 = segExtent;
+ s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
+ sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
- }
+ }
- }
+ } else {
- return undefined;
+ // region 5
- },
+ s1 = - segExtent;
+ s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
+ sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
- getWorldPosition: function ( target ) {
+ }
- if ( target === undefined ) {
+ } else {
- console.warn( 'THREE.Object3D: .getWorldPosition() target is now required' );
- target = new Vector3();
+ if ( s1 <= - extDet ) {
- }
+ // region 4
- this.updateMatrixWorld( true );
+ s0 = Math.max( 0, - ( - a01 * segExtent + b0 ) );
+ s1 = ( s0 > 0 ) ? - segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );
+ sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
- return target.setFromMatrixPosition( this.matrixWorld );
+ } else if ( s1 <= extDet ) {
- },
+ // region 3
- getWorldQuaternion: function ( target ) {
+ s0 = 0;
+ s1 = Math.min( Math.max( - segExtent, - b1 ), segExtent );
+ sqrDist = s1 * ( s1 + 2 * b1 ) + c;
- if ( target === undefined ) {
+ } else {
- console.warn( 'THREE.Object3D: .getWorldQuaternion() target is now required' );
- target = new Quaternion();
+ // region 2
- }
+ s0 = Math.max( 0, - ( a01 * segExtent + b0 ) );
+ s1 = ( s0 > 0 ) ? segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );
+ sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
- this.updateMatrixWorld( true );
+ }
- this.matrixWorld.decompose( _position, target, _scale );
+ }
- return target;
+ } else {
- },
+ // Ray and segment are parallel.
- getWorldScale: function ( target ) {
+ s1 = ( a01 > 0 ) ? - segExtent : segExtent;
+ s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
+ sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
- if ( target === undefined ) {
-
- console.warn( 'THREE.Object3D: .getWorldScale() target is now required' );
- target = new Vector3();
-
- }
+ }
- this.updateMatrixWorld( true );
+ if ( optionalPointOnRay ) {
- this.matrixWorld.decompose( _position, _quaternion$2, target );
+ optionalPointOnRay.copy( this.origin ).addScaledVector( this.direction, s0 );
- return target;
+ }
- },
+ if ( optionalPointOnSegment ) {
- getWorldDirection: function ( target ) {
+ optionalPointOnSegment.copy( _segCenter ).addScaledVector( _segDir, s1 );
- if ( target === undefined ) {
+ }
- console.warn( 'THREE.Object3D: .getWorldDirection() target is now required' );
- target = new Vector3();
+ return sqrDist;
- }
+ }
- this.updateMatrixWorld( true );
+ intersectSphere( sphere, target ) {
- var e = this.matrixWorld.elements;
+ _vector$9.subVectors( sphere.center, this.origin );
+ const tca = _vector$9.dot( this.direction );
+ const d2 = _vector$9.dot( _vector$9 ) - tca * tca;
+ const radius2 = sphere.radius * sphere.radius;
- return target.set( e[ 8 ], e[ 9 ], e[ 10 ] ).normalize();
+ if ( d2 > radius2 ) return null;
- },
+ const thc = Math.sqrt( radius2 - d2 );
- raycast: function () {},
+ // t0 = first intersect point - entrance on front of sphere
+ const t0 = tca - thc;
- traverse: function ( callback ) {
+ // t1 = second intersect point - exit point on back of sphere
+ const t1 = tca + thc;
- callback( this );
+ // test to see if t1 is behind the ray - if so, return null
+ if ( t1 < 0 ) return null;
- var children = this.children;
+ // test to see if t0 is behind the ray:
+ // if it is, the ray is inside the sphere, so return the second exit point scaled by t1,
+ // in order to always return an intersect point that is in front of the ray.
+ if ( t0 < 0 ) return this.at( t1, target );
- for ( var i = 0, l = children.length; i < l; i ++ ) {
+ // else t0 is in front of the ray, so return the first collision point scaled by t0
+ return this.at( t0, target );
- children[ i ].traverse( callback );
+ }
- }
+ intersectsSphere( sphere ) {
- },
+ return this.distanceSqToPoint( sphere.center ) <= ( sphere.radius * sphere.radius );
- traverseVisible: function ( callback ) {
+ }
- if ( this.visible === false ) return;
+ distanceToPlane( plane ) {
- callback( this );
+ const denominator = plane.normal.dot( this.direction );
- var children = this.children;
+ if ( denominator === 0 ) {
- for ( var i = 0, l = children.length; i < l; i ++ ) {
+ // line is coplanar, return origin
+ if ( plane.distanceToPoint( this.origin ) === 0 ) {
- children[ i ].traverseVisible( callback );
+ return 0;
}
- },
+ // Null is preferable to undefined since undefined means.... it is undefined
- traverseAncestors: function ( callback ) {
+ return null;
- var parent = this.parent;
+ }
- if ( parent !== null ) {
+ const t = - ( this.origin.dot( plane.normal ) + plane.constant ) / denominator;
- callback( parent );
+ // Return if the ray never intersects the plane
- parent.traverseAncestors( callback );
+ return t >= 0 ? t : null;
- }
+ }
- },
+ intersectPlane( plane, target ) {
- updateMatrix: function () {
+ const t = this.distanceToPlane( plane );
- this.matrix.compose( this.position, this.quaternion, this.scale );
+ if ( t === null ) {
- this.matrixWorldNeedsUpdate = true;
+ return null;
- },
+ }
- updateMatrixWorld: function ( force ) {
+ return this.at( t, target );
- if ( this.matrixAutoUpdate ) this.updateMatrix();
+ }
- if ( this.matrixWorldNeedsUpdate || force ) {
+ intersectsPlane( plane ) {
- if ( this.parent === null ) {
+ // check if the ray lies on the plane first
- this.matrixWorld.copy( this.matrix );
+ const distToPoint = plane.distanceToPoint( this.origin );
- } else {
+ if ( distToPoint === 0 ) {
- this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );
+ return true;
- }
+ }
- this.matrixWorldNeedsUpdate = false;
+ const denominator = plane.normal.dot( this.direction );
- force = true;
+ if ( denominator * distToPoint < 0 ) {
- }
+ return true;
- // update children
+ }
- var children = this.children;
+ // ray origin is behind the plane (and is pointing behind it)
- for ( var i = 0, l = children.length; i < l; i ++ ) {
+ return false;
- children[ i ].updateMatrixWorld( force );
+ }
- }
+ intersectBox( box, target ) {
- },
+ let tmin, tmax, tymin, tymax, tzmin, tzmax;
- updateWorldMatrix: function ( updateParents, updateChildren ) {
+ const invdirx = 1 / this.direction.x,
+ invdiry = 1 / this.direction.y,
+ invdirz = 1 / this.direction.z;
- var parent = this.parent;
+ const origin = this.origin;
- if ( updateParents === true && parent !== null ) {
+ if ( invdirx >= 0 ) {
- parent.updateWorldMatrix( true, false );
+ tmin = ( box.min.x - origin.x ) * invdirx;
+ tmax = ( box.max.x - origin.x ) * invdirx;
- }
+ } else {
- if ( this.matrixAutoUpdate ) this.updateMatrix();
+ tmin = ( box.max.x - origin.x ) * invdirx;
+ tmax = ( box.min.x - origin.x ) * invdirx;
- if ( this.parent === null ) {
+ }
- this.matrixWorld.copy( this.matrix );
+ if ( invdiry >= 0 ) {
- } else {
+ tymin = ( box.min.y - origin.y ) * invdiry;
+ tymax = ( box.max.y - origin.y ) * invdiry;
- this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );
+ } else {
- }
+ tymin = ( box.max.y - origin.y ) * invdiry;
+ tymax = ( box.min.y - origin.y ) * invdiry;
- // update children
+ }
- if ( updateChildren === true ) {
+ if ( ( tmin > tymax ) || ( tymin > tmax ) ) return null;
- var children = this.children;
+ if ( tymin > tmin || isNaN( tmin ) ) tmin = tymin;
- for ( var i = 0, l = children.length; i < l; i ++ ) {
+ if ( tymax < tmax || isNaN( tmax ) ) tmax = tymax;
- children[ i ].updateWorldMatrix( false, true );
+ if ( invdirz >= 0 ) {
- }
+ tzmin = ( box.min.z - origin.z ) * invdirz;
+ tzmax = ( box.max.z - origin.z ) * invdirz;
- }
+ } else {
- },
+ tzmin = ( box.max.z - origin.z ) * invdirz;
+ tzmax = ( box.min.z - origin.z ) * invdirz;
- toJSON: function ( meta ) {
+ }
- // meta is a string when called from JSON.stringify
- var isRootObject = ( meta === undefined || typeof meta === 'string' );
+ if ( ( tmin > tzmax ) || ( tzmin > tmax ) ) return null;
- var output = {};
+ if ( tzmin > tmin || tmin !== tmin ) tmin = tzmin;
- // meta is a hash used to collect geometries, materials.
- // not providing it implies that this is the root object
- // being serialized.
- if ( isRootObject ) {
+ if ( tzmax < tmax || tmax !== tmax ) tmax = tzmax;
- // initialize meta obj
- meta = {
- geometries: {},
- materials: {},
- textures: {},
- images: {},
- shapes: {}
- };
+ //return point closest to the ray (positive side)
- output.metadata = {
- version: 4.5,
- type: 'Object',
- generator: 'Object3D.toJSON'
- };
+ if ( tmax < 0 ) return null;
- }
+ return this.at( tmin >= 0 ? tmin : tmax, target );
- // standard Object3D serialization
+ }
- var object = {};
+ intersectsBox( box ) {
- object.uuid = this.uuid;
- object.type = this.type;
+ return this.intersectBox( box, _vector$9 ) !== null;
- if ( this.name !== '' ) object.name = this.name;
- if ( this.castShadow === true ) object.castShadow = true;
- if ( this.receiveShadow === true ) object.receiveShadow = true;
- if ( this.visible === false ) object.visible = false;
- if ( this.frustumCulled === false ) object.frustumCulled = false;
- if ( this.renderOrder !== 0 ) object.renderOrder = this.renderOrder;
- if ( JSON.stringify( this.userData ) !== '{}' ) object.userData = this.userData;
+ }
- object.layers = this.layers.mask;
- object.matrix = this.matrix.toArray();
+ intersectTriangle( a, b, c, backfaceCulling, target ) {
- if ( this.matrixAutoUpdate === false ) object.matrixAutoUpdate = false;
+ // Compute the offset origin, edges, and normal.
- // object specific properties
+ // from https://github.com/pmjoniak/GeometricTools/blob/master/GTEngine/Include/Mathematics/GteIntrRay3Triangle3.h
- if ( this.isMesh && this.drawMode !== TrianglesDrawMode ) object.drawMode = this.drawMode;
+ _edge1.subVectors( b, a );
+ _edge2.subVectors( c, a );
+ _normal$1.crossVectors( _edge1, _edge2 );
- //
+ // Solve Q + t*D = b1*E1 + b2*E2 (Q = kDiff, D = ray direction,
+ // E1 = kEdge1, E2 = kEdge2, N = Cross(E1,E2)) by
+ // |Dot(D,N)|*b1 = sign(Dot(D,N))*Dot(D,Cross(Q,E2))
+ // |Dot(D,N)|*b2 = sign(Dot(D,N))*Dot(D,Cross(E1,Q))
+ // |Dot(D,N)|*t = -sign(Dot(D,N))*Dot(Q,N)
+ let DdN = this.direction.dot( _normal$1 );
+ let sign;
- function serialize( library, element ) {
+ if ( DdN > 0 ) {
- if ( library[ element.uuid ] === undefined ) {
+ if ( backfaceCulling ) return null;
+ sign = 1;
- library[ element.uuid ] = element.toJSON( meta );
+ } else if ( DdN < 0 ) {
- }
+ sign = - 1;
+ DdN = - DdN;
- return element.uuid;
+ } else {
- }
+ return null;
- if ( this.isMesh || this.isLine || this.isPoints ) {
+ }
- object.geometry = serialize( meta.geometries, this.geometry );
+ _diff.subVectors( this.origin, a );
+ const DdQxE2 = sign * this.direction.dot( _edge2.crossVectors( _diff, _edge2 ) );
- var parameters = this.geometry.parameters;
+ // b1 < 0, no intersection
+ if ( DdQxE2 < 0 ) {
- if ( parameters !== undefined && parameters.shapes !== undefined ) {
+ return null;
- var shapes = parameters.shapes;
+ }
- if ( Array.isArray( shapes ) ) {
+ const DdE1xQ = sign * this.direction.dot( _edge1.cross( _diff ) );
- for ( var i = 0, l = shapes.length; i < l; i ++ ) {
+ // b2 < 0, no intersection
+ if ( DdE1xQ < 0 ) {
- var shape = shapes[ i ];
+ return null;
- serialize( meta.shapes, shape );
+ }
- }
+ // b1+b2 > 1, no intersection
+ if ( DdQxE2 + DdE1xQ > DdN ) {
- } else {
+ return null;
- serialize( meta.shapes, shapes );
+ }
- }
+ // Line intersects triangle, check if ray does.
+ const QdN = - sign * _diff.dot( _normal$1 );
- }
+ // t < 0, no intersection
+ if ( QdN < 0 ) {
- }
+ return null;
- if ( this.material !== undefined ) {
+ }
- if ( Array.isArray( this.material ) ) {
+ // Ray intersects triangle.
+ return this.at( QdN / DdN, target );
- var uuids = [];
+ }
- for ( var i = 0, l = this.material.length; i < l; i ++ ) {
+ applyMatrix4( matrix4 ) {
- uuids.push( serialize( meta.materials, this.material[ i ] ) );
+ this.origin.applyMatrix4( matrix4 );
+ this.direction.transformDirection( matrix4 );
- }
+ return this;
- object.material = uuids;
+ }
- } else {
+ equals( ray ) {
- object.material = serialize( meta.materials, this.material );
+ return ray.origin.equals( this.origin ) && ray.direction.equals( this.direction );
- }
+ }
- }
+ clone() {
- //
+ return new this.constructor().copy( this );
- if ( this.children.length > 0 ) {
+ }
- object.children = [];
+}
- for ( var i = 0; i < this.children.length; i ++ ) {
+class Matrix4 {
- object.children.push( this.children[ i ].toJSON( meta ).object );
+ constructor( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) {
- }
+ Matrix4.prototype.isMatrix4 = true;
- }
+ this.elements = [
+
+ 1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ 0, 0, 0, 1
- if ( isRootObject ) {
+ ];
- var geometries = extractFromCache( meta.geometries );
- var materials = extractFromCache( meta.materials );
- var textures = extractFromCache( meta.textures );
- var images = extractFromCache( meta.images );
- var shapes = extractFromCache( meta.shapes );
+ if ( n11 !== undefined ) {
- if ( geometries.length > 0 ) output.geometries = geometries;
- if ( materials.length > 0 ) output.materials = materials;
- if ( textures.length > 0 ) output.textures = textures;
- if ( images.length > 0 ) output.images = images;
- if ( shapes.length > 0 ) output.shapes = shapes;
+ this.set( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 );
- }
+ }
- output.object = object;
+ }
- return output;
+ set( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) {
- // extract data from the cache hash
- // remove metadata on each item
- // and return as array
- function extractFromCache( cache ) {
+ const te = this.elements;
- var values = [];
- for ( var key in cache ) {
+ te[ 0 ] = n11; te[ 4 ] = n12; te[ 8 ] = n13; te[ 12 ] = n14;
+ te[ 1 ] = n21; te[ 5 ] = n22; te[ 9 ] = n23; te[ 13 ] = n24;
+ te[ 2 ] = n31; te[ 6 ] = n32; te[ 10 ] = n33; te[ 14 ] = n34;
+ te[ 3 ] = n41; te[ 7 ] = n42; te[ 11 ] = n43; te[ 15 ] = n44;
- var data = cache[ key ];
- delete data.metadata;
- values.push( data );
+ return this;
- }
- return values;
+ }
- }
+ identity() {
- },
+ this.set(
- clone: function ( recursive ) {
+ 1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ 0, 0, 0, 1
- return new this.constructor().copy( this, recursive );
+ );
- },
+ return this;
- copy: function ( source, recursive ) {
+ }
- if ( recursive === undefined ) recursive = true;
+ clone() {
- this.name = source.name;
+ return new Matrix4().fromArray( this.elements );
- this.up.copy( source.up );
+ }
- this.position.copy( source.position );
- this.quaternion.copy( source.quaternion );
- this.scale.copy( source.scale );
+ copy( m ) {
- this.matrix.copy( source.matrix );
- this.matrixWorld.copy( source.matrixWorld );
+ const te = this.elements;
+ const me = m.elements;
- this.matrixAutoUpdate = source.matrixAutoUpdate;
- this.matrixWorldNeedsUpdate = source.matrixWorldNeedsUpdate;
+ te[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ]; te[ 3 ] = me[ 3 ];
+ te[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ]; te[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ];
+ te[ 8 ] = me[ 8 ]; te[ 9 ] = me[ 9 ]; te[ 10 ] = me[ 10 ]; te[ 11 ] = me[ 11 ];
+ te[ 12 ] = me[ 12 ]; te[ 13 ] = me[ 13 ]; te[ 14 ] = me[ 14 ]; te[ 15 ] = me[ 15 ];
- this.layers.mask = source.layers.mask;
- this.visible = source.visible;
+ return this;
- this.castShadow = source.castShadow;
- this.receiveShadow = source.receiveShadow;
+ }
- this.frustumCulled = source.frustumCulled;
- this.renderOrder = source.renderOrder;
+ copyPosition( m ) {
- this.userData = JSON.parse( JSON.stringify( source.userData ) );
+ const te = this.elements, me = m.elements;
- if ( recursive === true ) {
+ te[ 12 ] = me[ 12 ];
+ te[ 13 ] = me[ 13 ];
+ te[ 14 ] = me[ 14 ];
- for ( var i = 0; i < source.children.length; i ++ ) {
+ return this;
- var child = source.children[ i ];
- this.add( child.clone() );
+ }
- }
+ setFromMatrix3( m ) {
- }
+ const me = m.elements;
- return this;
+ 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
- } );
+ );
- /**
- * @author mrdoob / http://mrdoob.com/
- */
+ return this;
- function Scene() {
+ }
- Object3D.call( this );
+ extractBasis( xAxis, yAxis, zAxis ) {
- this.type = 'Scene';
+ xAxis.setFromMatrixColumn( this, 0 );
+ yAxis.setFromMatrixColumn( this, 1 );
+ zAxis.setFromMatrixColumn( this, 2 );
- this.background = null;
- this.fog = null;
- this.overrideMaterial = null;
+ return this;
- this.autoUpdate = true; // checked by the renderer
+ }
- if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) {
+ makeBasis( xAxis, yAxis, zAxis ) {
- __THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'observe', { detail: this } ) ); // eslint-disable-line no-undef
+ this.set(
+ xAxis.x, yAxis.x, zAxis.x, 0,
+ xAxis.y, yAxis.y, zAxis.y, 0,
+ xAxis.z, yAxis.z, zAxis.z, 0,
+ 0, 0, 0, 1
+ );
- }
+ return this;
}
- Scene.prototype = Object.assign( Object.create( Object3D.prototype ), {
+ extractRotation( m ) {
- constructor: Scene,
+ // this method does not support reflection matrices
- isScene: true,
+ const te = this.elements;
+ const me = m.elements;
- copy: function ( source, recursive ) {
+ const scaleX = 1 / _v1$5.setFromMatrixColumn( m, 0 ).length();
+ const scaleY = 1 / _v1$5.setFromMatrixColumn( m, 1 ).length();
+ const scaleZ = 1 / _v1$5.setFromMatrixColumn( m, 2 ).length();
- Object3D.prototype.copy.call( this, source, recursive );
+ te[ 0 ] = me[ 0 ] * scaleX;
+ te[ 1 ] = me[ 1 ] * scaleX;
+ te[ 2 ] = me[ 2 ] * scaleX;
+ te[ 3 ] = 0;
- if ( source.background !== null ) this.background = source.background.clone();
- if ( source.fog !== null ) this.fog = source.fog.clone();
- if ( source.overrideMaterial !== null ) this.overrideMaterial = source.overrideMaterial.clone();
+ te[ 4 ] = me[ 4 ] * scaleY;
+ te[ 5 ] = me[ 5 ] * scaleY;
+ te[ 6 ] = me[ 6 ] * scaleY;
+ te[ 7 ] = 0;
- this.autoUpdate = source.autoUpdate;
- this.matrixAutoUpdate = source.matrixAutoUpdate;
+ te[ 8 ] = me[ 8 ] * scaleZ;
+ te[ 9 ] = me[ 9 ] * scaleZ;
+ te[ 10 ] = me[ 10 ] * scaleZ;
+ te[ 11 ] = 0;
- return this;
+ te[ 12 ] = 0;
+ te[ 13 ] = 0;
+ te[ 14 ] = 0;
+ te[ 15 ] = 1;
- },
+ return this;
- toJSON: function ( meta ) {
+ }
- var data = Object3D.prototype.toJSON.call( this, meta );
+ makeRotationFromEuler( euler ) {
- if ( this.background !== null ) data.object.background = this.background.toJSON( meta );
- if ( this.fog !== null ) data.object.fog = this.fog.toJSON();
+ const te = this.elements;
- return data;
+ const x = euler.x, y = euler.y, z = euler.z;
+ const a = Math.cos( x ), b = Math.sin( x );
+ const c = Math.cos( y ), d = Math.sin( y );
+ const e = Math.cos( z ), f = Math.sin( z );
- },
+ if ( euler.order === 'XYZ' ) {
- dispose: function () {
+ const ae = a * e, af = a * f, be = b * e, bf = b * f;
- this.dispatchEvent( { type: 'dispose' } );
+ te[ 0 ] = c * e;
+ te[ 4 ] = - c * f;
+ te[ 8 ] = d;
- }
+ te[ 1 ] = af + be * d;
+ te[ 5 ] = ae - bf * d;
+ te[ 9 ] = - b * c;
- } );
+ te[ 2 ] = bf - ae * d;
+ te[ 6 ] = be + af * d;
+ te[ 10 ] = a * c;
- var _points = [
- new Vector3(),
- new Vector3(),
- new Vector3(),
- new Vector3(),
- new Vector3(),
- new Vector3(),
- new Vector3(),
- new Vector3()
- ];
- var _vector$2 = new Vector3();
+ } else if ( euler.order === 'YXZ' ) {
- // triangle centered vertices
+ const ce = c * e, cf = c * f, de = d * e, df = d * f;
- var _v0 = new Vector3();
- var _v1$2 = new Vector3();
- var _v2 = new Vector3();
+ te[ 0 ] = ce + df * b;
+ te[ 4 ] = de * b - cf;
+ te[ 8 ] = a * d;
- // triangle edge vectors
+ te[ 1 ] = a * f;
+ te[ 5 ] = a * e;
+ te[ 9 ] = - b;
- var _f0 = new Vector3();
- var _f1 = new Vector3();
- var _f2 = new Vector3();
+ te[ 2 ] = cf * b - de;
+ te[ 6 ] = df + ce * b;
+ te[ 10 ] = a * c;
- var _center = new Vector3();
- var _extents = new Vector3();
- var _triangleNormal = new Vector3();
- var _testAxis = new Vector3();
+ } else if ( euler.order === 'ZXY' ) {
- /**
- * @author bhouston / http://clara.io
- * @author WestLangley / http://github.com/WestLangley
- */
+ const ce = c * e, cf = c * f, de = d * e, df = d * f;
- function Box3( min, max ) {
+ te[ 0 ] = ce - df * b;
+ te[ 4 ] = - a * f;
+ te[ 8 ] = de + cf * b;
- this.min = ( min !== undefined ) ? min : new Vector3( + Infinity, + Infinity, + Infinity );
- this.max = ( max !== undefined ) ? max : new Vector3( - Infinity, - Infinity, - Infinity );
+ te[ 1 ] = cf + de * b;
+ te[ 5 ] = a * e;
+ te[ 9 ] = df - ce * b;
- }
+ te[ 2 ] = - a * d;
+ te[ 6 ] = b;
+ te[ 10 ] = a * c;
- Object.assign( Box3.prototype, {
+ } else if ( euler.order === 'ZYX' ) {
- isBox3: true,
+ const ae = a * e, af = a * f, be = b * e, bf = b * f;
- set: function ( min, max ) {
+ te[ 0 ] = c * e;
+ te[ 4 ] = be * d - af;
+ te[ 8 ] = ae * d + bf;
- this.min.copy( min );
- this.max.copy( max );
+ te[ 1 ] = c * f;
+ te[ 5 ] = bf * d + ae;
+ te[ 9 ] = af * d - be;
- return this;
+ te[ 2 ] = - d;
+ te[ 6 ] = b * c;
+ te[ 10 ] = a * c;
- },
+ } else if ( euler.order === 'YZX' ) {
- setFromArray: function ( array ) {
+ const ac = a * c, ad = a * d, bc = b * c, bd = b * d;
- var minX = + Infinity;
- var minY = + Infinity;
- var minZ = + Infinity;
+ te[ 0 ] = c * e;
+ te[ 4 ] = bd - ac * f;
+ te[ 8 ] = bc * f + ad;
- var maxX = - Infinity;
- var maxY = - Infinity;
- var maxZ = - Infinity;
+ te[ 1 ] = f;
+ te[ 5 ] = a * e;
+ te[ 9 ] = - b * e;
- for ( var i = 0, l = array.length; i < l; i += 3 ) {
+ te[ 2 ] = - d * e;
+ te[ 6 ] = ad * f + bc;
+ te[ 10 ] = ac - bd * f;
- var x = array[ i ];
- var y = array[ i + 1 ];
- var z = array[ i + 2 ];
+ } else if ( euler.order === 'XZY' ) {
- if ( x < minX ) minX = x;
- if ( y < minY ) minY = y;
- if ( z < minZ ) minZ = z;
+ const ac = a * c, ad = a * d, bc = b * c, bd = b * d;
- if ( x > maxX ) maxX = x;
- if ( y > maxY ) maxY = y;
- if ( z > maxZ ) maxZ = z;
+ te[ 0 ] = c * e;
+ te[ 4 ] = - f;
+ te[ 8 ] = d * e;
- }
+ te[ 1 ] = ac * f + bd;
+ te[ 5 ] = a * e;
+ te[ 9 ] = ad * f - bc;
- this.min.set( minX, minY, minZ );
- this.max.set( maxX, maxY, maxZ );
+ te[ 2 ] = bc * f - ad;
+ te[ 6 ] = b * e;
+ te[ 10 ] = bd * f + ac;
- return this;
+ }
- },
+ // bottom row
+ te[ 3 ] = 0;
+ te[ 7 ] = 0;
+ te[ 11 ] = 0;
- setFromBufferAttribute: function ( attribute ) {
+ // last column
+ te[ 12 ] = 0;
+ te[ 13 ] = 0;
+ te[ 14 ] = 0;
+ te[ 15 ] = 1;
- var minX = + Infinity;
- var minY = + Infinity;
- var minZ = + Infinity;
+ return this;
- var maxX = - Infinity;
- var maxY = - Infinity;
- var maxZ = - Infinity;
+ }
- for ( var i = 0, l = attribute.count; i < l; i ++ ) {
+ makeRotationFromQuaternion( q ) {
- var x = attribute.getX( i );
- var y = attribute.getY( i );
- var z = attribute.getZ( i );
+ return this.compose( _zero, q, _one );
- if ( x < minX ) minX = x;
- if ( y < minY ) minY = y;
- if ( z < minZ ) minZ = z;
+ }
- if ( x > maxX ) maxX = x;
- if ( y > maxY ) maxY = y;
- if ( z > maxZ ) maxZ = z;
+ lookAt( eye, target, up ) {
- }
+ const te = this.elements;
- this.min.set( minX, minY, minZ );
- this.max.set( maxX, maxY, maxZ );
+ _z.subVectors( eye, target );
- return this;
+ if ( _z.lengthSq() === 0 ) {
- },
+ // eye and target are in the same position
- setFromPoints: function ( points ) {
+ _z.z = 1;
- this.makeEmpty();
+ }
- for ( var i = 0, il = points.length; i < il; i ++ ) {
+ _z.normalize();
+ _x.crossVectors( up, _z );
- this.expandByPoint( points[ i ] );
+ if ( _x.lengthSq() === 0 ) {
- }
+ // up and z are parallel
- return this;
+ if ( Math.abs( up.z ) === 1 ) {
- },
+ _z.x += 0.0001;
- setFromCenterAndSize: function ( center, size ) {
+ } else {
- var halfSize = _vector$2.copy( size ).multiplyScalar( 0.5 );
+ _z.z += 0.0001;
- this.min.copy( center ).sub( halfSize );
- this.max.copy( center ).add( halfSize );
+ }
- return this;
+ _z.normalize();
+ _x.crossVectors( up, _z );
- },
+ }
- setFromObject: function ( object ) {
+ _x.normalize();
+ _y.crossVectors( _z, _x );
- this.makeEmpty();
+ te[ 0 ] = _x.x; te[ 4 ] = _y.x; te[ 8 ] = _z.x;
+ te[ 1 ] = _x.y; te[ 5 ] = _y.y; te[ 9 ] = _z.y;
+ te[ 2 ] = _x.z; te[ 6 ] = _y.z; te[ 10 ] = _z.z;
- return this.expandByObject( object );
+ return this;
- },
+ }
- clone: function () {
+ multiply( m ) {
- return new this.constructor().copy( this );
+ return this.multiplyMatrices( this, m );
- },
+ }
- copy: function ( box ) {
+ premultiply( m ) {
- this.min.copy( box.min );
- this.max.copy( box.max );
+ return this.multiplyMatrices( m, this );
- return this;
+ }
- },
+ multiplyMatrices( a, b ) {
- makeEmpty: function () {
+ const ae = a.elements;
+ const be = b.elements;
+ const te = this.elements;
- this.min.x = this.min.y = this.min.z = + Infinity;
- this.max.x = this.max.y = this.max.z = - Infinity;
+ const a11 = ae[ 0 ], a12 = ae[ 4 ], a13 = ae[ 8 ], a14 = ae[ 12 ];
+ const a21 = ae[ 1 ], a22 = ae[ 5 ], a23 = ae[ 9 ], a24 = ae[ 13 ];
+ const a31 = ae[ 2 ], a32 = ae[ 6 ], a33 = ae[ 10 ], a34 = ae[ 14 ];
+ const a41 = ae[ 3 ], a42 = ae[ 7 ], a43 = ae[ 11 ], a44 = ae[ 15 ];
- return this;
+ const b11 = be[ 0 ], b12 = be[ 4 ], b13 = be[ 8 ], b14 = be[ 12 ];
+ const b21 = be[ 1 ], b22 = be[ 5 ], b23 = be[ 9 ], b24 = be[ 13 ];
+ const b31 = be[ 2 ], b32 = be[ 6 ], b33 = be[ 10 ], b34 = be[ 14 ];
+ const b41 = be[ 3 ], b42 = be[ 7 ], b43 = be[ 11 ], b44 = be[ 15 ];
- },
+ te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41;
+ te[ 4 ] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42;
+ te[ 8 ] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43;
+ te[ 12 ] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44;
- isEmpty: function () {
+ te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41;
+ te[ 5 ] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42;
+ te[ 9 ] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43;
+ te[ 13 ] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44;
- // this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes
+ te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41;
+ te[ 6 ] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42;
+ te[ 10 ] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43;
+ te[ 14 ] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44;
- return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y ) || ( this.max.z < this.min.z );
+ te[ 3 ] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41;
+ te[ 7 ] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42;
+ te[ 11 ] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43;
+ te[ 15 ] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44;
- },
+ return this;
- getCenter: function ( target ) {
+ }
- if ( target === undefined ) {
+ multiplyScalar( s ) {
- console.warn( 'THREE.Box3: .getCenter() target is now required' );
- target = new Vector3();
+ const te = this.elements;
- }
+ te[ 0 ] *= s; te[ 4 ] *= s; te[ 8 ] *= s; te[ 12 ] *= s;
+ te[ 1 ] *= s; te[ 5 ] *= s; te[ 9 ] *= s; te[ 13 ] *= s;
+ te[ 2 ] *= s; te[ 6 ] *= s; te[ 10 ] *= s; te[ 14 ] *= s;
+ te[ 3 ] *= s; te[ 7 ] *= s; te[ 11 ] *= s; te[ 15 ] *= s;
- return this.isEmpty() ? target.set( 0, 0, 0 ) : target.addVectors( this.min, this.max ).multiplyScalar( 0.5 );
+ return this;
- },
+ }
- getSize: function ( target ) {
+ determinant() {
+
+ const te = this.elements;
+
+ const n11 = te[ 0 ], n12 = te[ 4 ], n13 = te[ 8 ], n14 = te[ 12 ];
+ const n21 = te[ 1 ], n22 = te[ 5 ], n23 = te[ 9 ], n24 = te[ 13 ];
+ const n31 = te[ 2 ], n32 = te[ 6 ], n33 = te[ 10 ], n34 = te[ 14 ];
+ const n41 = te[ 3 ], n42 = te[ 7 ], n43 = te[ 11 ], n44 = te[ 15 ];
+
+ //TODO: make this more efficient
+ //( based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm )
+
+ return (
+ n41 * (
+ + n14 * n23 * n32
+ - n13 * n24 * n32
+ - n14 * n22 * n33
+ + n12 * n24 * n33
+ + n13 * n22 * n34
+ - n12 * n23 * n34
+ ) +
+ n42 * (
+ + n11 * n23 * n34
+ - n11 * n24 * n33
+ + n14 * n21 * n33
+ - n13 * n21 * n34
+ + n13 * n24 * n31
+ - n14 * n23 * n31
+ ) +
+ n43 * (
+ + n11 * n24 * n32
+ - n11 * n22 * n34
+ - n14 * n21 * n32
+ + n12 * n21 * n34
+ + n14 * n22 * n31
+ - n12 * n24 * n31
+ ) +
+ n44 * (
+ - n13 * n22 * n31
+ - n11 * n23 * n32
+ + n11 * n22 * n33
+ + n13 * n21 * n32
+ - n12 * n21 * n33
+ + n12 * n23 * n31
+ )
- if ( target === undefined ) {
+ );
- console.warn( 'THREE.Box3: .getSize() target is now required' );
- target = new Vector3();
+ }
- }
+ transpose() {
- return this.isEmpty() ? target.set( 0, 0, 0 ) : target.subVectors( this.max, this.min );
+ const te = this.elements;
+ let tmp;
- },
+ tmp = te[ 1 ]; te[ 1 ] = te[ 4 ]; te[ 4 ] = tmp;
+ tmp = te[ 2 ]; te[ 2 ] = te[ 8 ]; te[ 8 ] = tmp;
+ tmp = te[ 6 ]; te[ 6 ] = te[ 9 ]; te[ 9 ] = tmp;
- expandByPoint: function ( point ) {
+ tmp = te[ 3 ]; te[ 3 ] = te[ 12 ]; te[ 12 ] = tmp;
+ tmp = te[ 7 ]; te[ 7 ] = te[ 13 ]; te[ 13 ] = tmp;
+ tmp = te[ 11 ]; te[ 11 ] = te[ 14 ]; te[ 14 ] = tmp;
- this.min.min( point );
- this.max.max( point );
+ return this;
- return this;
+ }
- },
+ setPosition( x, y, z ) {
- expandByVector: function ( vector ) {
+ const te = this.elements;
- this.min.sub( vector );
- this.max.add( vector );
+ if ( x.isVector3 ) {
- return this;
+ te[ 12 ] = x.x;
+ te[ 13 ] = x.y;
+ te[ 14 ] = x.z;
- },
+ } else {
- expandByScalar: function ( scalar ) {
+ te[ 12 ] = x;
+ te[ 13 ] = y;
+ te[ 14 ] = z;
- this.min.addScalar( - scalar );
- this.max.addScalar( scalar );
+ }
- return this;
+ return this;
- },
+ }
- expandByObject: function ( object ) {
+ invert() {
- var i, l;
+ // based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm
+ const te = this.elements,
- // Computes the world-axis-aligned bounding box of an object (including its children),
- // accounting for both the object's, and children's, world transforms
+ n11 = te[ 0 ], n21 = te[ 1 ], n31 = te[ 2 ], n41 = te[ 3 ],
+ n12 = te[ 4 ], n22 = te[ 5 ], n32 = te[ 6 ], n42 = te[ 7 ],
+ n13 = te[ 8 ], n23 = te[ 9 ], n33 = te[ 10 ], n43 = te[ 11 ],
+ n14 = te[ 12 ], n24 = te[ 13 ], n34 = te[ 14 ], n44 = te[ 15 ],
- object.updateWorldMatrix( false, false );
+ t11 = n23 * n34 * n42 - n24 * n33 * n42 + n24 * n32 * n43 - n22 * n34 * n43 - n23 * n32 * n44 + n22 * n33 * n44,
+ t12 = n14 * n33 * n42 - n13 * n34 * n42 - n14 * n32 * n43 + n12 * n34 * n43 + n13 * n32 * n44 - n12 * n33 * n44,
+ t13 = n13 * n24 * n42 - n14 * n23 * n42 + n14 * n22 * n43 - n12 * n24 * n43 - n13 * n22 * n44 + n12 * n23 * n44,
+ t14 = n14 * n23 * n32 - n13 * n24 * n32 - n14 * n22 * n33 + n12 * n24 * n33 + n13 * n22 * n34 - n12 * n23 * n34;
- var geometry = object.geometry;
+ const det = n11 * t11 + n21 * t12 + n31 * t13 + n41 * t14;
- if ( geometry !== undefined ) {
+ if ( det === 0 ) return this.set( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 );
- if ( geometry.isGeometry ) {
+ const detInv = 1 / det;
- var vertices = geometry.vertices;
+ te[ 0 ] = t11 * detInv;
+ te[ 1 ] = ( n24 * n33 * n41 - n23 * n34 * n41 - n24 * n31 * n43 + n21 * n34 * n43 + n23 * n31 * n44 - n21 * n33 * n44 ) * detInv;
+ te[ 2 ] = ( n22 * n34 * n41 - n24 * n32 * n41 + n24 * n31 * n42 - n21 * n34 * n42 - n22 * n31 * n44 + n21 * n32 * n44 ) * detInv;
+ te[ 3 ] = ( n23 * n32 * n41 - n22 * n33 * n41 - n23 * n31 * n42 + n21 * n33 * n42 + n22 * n31 * n43 - n21 * n32 * n43 ) * detInv;
- for ( i = 0, l = vertices.length; i < l; i ++ ) {
+ te[ 4 ] = t12 * detInv;
+ te[ 5 ] = ( n13 * n34 * n41 - n14 * n33 * n41 + n14 * n31 * n43 - n11 * n34 * n43 - n13 * n31 * n44 + n11 * n33 * n44 ) * detInv;
+ te[ 6 ] = ( n14 * n32 * n41 - n12 * n34 * n41 - n14 * n31 * n42 + n11 * n34 * n42 + n12 * n31 * n44 - n11 * n32 * n44 ) * detInv;
+ te[ 7 ] = ( n12 * n33 * n41 - n13 * n32 * n41 + n13 * n31 * n42 - n11 * n33 * n42 - n12 * n31 * n43 + n11 * n32 * n43 ) * detInv;
- _vector$2.copy( vertices[ i ] );
- _vector$2.applyMatrix4( object.matrixWorld );
+ te[ 8 ] = t13 * detInv;
+ te[ 9 ] = ( n14 * n23 * n41 - n13 * n24 * n41 - n14 * n21 * n43 + n11 * n24 * n43 + n13 * n21 * n44 - n11 * n23 * n44 ) * detInv;
+ te[ 10 ] = ( n12 * n24 * n41 - n14 * n22 * n41 + n14 * n21 * n42 - n11 * n24 * n42 - n12 * n21 * n44 + n11 * n22 * n44 ) * detInv;
+ te[ 11 ] = ( n13 * n22 * n41 - n12 * n23 * n41 - n13 * n21 * n42 + n11 * n23 * n42 + n12 * n21 * n43 - n11 * n22 * n43 ) * detInv;
- this.expandByPoint( _vector$2 );
+ te[ 12 ] = t14 * detInv;
+ te[ 13 ] = ( n13 * n24 * n31 - n14 * n23 * n31 + n14 * n21 * n33 - n11 * n24 * n33 - n13 * n21 * n34 + n11 * n23 * n34 ) * detInv;
+ te[ 14 ] = ( n14 * n22 * n31 - n12 * n24 * n31 - n14 * n21 * n32 + n11 * n24 * n32 + n12 * n21 * n34 - n11 * n22 * n34 ) * detInv;
+ te[ 15 ] = ( n12 * n23 * n31 - n13 * n22 * n31 + n13 * n21 * n32 - n11 * n23 * n32 - n12 * n21 * n33 + n11 * n22 * n33 ) * detInv;
- }
+ return this;
- } else if ( geometry.isBufferGeometry ) {
+ }
- var attribute = geometry.attributes.position;
+ scale( v ) {
- if ( attribute !== undefined ) {
+ const te = this.elements;
+ const x = v.x, y = v.y, z = v.z;
- for ( i = 0, l = attribute.count; i < l; i ++ ) {
+ te[ 0 ] *= x; te[ 4 ] *= y; te[ 8 ] *= z;
+ te[ 1 ] *= x; te[ 5 ] *= y; te[ 9 ] *= z;
+ te[ 2 ] *= x; te[ 6 ] *= y; te[ 10 ] *= z;
+ te[ 3 ] *= x; te[ 7 ] *= y; te[ 11 ] *= z;
- _vector$2.fromBufferAttribute( attribute, i ).applyMatrix4( object.matrixWorld );
+ return this;
- this.expandByPoint( _vector$2 );
+ }
- }
+ getMaxScaleOnAxis() {
- }
+ const te = this.elements;
- }
+ const scaleXSq = te[ 0 ] * te[ 0 ] + te[ 1 ] * te[ 1 ] + te[ 2 ] * te[ 2 ];
+ const scaleYSq = te[ 4 ] * te[ 4 ] + te[ 5 ] * te[ 5 ] + te[ 6 ] * te[ 6 ];
+ const scaleZSq = te[ 8 ] * te[ 8 ] + te[ 9 ] * te[ 9 ] + te[ 10 ] * te[ 10 ];
- }
+ return Math.sqrt( Math.max( scaleXSq, scaleYSq, scaleZSq ) );
- //
+ }
- var children = object.children;
+ makeTranslation( x, y, z ) {
- for ( i = 0, l = children.length; i < l; i ++ ) {
+ if ( x.isVector3 ) {
- this.expandByObject( children[ i ] );
+ this.set(
- }
+ 1, 0, 0, x.x,
+ 0, 1, 0, x.y,
+ 0, 0, 1, x.z,
+ 0, 0, 0, 1
- return this;
+ );
- },
+ } else {
- containsPoint: function ( point ) {
+ this.set(
- return point.x < this.min.x || point.x > this.max.x ||
- point.y < this.min.y || point.y > this.max.y ||
- point.z < this.min.z || point.z > this.max.z ? false : true;
+ 1, 0, 0, x,
+ 0, 1, 0, y,
+ 0, 0, 1, z,
+ 0, 0, 0, 1
- },
+ );
- containsBox: function ( box ) {
+ }
- return this.min.x <= box.min.x && box.max.x <= this.max.x &&
- this.min.y <= box.min.y && box.max.y <= this.max.y &&
- this.min.z <= box.min.z && box.max.z <= this.max.z;
+ return this;
- },
+ }
- getParameter: function ( point, target ) {
+ makeRotationX( theta ) {
- // This can potentially have a divide by zero if the box
- // has a size dimension of 0.
+ const c = Math.cos( theta ), s = Math.sin( theta );
- if ( target === undefined ) {
+ this.set(
- console.warn( 'THREE.Box3: .getParameter() target is now required' );
- target = new Vector3();
+ 1, 0, 0, 0,
+ 0, c, - s, 0,
+ 0, s, c, 0,
+ 0, 0, 0, 1
- }
+ );
- return target.set(
- ( point.x - this.min.x ) / ( this.max.x - this.min.x ),
- ( point.y - this.min.y ) / ( this.max.y - this.min.y ),
- ( point.z - this.min.z ) / ( this.max.z - this.min.z )
- );
+ return this;
- },
+ }
- intersectsBox: function ( box ) {
+ makeRotationY( theta ) {
- // using 6 splitting planes to rule out intersections.
- return box.max.x < this.min.x || box.min.x > this.max.x ||
- box.max.y < this.min.y || box.min.y > this.max.y ||
- box.max.z < this.min.z || box.min.z > this.max.z ? false : true;
+ const c = Math.cos( theta ), s = Math.sin( theta );
- },
+ this.set(
- intersectsSphere: function ( sphere ) {
+ c, 0, s, 0,
+ 0, 1, 0, 0,
+ - s, 0, c, 0,
+ 0, 0, 0, 1
- // Find the point on the AABB closest to the sphere center.
- this.clampPoint( sphere.center, _vector$2 );
+ );
- // If that point is inside the sphere, the AABB and sphere intersect.
- return _vector$2.distanceToSquared( sphere.center ) <= ( sphere.radius * sphere.radius );
+ return this;
- },
+ }
- intersectsPlane: function ( plane ) {
+ makeRotationZ( theta ) {
- // We compute the minimum and maximum dot product values. If those values
- // are on the same side (back or front) of the plane, then there is no intersection.
+ const c = Math.cos( theta ), s = Math.sin( theta );
- var min, max;
+ this.set(
- if ( plane.normal.x > 0 ) {
+ c, - s, 0, 0,
+ s, c, 0, 0,
+ 0, 0, 1, 0,
+ 0, 0, 0, 1
- min = plane.normal.x * this.min.x;
- max = plane.normal.x * this.max.x;
+ );
- } else {
+ return this;
- min = plane.normal.x * this.max.x;
- max = plane.normal.x * this.min.x;
+ }
- }
+ makeRotationAxis( axis, angle ) {
- if ( plane.normal.y > 0 ) {
+ // Based on http://www.gamedev.net/reference/articles/article1199.asp
- min += plane.normal.y * this.min.y;
- max += plane.normal.y * this.max.y;
+ const c = Math.cos( angle );
+ const s = Math.sin( angle );
+ const t = 1 - c;
+ const x = axis.x, y = axis.y, z = axis.z;
+ const tx = t * x, ty = t * y;
- } else {
+ this.set(
- min += plane.normal.y * this.max.y;
- max += plane.normal.y * this.min.y;
+ tx * x + c, tx * y - s * z, tx * z + s * y, 0,
+ tx * y + s * z, ty * y + c, ty * z - s * x, 0,
+ tx * z - s * y, ty * z + s * x, t * z * z + c, 0,
+ 0, 0, 0, 1
- }
+ );
- if ( plane.normal.z > 0 ) {
+ return this;
- min += plane.normal.z * this.min.z;
- max += plane.normal.z * this.max.z;
+ }
- } else {
+ makeScale( x, y, z ) {
- min += plane.normal.z * this.max.z;
- max += plane.normal.z * this.min.z;
+ this.set(
- }
+ x, 0, 0, 0,
+ 0, y, 0, 0,
+ 0, 0, z, 0,
+ 0, 0, 0, 1
- return ( min <= - plane.constant && max >= - plane.constant );
+ );
- },
+ return this;
- intersectsTriangle: function ( triangle ) {
+ }
- if ( this.isEmpty() ) {
+ makeShear( xy, xz, yx, yz, zx, zy ) {
- return false;
+ this.set(
- }
+ 1, yx, zx, 0,
+ xy, 1, zy, 0,
+ xz, yz, 1, 0,
+ 0, 0, 0, 1
- // compute box center and extents
- this.getCenter( _center );
- _extents.subVectors( this.max, _center );
+ );
- // translate triangle to aabb origin
- _v0.subVectors( triangle.a, _center );
- _v1$2.subVectors( triangle.b, _center );
- _v2.subVectors( triangle.c, _center );
+ return this;
- // compute edge vectors for triangle
- _f0.subVectors( _v1$2, _v0 );
- _f1.subVectors( _v2, _v1$2 );
- _f2.subVectors( _v0, _v2 );
+ }
- // test against axes that are given by cross product combinations of the edges of the triangle and the edges of the aabb
- // make an axis testing of each of the 3 sides of the aabb against each of the 3 sides of the triangle = 9 axis of separation
- // axis_ij = u_i x f_j (u0, u1, u2 = face normals of aabb = x,y,z axes vectors since aabb is axis aligned)
- var axes = [
- 0, - _f0.z, _f0.y, 0, - _f1.z, _f1.y, 0, - _f2.z, _f2.y,
- _f0.z, 0, - _f0.x, _f1.z, 0, - _f1.x, _f2.z, 0, - _f2.x,
- - _f0.y, _f0.x, 0, - _f1.y, _f1.x, 0, - _f2.y, _f2.x, 0
- ];
- if ( ! satForAxes( axes, _v0, _v1$2, _v2, _extents ) ) {
+ compose( position, quaternion, scale ) {
- return false;
+ const te = this.elements;
- }
+ const x = quaternion._x, y = quaternion._y, z = quaternion._z, w = quaternion._w;
+ const x2 = x + x, y2 = y + y, z2 = z + z;
+ const xx = x * x2, xy = x * y2, xz = x * z2;
+ const yy = y * y2, yz = y * z2, zz = z * z2;
+ const wx = w * x2, wy = w * y2, wz = w * z2;
- // test 3 face normals from the aabb
- axes = [ 1, 0, 0, 0, 1, 0, 0, 0, 1 ];
- if ( ! satForAxes( axes, _v0, _v1$2, _v2, _extents ) ) {
+ const sx = scale.x, sy = scale.y, sz = scale.z;
- return false;
+ te[ 0 ] = ( 1 - ( yy + zz ) ) * sx;
+ te[ 1 ] = ( xy + wz ) * sx;
+ te[ 2 ] = ( xz - wy ) * sx;
+ te[ 3 ] = 0;
- }
+ te[ 4 ] = ( xy - wz ) * sy;
+ te[ 5 ] = ( 1 - ( xx + zz ) ) * sy;
+ te[ 6 ] = ( yz + wx ) * sy;
+ te[ 7 ] = 0;
- // finally testing the face normal of the triangle
- // use already existing triangle edge vectors here
- _triangleNormal.crossVectors( _f0, _f1 );
- axes = [ _triangleNormal.x, _triangleNormal.y, _triangleNormal.z ];
+ te[ 8 ] = ( xz + wy ) * sz;
+ te[ 9 ] = ( yz - wx ) * sz;
+ te[ 10 ] = ( 1 - ( xx + yy ) ) * sz;
+ te[ 11 ] = 0;
- return satForAxes( axes, _v0, _v1$2, _v2, _extents );
+ te[ 12 ] = position.x;
+ te[ 13 ] = position.y;
+ te[ 14 ] = position.z;
+ te[ 15 ] = 1;
- },
+ return this;
- clampPoint: function ( point, target ) {
+ }
- if ( target === undefined ) {
+ decompose( position, quaternion, scale ) {
- console.warn( 'THREE.Box3: .clampPoint() target is now required' );
- target = new Vector3();
+ const te = this.elements;
- }
+ let sx = _v1$5.set( te[ 0 ], te[ 1 ], te[ 2 ] ).length();
+ const sy = _v1$5.set( te[ 4 ], te[ 5 ], te[ 6 ] ).length();
+ const sz = _v1$5.set( te[ 8 ], te[ 9 ], te[ 10 ] ).length();
- return target.copy( point ).clamp( this.min, this.max );
+ // if determine is negative, we need to invert one scale
+ const det = this.determinant();
+ if ( det < 0 ) sx = - sx;
- },
+ position.x = te[ 12 ];
+ position.y = te[ 13 ];
+ position.z = te[ 14 ];
- distanceToPoint: function ( point ) {
+ // scale the rotation part
+ _m1$2.copy( this );
- var clampedPoint = _vector$2.copy( point ).clamp( this.min, this.max );
+ const invSX = 1 / sx;
+ const invSY = 1 / sy;
+ const invSZ = 1 / sz;
- return clampedPoint.sub( point ).length();
+ _m1$2.elements[ 0 ] *= invSX;
+ _m1$2.elements[ 1 ] *= invSX;
+ _m1$2.elements[ 2 ] *= invSX;
- },
+ _m1$2.elements[ 4 ] *= invSY;
+ _m1$2.elements[ 5 ] *= invSY;
+ _m1$2.elements[ 6 ] *= invSY;
- getBoundingSphere: function ( target ) {
+ _m1$2.elements[ 8 ] *= invSZ;
+ _m1$2.elements[ 9 ] *= invSZ;
+ _m1$2.elements[ 10 ] *= invSZ;
- if ( target === undefined ) {
+ quaternion.setFromRotationMatrix( _m1$2 );
- console.error( 'THREE.Box3: .getBoundingSphere() target is now required' );
- //target = new Sphere(); // removed to avoid cyclic dependency
+ scale.x = sx;
+ scale.y = sy;
+ scale.z = sz;
- }
+ return this;
- this.getCenter( target.center );
+ }
- target.radius = this.getSize( _vector$2 ).length() * 0.5;
+ makePerspective( left, right, top, bottom, near, far, coordinateSystem = WebGLCoordinateSystem ) {
- return target;
+ const te = this.elements;
+ const x = 2 * near / ( right - left );
+ const y = 2 * near / ( top - bottom );
- },
+ const a = ( right + left ) / ( right - left );
+ const b = ( top + bottom ) / ( top - bottom );
- intersect: function ( box ) {
+ let c, d;
- this.min.max( box.min );
- this.max.min( box.max );
+ if ( coordinateSystem === WebGLCoordinateSystem ) {
- // ensure that if there is no overlap, the result is fully empty, not slightly empty with non-inf/+inf values that will cause subsequence intersects to erroneously return valid values.
- if ( this.isEmpty() ) this.makeEmpty();
+ c = - ( far + near ) / ( far - near );
+ d = ( - 2 * far * near ) / ( far - near );
- return this;
+ } else if ( coordinateSystem === WebGPUCoordinateSystem ) {
- },
+ c = - far / ( far - near );
+ d = ( - far * near ) / ( far - near );
- union: function ( box ) {
+ } else {
- this.min.min( box.min );
- this.max.max( box.max );
+ throw new Error( 'THREE.Matrix4.makePerspective(): Invalid coordinate system: ' + coordinateSystem );
- return this;
+ }
- },
+ te[ 0 ] = x; te[ 4 ] = 0; te[ 8 ] = a; te[ 12 ] = 0;
+ te[ 1 ] = 0; te[ 5 ] = y; te[ 9 ] = b; te[ 13 ] = 0;
+ te[ 2 ] = 0; te[ 6 ] = 0; te[ 10 ] = c; te[ 14 ] = d;
+ te[ 3 ] = 0; te[ 7 ] = 0; te[ 11 ] = - 1; te[ 15 ] = 0;
- applyMatrix4: function ( matrix ) {
+ return this;
- // transform of empty box is an empty box.
- if ( this.isEmpty() ) return this;
+ }
- // NOTE: I am using a binary pattern to specify all 2^3 combinations below
- _points[ 0 ].set( this.min.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 000
- _points[ 1 ].set( this.min.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 001
- _points[ 2 ].set( this.min.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 010
- _points[ 3 ].set( this.min.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 011
- _points[ 4 ].set( this.max.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 100
- _points[ 5 ].set( this.max.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 101
- _points[ 6 ].set( this.max.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 110
- _points[ 7 ].set( this.max.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 111
+ makeOrthographic( left, right, top, bottom, near, far, coordinateSystem = WebGLCoordinateSystem ) {
- this.setFromPoints( _points );
+ const te = this.elements;
+ const w = 1.0 / ( right - left );
+ const h = 1.0 / ( top - bottom );
+ const p = 1.0 / ( far - near );
- return this;
+ const x = ( right + left ) * w;
+ const y = ( top + bottom ) * h;
- },
+ let z, zInv;
- translate: function ( offset ) {
+ if ( coordinateSystem === WebGLCoordinateSystem ) {
- this.min.add( offset );
- this.max.add( offset );
+ z = ( far + near ) * p;
+ zInv = - 2 * p;
- return this;
+ } else if ( coordinateSystem === WebGPUCoordinateSystem ) {
- },
+ z = near * p;
+ zInv = - 1 * p;
- equals: function ( box ) {
+ } else {
- return box.min.equals( this.min ) && box.max.equals( this.max );
+ throw new Error( 'THREE.Matrix4.makeOrthographic(): Invalid coordinate system: ' + coordinateSystem );
}
- } );
+ te[ 0 ] = 2 * w; te[ 4 ] = 0; te[ 8 ] = 0; te[ 12 ] = - x;
+ te[ 1 ] = 0; te[ 5 ] = 2 * h; te[ 9 ] = 0; te[ 13 ] = - y;
+ te[ 2 ] = 0; te[ 6 ] = 0; te[ 10 ] = zInv; te[ 14 ] = - z;
+ te[ 3 ] = 0; te[ 7 ] = 0; te[ 11 ] = 0; te[ 15 ] = 1;
- function satForAxes( axes, v0, v1, v2, extents ) {
+ return this;
- var i, j;
+ }
- for ( i = 0, j = axes.length - 3; i <= j; i += 3 ) {
+ equals( matrix ) {
- _testAxis.fromArray( axes, i );
- // project the aabb onto the seperating axis
- var r = extents.x * Math.abs( _testAxis.x ) + extents.y * Math.abs( _testAxis.y ) + extents.z * Math.abs( _testAxis.z );
- // project all 3 vertices of the triangle onto the seperating axis
- var p0 = v0.dot( _testAxis );
- var p1 = v1.dot( _testAxis );
- var p2 = v2.dot( _testAxis );
- // actual test, basically see if either of the most extreme of the triangle points intersects r
- if ( Math.max( - Math.max( p0, p1, p2 ), Math.min( p0, p1, p2 ) ) > r ) {
+ const te = this.elements;
+ const me = matrix.elements;
- // points of the projected triangle are outside the projected half-length of the aabb
- // the axis is seperating and we can exit
- return false;
+ for ( let i = 0; i < 16; i ++ ) {
- }
+ if ( te[ i ] !== me[ i ] ) return false;
}
@@ -6641,1683 +6727,1724 @@
}
- var _box = new Box3();
-
- /**
- * @author bhouston / http://clara.io
- * @author mrdoob / http://mrdoob.com/
- */
-
- function Sphere( center, radius ) {
-
- this.center = ( center !== undefined ) ? center : new Vector3();
- this.radius = ( radius !== undefined ) ? radius : 0;
-
- }
-
- Object.assign( Sphere.prototype, {
+ fromArray( array, offset = 0 ) {
- set: function ( center, radius ) {
+ for ( let i = 0; i < 16; i ++ ) {
- this.center.copy( center );
- this.radius = radius;
+ this.elements[ i ] = array[ i + offset ];
- return this;
+ }
- },
+ return this;
- setFromPoints: function ( points, optionalCenter ) {
+ }
- var center = this.center;
+ toArray( array = [], offset = 0 ) {
- if ( optionalCenter !== undefined ) {
+ const te = this.elements;
- center.copy( optionalCenter );
+ array[ offset ] = te[ 0 ];
+ array[ offset + 1 ] = te[ 1 ];
+ array[ offset + 2 ] = te[ 2 ];
+ array[ offset + 3 ] = te[ 3 ];
- } else {
+ array[ offset + 4 ] = te[ 4 ];
+ array[ offset + 5 ] = te[ 5 ];
+ array[ offset + 6 ] = te[ 6 ];
+ array[ offset + 7 ] = te[ 7 ];
- _box.setFromPoints( points ).getCenter( center );
+ array[ offset + 8 ] = te[ 8 ];
+ array[ offset + 9 ] = te[ 9 ];
+ array[ offset + 10 ] = te[ 10 ];
+ array[ offset + 11 ] = te[ 11 ];
- }
+ array[ offset + 12 ] = te[ 12 ];
+ array[ offset + 13 ] = te[ 13 ];
+ array[ offset + 14 ] = te[ 14 ];
+ array[ offset + 15 ] = te[ 15 ];
- var maxRadiusSq = 0;
+ return array;
- for ( var i = 0, il = points.length; i < il; i ++ ) {
+ }
- maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( points[ i ] ) );
+}
- }
+const _v1$5 = /*@__PURE__*/ new Vector3();
+const _m1$2 = /*@__PURE__*/ new Matrix4();
+const _zero = /*@__PURE__*/ new Vector3( 0, 0, 0 );
+const _one = /*@__PURE__*/ new Vector3( 1, 1, 1 );
+const _x = /*@__PURE__*/ new Vector3();
+const _y = /*@__PURE__*/ new Vector3();
+const _z = /*@__PURE__*/ new Vector3();
- this.radius = Math.sqrt( maxRadiusSq );
+const _matrix = /*@__PURE__*/ new Matrix4();
+const _quaternion$3 = /*@__PURE__*/ new Quaternion();
- return this;
+class Euler {
- },
+ constructor( x = 0, y = 0, z = 0, order = Euler.DEFAULT_ORDER ) {
- clone: function () {
+ this.isEuler = true;
- return new this.constructor().copy( this );
+ this._x = x;
+ this._y = y;
+ this._z = z;
+ this._order = order;
- },
+ }
- copy: function ( sphere ) {
+ get x() {
- this.center.copy( sphere.center );
- this.radius = sphere.radius;
+ return this._x;
- return this;
+ }
- },
+ set x( value ) {
- empty: function () {
+ this._x = value;
+ this._onChangeCallback();
- return ( this.radius <= 0 );
+ }
- },
+ get y() {
- containsPoint: function ( point ) {
+ return this._y;
- return ( point.distanceToSquared( this.center ) <= ( this.radius * this.radius ) );
+ }
- },
+ set y( value ) {
- distanceToPoint: function ( point ) {
+ this._y = value;
+ this._onChangeCallback();
- return ( point.distanceTo( this.center ) - this.radius );
+ }
- },
+ get z() {
- intersectsSphere: function ( sphere ) {
+ return this._z;
- var radiusSum = this.radius + sphere.radius;
+ }
- return sphere.center.distanceToSquared( this.center ) <= ( radiusSum * radiusSum );
+ set z( value ) {
- },
+ this._z = value;
+ this._onChangeCallback();
- intersectsBox: function ( box ) {
+ }
- return box.intersectsSphere( this );
+ get order() {
- },
+ return this._order;
- intersectsPlane: function ( plane ) {
+ }
- return Math.abs( plane.distanceToPoint( this.center ) ) <= this.radius;
+ set order( value ) {
- },
+ this._order = value;
+ this._onChangeCallback();
- clampPoint: function ( point, target ) {
+ }
- var deltaLengthSq = this.center.distanceToSquared( point );
+ set( x, y, z, order = this._order ) {
- if ( target === undefined ) {
+ this._x = x;
+ this._y = y;
+ this._z = z;
+ this._order = order;
- console.warn( 'THREE.Sphere: .clampPoint() target is now required' );
- target = new Vector3();
+ this._onChangeCallback();
- }
+ return this;
- target.copy( point );
+ }
- if ( deltaLengthSq > ( this.radius * this.radius ) ) {
+ clone() {
- target.sub( this.center ).normalize();
- target.multiplyScalar( this.radius ).add( this.center );
+ return new this.constructor( this._x, this._y, this._z, this._order );
- }
+ }
- return target;
+ copy( euler ) {
- },
+ this._x = euler._x;
+ this._y = euler._y;
+ this._z = euler._z;
+ this._order = euler._order;
- getBoundingBox: function ( target ) {
+ this._onChangeCallback();
- if ( target === undefined ) {
+ return this;
- console.warn( 'THREE.Sphere: .getBoundingBox() target is now required' );
- target = new Box3();
+ }
- }
+ setFromRotationMatrix( m, order = this._order, update = true ) {
- target.set( this.center, this.center );
- target.expandByScalar( this.radius );
+ // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
- return target;
+ const te = m.elements;
+ const m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ];
+ const m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ];
+ const m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ];
- },
+ switch ( order ) {
- applyMatrix4: function ( matrix ) {
+ case 'XYZ':
- this.center.applyMatrix4( matrix );
- this.radius = this.radius * matrix.getMaxScaleOnAxis();
+ this._y = Math.asin( clamp( m13, - 1, 1 ) );
- return this;
+ if ( Math.abs( m13 ) < 0.9999999 ) {
- },
+ this._x = Math.atan2( - m23, m33 );
+ this._z = Math.atan2( - m12, m11 );
- translate: function ( offset ) {
+ } else {
- this.center.add( offset );
+ this._x = Math.atan2( m32, m22 );
+ this._z = 0;
- return this;
+ }
- },
+ break;
- equals: function ( sphere ) {
+ case 'YXZ':
- return sphere.center.equals( this.center ) && ( sphere.radius === this.radius );
+ this._x = Math.asin( - clamp( m23, - 1, 1 ) );
- }
+ if ( Math.abs( m23 ) < 0.9999999 ) {
- } );
+ this._y = Math.atan2( m13, m33 );
+ this._z = Math.atan2( m21, m22 );
- var _vector$3 = new Vector3();
- var _segCenter = new Vector3();
- var _segDir = new Vector3();
- var _diff = new Vector3();
+ } else {
- var _edge1 = new Vector3();
- var _edge2 = new Vector3();
- var _normal = new Vector3();
+ this._y = Math.atan2( - m31, m11 );
+ this._z = 0;
- /**
- * @author bhouston / http://clara.io
- */
+ }
- function Ray( origin, direction ) {
+ break;
- this.origin = ( origin !== undefined ) ? origin : new Vector3();
- this.direction = ( direction !== undefined ) ? direction : new Vector3();
+ case 'ZXY':
- }
+ this._x = Math.asin( clamp( m32, - 1, 1 ) );
- Object.assign( Ray.prototype, {
+ if ( Math.abs( m32 ) < 0.9999999 ) {
- set: function ( origin, direction ) {
+ this._y = Math.atan2( - m31, m33 );
+ this._z = Math.atan2( - m12, m22 );
- this.origin.copy( origin );
- this.direction.copy( direction );
+ } else {
- return this;
+ this._y = 0;
+ this._z = Math.atan2( m21, m11 );
- },
+ }
- clone: function () {
+ break;
- return new this.constructor().copy( this );
+ case 'ZYX':
- },
+ this._y = Math.asin( - clamp( m31, - 1, 1 ) );
- copy: function ( ray ) {
+ if ( Math.abs( m31 ) < 0.9999999 ) {
- this.origin.copy( ray.origin );
- this.direction.copy( ray.direction );
+ this._x = Math.atan2( m32, m33 );
+ this._z = Math.atan2( m21, m11 );
- return this;
+ } else {
- },
+ this._x = 0;
+ this._z = Math.atan2( - m12, m22 );
- at: function ( t, target ) {
+ }
- if ( target === undefined ) {
+ break;
- console.warn( 'THREE.Ray: .at() target is now required' );
- target = new Vector3();
+ case 'YZX':
- }
+ this._z = Math.asin( clamp( m21, - 1, 1 ) );
- return target.copy( this.direction ).multiplyScalar( t ).add( this.origin );
+ if ( Math.abs( m21 ) < 0.9999999 ) {
- },
+ this._x = Math.atan2( - m23, m22 );
+ this._y = Math.atan2( - m31, m11 );
- lookAt: function ( v ) {
+ } else {
- this.direction.copy( v ).sub( this.origin ).normalize();
+ this._x = 0;
+ this._y = Math.atan2( m13, m33 );
- return this;
+ }
- },
+ break;
- recast: function ( t ) {
+ case 'XZY':
- this.origin.copy( this.at( t, _vector$3 ) );
+ this._z = Math.asin( - clamp( m12, - 1, 1 ) );
- return this;
+ if ( Math.abs( m12 ) < 0.9999999 ) {
- },
+ this._x = Math.atan2( m32, m22 );
+ this._y = Math.atan2( m13, m11 );
- closestPointToPoint: function ( point, target ) {
+ } else {
- if ( target === undefined ) {
+ this._x = Math.atan2( - m23, m33 );
+ this._y = 0;
- console.warn( 'THREE.Ray: .closestPointToPoint() target is now required' );
- target = new Vector3();
+ }
- }
+ break;
- target.subVectors( point, this.origin );
+ default:
- var directionDistance = target.dot( this.direction );
+ console.warn( 'THREE.Euler: .setFromRotationMatrix() encountered an unknown order: ' + order );
- if ( directionDistance < 0 ) {
+ }
- return target.copy( this.origin );
+ this._order = order;
- }
+ if ( update === true ) this._onChangeCallback();
- return target.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin );
+ return this;
- },
+ }
- distanceToPoint: function ( point ) {
+ setFromQuaternion( q, order, update ) {
- return Math.sqrt( this.distanceSqToPoint( point ) );
+ _matrix.makeRotationFromQuaternion( q );
- },
+ return this.setFromRotationMatrix( _matrix, order, update );
- distanceSqToPoint: function ( point ) {
+ }
- var directionDistance = _vector$3.subVectors( point, this.origin ).dot( this.direction );
+ setFromVector3( v, order = this._order ) {
- // point behind the ray
+ return this.set( v.x, v.y, v.z, order );
- if ( directionDistance < 0 ) {
+ }
- return this.origin.distanceToSquared( point );
+ reorder( newOrder ) {
- }
+ // WARNING: this discards revolution information -bhouston
- _vector$3.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin );
+ _quaternion$3.setFromEuler( this );
- return _vector$3.distanceToSquared( point );
+ return this.setFromQuaternion( _quaternion$3, newOrder );
- },
+ }
- distanceSqToSegment: function ( v0, v1, optionalPointOnRay, optionalPointOnSegment ) {
+ equals( euler ) {
- // from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteDistRaySegment.h
- // It returns the min distance between the ray and the segment
- // defined by v0 and v1
- // It can also set two optional targets :
- // - The closest point on the ray
- // - The closest point on the segment
+ return ( euler._x === this._x ) && ( euler._y === this._y ) && ( euler._z === this._z ) && ( euler._order === this._order );
- _segCenter.copy( v0 ).add( v1 ).multiplyScalar( 0.5 );
- _segDir.copy( v1 ).sub( v0 ).normalize();
- _diff.copy( this.origin ).sub( _segCenter );
+ }
- var segExtent = v0.distanceTo( v1 ) * 0.5;
- var a01 = - this.direction.dot( _segDir );
- var b0 = _diff.dot( this.direction );
- var b1 = - _diff.dot( _segDir );
- var c = _diff.lengthSq();
- var det = Math.abs( 1 - a01 * a01 );
- var s0, s1, sqrDist, extDet;
+ fromArray( array ) {
- if ( det > 0 ) {
+ this._x = array[ 0 ];
+ this._y = array[ 1 ];
+ this._z = array[ 2 ];
+ if ( array[ 3 ] !== undefined ) this._order = array[ 3 ];
- // The ray and segment are not parallel.
+ this._onChangeCallback();
- s0 = a01 * b1 - b0;
- s1 = a01 * b0 - b1;
- extDet = segExtent * det;
+ return this;
- if ( s0 >= 0 ) {
+ }
- if ( s1 >= - extDet ) {
+ toArray( array = [], offset = 0 ) {
- if ( s1 <= extDet ) {
+ array[ offset ] = this._x;
+ array[ offset + 1 ] = this._y;
+ array[ offset + 2 ] = this._z;
+ array[ offset + 3 ] = this._order;
- // region 0
- // Minimum at interior points of ray and segment.
+ return array;
- var invDet = 1 / det;
- s0 *= invDet;
- s1 *= invDet;
- sqrDist = s0 * ( s0 + a01 * s1 + 2 * b0 ) + s1 * ( a01 * s0 + s1 + 2 * b1 ) + c;
+ }
- } else {
+ _onChange( callback ) {
- // region 1
+ this._onChangeCallback = callback;
- s1 = segExtent;
- s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
- sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
+ return this;
- }
+ }
- } else {
+ _onChangeCallback() {}
- // region 5
+ *[ Symbol.iterator ]() {
- s1 = - segExtent;
- s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
- sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
+ yield this._x;
+ yield this._y;
+ yield this._z;
+ yield this._order;
- }
+ }
- } else {
+}
- if ( s1 <= - extDet ) {
+Euler.DEFAULT_ORDER = 'XYZ';
- // region 4
+class Layers {
- s0 = Math.max( 0, - ( - a01 * segExtent + b0 ) );
- s1 = ( s0 > 0 ) ? - segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );
- sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
+ constructor() {
- } else if ( s1 <= extDet ) {
+ this.mask = 1 | 0;
- // region 3
+ }
- s0 = 0;
- s1 = Math.min( Math.max( - segExtent, - b1 ), segExtent );
- sqrDist = s1 * ( s1 + 2 * b1 ) + c;
+ set( channel ) {
- } else {
+ this.mask = ( 1 << channel | 0 ) >>> 0;
- // region 2
+ }
- s0 = Math.max( 0, - ( a01 * segExtent + b0 ) );
- s1 = ( s0 > 0 ) ? segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );
- sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
+ enable( channel ) {
- }
+ this.mask |= 1 << channel | 0;
- }
+ }
- } else {
+ enableAll() {
- // Ray and segment are parallel.
+ this.mask = 0xffffffff | 0;
- s1 = ( a01 > 0 ) ? - segExtent : segExtent;
- s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
- sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
+ }
- }
+ toggle( channel ) {
- if ( optionalPointOnRay ) {
+ this.mask ^= 1 << channel | 0;
- optionalPointOnRay.copy( this.direction ).multiplyScalar( s0 ).add( this.origin );
+ }
- }
+ disable( channel ) {
- if ( optionalPointOnSegment ) {
+ this.mask &= ~ ( 1 << channel | 0 );
- optionalPointOnSegment.copy( _segDir ).multiplyScalar( s1 ).add( _segCenter );
+ }
- }
+ disableAll() {
- return sqrDist;
+ this.mask = 0;
- },
+ }
- intersectSphere: function ( sphere, target ) {
+ test( layers ) {
- _vector$3.subVectors( sphere.center, this.origin );
- var tca = _vector$3.dot( this.direction );
- var d2 = _vector$3.dot( _vector$3 ) - tca * tca;
- var radius2 = sphere.radius * sphere.radius;
+ return ( this.mask & layers.mask ) !== 0;
- if ( d2 > radius2 ) return null;
+ }
- var thc = Math.sqrt( radius2 - d2 );
+ isEnabled( channel ) {
- // t0 = first intersect point - entrance on front of sphere
- var t0 = tca - thc;
+ return ( this.mask & ( 1 << channel | 0 ) ) !== 0;
- // t1 = second intersect point - exit point on back of sphere
- var t1 = tca + thc;
+ }
- // test to see if both t0 and t1 are behind the ray - if so, return null
- if ( t0 < 0 && t1 < 0 ) return null;
+}
- // test to see if t0 is behind the ray:
- // if it is, the ray is inside the sphere, so return the second exit point scaled by t1,
- // in order to always return an intersect point that is in front of the ray.
- if ( t0 < 0 ) return this.at( t1, target );
+let _object3DId = 0;
- // else t0 is in front of the ray, so return the first collision point scaled by t0
- return this.at( t0, target );
+const _v1$4 = /*@__PURE__*/ new Vector3();
+const _q1 = /*@__PURE__*/ new Quaternion();
+const _m1$1 = /*@__PURE__*/ new Matrix4();
+const _target = /*@__PURE__*/ new Vector3();
- },
+const _position$3 = /*@__PURE__*/ new Vector3();
+const _scale$2 = /*@__PURE__*/ new Vector3();
+const _quaternion$2 = /*@__PURE__*/ new Quaternion();
- intersectsSphere: function ( sphere ) {
+const _xAxis = /*@__PURE__*/ new Vector3( 1, 0, 0 );
+const _yAxis = /*@__PURE__*/ new Vector3( 0, 1, 0 );
+const _zAxis = /*@__PURE__*/ new Vector3( 0, 0, 1 );
- return this.distanceSqToPoint( sphere.center ) <= ( sphere.radius * sphere.radius );
+const _addedEvent = { type: 'added' };
+const _removedEvent = { type: 'removed' };
- },
+class Object3D extends EventDispatcher {
- distanceToPlane: function ( plane ) {
+ constructor() {
- var denominator = plane.normal.dot( this.direction );
+ super();
- if ( denominator === 0 ) {
+ this.isObject3D = true;
- // line is coplanar, return origin
- if ( plane.distanceToPoint( this.origin ) === 0 ) {
+ Object.defineProperty( this, 'id', { value: _object3DId ++ } );
- return 0;
+ this.uuid = generateUUID();
- }
+ this.name = '';
+ this.type = 'Object3D';
- // Null is preferable to undefined since undefined means.... it is undefined
+ this.parent = null;
+ this.children = [];
- return null;
+ this.up = Object3D.DEFAULT_UP.clone();
- }
+ const position = new Vector3();
+ const rotation = new Euler();
+ const quaternion = new Quaternion();
+ const scale = new Vector3( 1, 1, 1 );
- var t = - ( this.origin.dot( plane.normal ) + plane.constant ) / denominator;
+ function onRotationChange() {
- // Return if the ray never intersects the plane
+ quaternion.setFromEuler( rotation, false );
- return t >= 0 ? t : null;
+ }
- },
+ function onQuaternionChange() {
- intersectPlane: function ( plane, target ) {
+ rotation.setFromQuaternion( quaternion, undefined, false );
- var t = this.distanceToPlane( plane );
+ }
- if ( t === null ) {
-
- return null;
+ rotation._onChange( onRotationChange );
+ quaternion._onChange( onQuaternionChange );
+ Object.defineProperties( this, {
+ position: {
+ configurable: true,
+ enumerable: true,
+ value: position
+ },
+ rotation: {
+ configurable: true,
+ enumerable: true,
+ value: rotation
+ },
+ quaternion: {
+ configurable: true,
+ enumerable: true,
+ value: quaternion
+ },
+ scale: {
+ configurable: true,
+ enumerable: true,
+ value: scale
+ },
+ modelViewMatrix: {
+ value: new Matrix4()
+ },
+ normalMatrix: {
+ value: new Matrix3()
}
+ } );
- return this.at( t, target );
+ this.matrix = new Matrix4();
+ this.matrixWorld = new Matrix4();
- },
+ this.matrixAutoUpdate = Object3D.DEFAULT_MATRIX_AUTO_UPDATE;
+ this.matrixWorldNeedsUpdate = false;
- intersectsPlane: function ( plane ) {
+ this.matrixWorldAutoUpdate = Object3D.DEFAULT_MATRIX_WORLD_AUTO_UPDATE; // checked by the renderer
- // check if the ray lies on the plane first
+ this.layers = new Layers();
+ this.visible = true;
- var distToPoint = plane.distanceToPoint( this.origin );
+ this.castShadow = false;
+ this.receiveShadow = false;
- if ( distToPoint === 0 ) {
+ this.frustumCulled = true;
+ this.renderOrder = 0;
- return true;
+ this.animations = [];
- }
+ this.userData = {};
- var denominator = plane.normal.dot( this.direction );
+ }
- if ( denominator * distToPoint < 0 ) {
+ onBeforeRender( /* renderer, scene, camera, geometry, material, group */ ) {}
- return true;
+ onAfterRender( /* renderer, scene, camera, geometry, material, group */ ) {}
- }
+ applyMatrix4( matrix ) {
- // ray origin is behind the plane (and is pointing behind it)
+ if ( this.matrixAutoUpdate ) this.updateMatrix();
- return false;
+ this.matrix.premultiply( matrix );
- },
+ this.matrix.decompose( this.position, this.quaternion, this.scale );
- intersectBox: function ( box, target ) {
+ }
- var tmin, tmax, tymin, tymax, tzmin, tzmax;
+ applyQuaternion( q ) {
- var invdirx = 1 / this.direction.x,
- invdiry = 1 / this.direction.y,
- invdirz = 1 / this.direction.z;
+ this.quaternion.premultiply( q );
- var origin = this.origin;
+ return this;
- if ( invdirx >= 0 ) {
+ }
- tmin = ( box.min.x - origin.x ) * invdirx;
- tmax = ( box.max.x - origin.x ) * invdirx;
+ setRotationFromAxisAngle( axis, angle ) {
- } else {
+ // assumes axis is normalized
- tmin = ( box.max.x - origin.x ) * invdirx;
- tmax = ( box.min.x - origin.x ) * invdirx;
+ this.quaternion.setFromAxisAngle( axis, angle );
- }
+ }
- if ( invdiry >= 0 ) {
+ setRotationFromEuler( euler ) {
- tymin = ( box.min.y - origin.y ) * invdiry;
- tymax = ( box.max.y - origin.y ) * invdiry;
+ this.quaternion.setFromEuler( euler, true );
- } else {
+ }
- tymin = ( box.max.y - origin.y ) * invdiry;
- tymax = ( box.min.y - origin.y ) * invdiry;
+ setRotationFromMatrix( m ) {
- }
+ // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
- if ( ( tmin > tymax ) || ( tymin > tmax ) ) return null;
+ this.quaternion.setFromRotationMatrix( m );
- // These lines also handle the case where tmin or tmax is NaN
- // (result of 0 * Infinity). x !== x returns true if x is NaN
+ }
- if ( tymin > tmin || tmin !== tmin ) tmin = tymin;
+ setRotationFromQuaternion( q ) {
- if ( tymax < tmax || tmax !== tmax ) tmax = tymax;
+ // assumes q is normalized
- if ( invdirz >= 0 ) {
+ this.quaternion.copy( q );
- tzmin = ( box.min.z - origin.z ) * invdirz;
- tzmax = ( box.max.z - origin.z ) * invdirz;
+ }
- } else {
+ rotateOnAxis( axis, angle ) {
- tzmin = ( box.max.z - origin.z ) * invdirz;
- tzmax = ( box.min.z - origin.z ) * invdirz;
+ // rotate object on axis in object space
+ // axis is assumed to be normalized
- }
+ _q1.setFromAxisAngle( axis, angle );
- if ( ( tmin > tzmax ) || ( tzmin > tmax ) ) return null;
+ this.quaternion.multiply( _q1 );
- if ( tzmin > tmin || tmin !== tmin ) tmin = tzmin;
+ return this;
- if ( tzmax < tmax || tmax !== tmax ) tmax = tzmax;
+ }
- //return point closest to the ray (positive side)
+ rotateOnWorldAxis( axis, angle ) {
- if ( tmax < 0 ) return null;
+ // rotate object on axis in world space
+ // axis is assumed to be normalized
+ // method assumes no rotated parent
- return this.at( tmin >= 0 ? tmin : tmax, target );
+ _q1.setFromAxisAngle( axis, angle );
- },
+ this.quaternion.premultiply( _q1 );
- intersectsBox: function ( box ) {
+ return this;
+
+ }
- return this.intersectBox( box, _vector$3 ) !== null;
+ rotateX( angle ) {
- },
+ return this.rotateOnAxis( _xAxis, angle );
- intersectTriangle: function ( a, b, c, backfaceCulling, target ) {
+ }
- // Compute the offset origin, edges, and normal.
+ rotateY( angle ) {
- // from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteIntrRay3Triangle3.h
+ return this.rotateOnAxis( _yAxis, angle );
- _edge1.subVectors( b, a );
- _edge2.subVectors( c, a );
- _normal.crossVectors( _edge1, _edge2 );
+ }
- // Solve Q + t*D = b1*E1 + b2*E2 (Q = kDiff, D = ray direction,
- // E1 = kEdge1, E2 = kEdge2, N = Cross(E1,E2)) by
- // |Dot(D,N)|*b1 = sign(Dot(D,N))*Dot(D,Cross(Q,E2))
- // |Dot(D,N)|*b2 = sign(Dot(D,N))*Dot(D,Cross(E1,Q))
- // |Dot(D,N)|*t = -sign(Dot(D,N))*Dot(Q,N)
- var DdN = this.direction.dot( _normal );
- var sign;
+ rotateZ( angle ) {
- if ( DdN > 0 ) {
+ return this.rotateOnAxis( _zAxis, angle );
- if ( backfaceCulling ) return null;
- sign = 1;
+ }
- } else if ( DdN < 0 ) {
+ translateOnAxis( axis, distance ) {
- sign = - 1;
- DdN = - DdN;
+ // translate object by distance along axis in object space
+ // axis is assumed to be normalized
- } else {
+ _v1$4.copy( axis ).applyQuaternion( this.quaternion );
- return null;
+ this.position.add( _v1$4.multiplyScalar( distance ) );
- }
+ return this;
- _diff.subVectors( this.origin, a );
- var DdQxE2 = sign * this.direction.dot( _edge2.crossVectors( _diff, _edge2 ) );
+ }
- // b1 < 0, no intersection
- if ( DdQxE2 < 0 ) {
+ translateX( distance ) {
- return null;
+ return this.translateOnAxis( _xAxis, distance );
- }
+ }
- var DdE1xQ = sign * this.direction.dot( _edge1.cross( _diff ) );
+ translateY( distance ) {
- // b2 < 0, no intersection
- if ( DdE1xQ < 0 ) {
+ return this.translateOnAxis( _yAxis, distance );
- return null;
+ }
- }
+ translateZ( distance ) {
- // b1+b2 > 1, no intersection
- if ( DdQxE2 + DdE1xQ > DdN ) {
+ return this.translateOnAxis( _zAxis, distance );
- return null;
+ }
- }
+ localToWorld( vector ) {
- // Line intersects triangle, check if ray does.
- var QdN = - sign * _diff.dot( _normal );
+ this.updateWorldMatrix( true, false );
- // t < 0, no intersection
- if ( QdN < 0 ) {
+ return vector.applyMatrix4( this.matrixWorld );
- return null;
+ }
- }
+ worldToLocal( vector ) {
- // Ray intersects triangle.
- return this.at( QdN / DdN, target );
+ this.updateWorldMatrix( true, false );
- },
+ return vector.applyMatrix4( _m1$1.copy( this.matrixWorld ).invert() );
- applyMatrix4: function ( matrix4 ) {
+ }
- this.origin.applyMatrix4( matrix4 );
- this.direction.transformDirection( matrix4 );
+ lookAt( x, y, z ) {
- return this;
+ // This method does not support objects having non-uniformly-scaled parent(s)
- },
+ if ( x.isVector3 ) {
- equals: function ( ray ) {
+ _target.copy( x );
- return ray.origin.equals( this.origin ) && ray.direction.equals( this.direction );
+ } else {
+
+ _target.set( x, y, z );
}
- } );
+ const parent = this.parent;
- /**
- * @author bhouston / http://clara.io
- * @author mrdoob / http://mrdoob.com/
- */
+ this.updateWorldMatrix( true, false );
+
+ _position$3.setFromMatrixPosition( this.matrixWorld );
- var _v0$1 = new Vector3();
- var _v1$3 = new Vector3();
- var _v2$1 = new Vector3();
- var _v3 = new Vector3();
+ if ( this.isCamera || this.isLight ) {
- var _vab = new Vector3();
- var _vac = new Vector3();
- var _vbc = new Vector3();
- var _vap = new Vector3();
- var _vbp = new Vector3();
- var _vcp = new Vector3();
+ _m1$1.lookAt( _position$3, _target, this.up );
- function Triangle( a, b, c ) {
+ } else {
- this.a = ( a !== undefined ) ? a : new Vector3();
- this.b = ( b !== undefined ) ? b : new Vector3();
- this.c = ( c !== undefined ) ? c : new Vector3();
+ _m1$1.lookAt( _target, _position$3, this.up );
- }
+ }
- Object.assign( Triangle, {
+ this.quaternion.setFromRotationMatrix( _m1$1 );
- getNormal: function ( a, b, c, target ) {
+ if ( parent ) {
- if ( target === undefined ) {
+ _m1$1.extractRotation( parent.matrixWorld );
+ _q1.setFromRotationMatrix( _m1$1 );
+ this.quaternion.premultiply( _q1.invert() );
- console.warn( 'THREE.Triangle: .getNormal() target is now required' );
- target = new Vector3();
+ }
- }
+ }
- target.subVectors( c, b );
- _v0$1.subVectors( a, b );
- target.cross( _v0$1 );
+ add( object ) {
- var targetLengthSq = target.lengthSq();
- if ( targetLengthSq > 0 ) {
+ if ( arguments.length > 1 ) {
- return target.multiplyScalar( 1 / Math.sqrt( targetLengthSq ) );
+ for ( let i = 0; i < arguments.length; i ++ ) {
+
+ this.add( arguments[ i ] );
}
- return target.set( 0, 0, 0 );
+ return this;
- },
+ }
- // static/instance method to calculate barycentric coordinates
- // based on: http://www.blackpawn.com/texts/pointinpoly/default.html
- getBarycoord: function ( point, a, b, c, target ) {
+ if ( object === this ) {
- _v0$1.subVectors( c, a );
- _v1$3.subVectors( b, a );
- _v2$1.subVectors( point, a );
+ console.error( 'THREE.Object3D.add: object can\'t be added as a child of itself.', object );
+ return this;
- var dot00 = _v0$1.dot( _v0$1 );
- var dot01 = _v0$1.dot( _v1$3 );
- var dot02 = _v0$1.dot( _v2$1 );
- var dot11 = _v1$3.dot( _v1$3 );
- var dot12 = _v1$3.dot( _v2$1 );
+ }
- var denom = ( dot00 * dot11 - dot01 * dot01 );
+ if ( object && object.isObject3D ) {
- if ( target === undefined ) {
+ if ( object.parent !== null ) {
- console.warn( 'THREE.Triangle: .getBarycoord() target is now required' );
- target = new Vector3();
+ object.parent.remove( object );
}
- // collinear or singular triangle
- if ( denom === 0 ) {
+ object.parent = this;
+ this.children.push( object );
- // arbitrary location outside of triangle?
- // not sure if this is the best idea, maybe should be returning undefined
- return target.set( - 2, - 1, - 1 );
+ object.dispatchEvent( _addedEvent );
- }
+ } else {
- var invDenom = 1 / denom;
- var u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom;
- var v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom;
+ console.error( 'THREE.Object3D.add: object not an instance of THREE.Object3D.', object );
- // barycentric coordinates must always sum to 1
- return target.set( 1 - u - v, v, u );
+ }
- },
+ return this;
- containsPoint: function ( point, a, b, c ) {
+ }
- Triangle.getBarycoord( point, a, b, c, _v3 );
+ remove( object ) {
- return ( _v3.x >= 0 ) && ( _v3.y >= 0 ) && ( ( _v3.x + _v3.y ) <= 1 );
+ if ( arguments.length > 1 ) {
- },
+ for ( let i = 0; i < arguments.length; i ++ ) {
- getUV: function ( point, p1, p2, p3, uv1, uv2, uv3, target ) {
+ this.remove( arguments[ i ] );
- this.getBarycoord( point, p1, p2, p3, _v3 );
+ }
- target.set( 0, 0 );
- target.addScaledVector( uv1, _v3.x );
- target.addScaledVector( uv2, _v3.y );
- target.addScaledVector( uv3, _v3.z );
+ return this;
- return target;
+ }
- },
+ const index = this.children.indexOf( object );
- isFrontFacing: function ( a, b, c, direction ) {
+ if ( index !== - 1 ) {
- _v0$1.subVectors( c, b );
- _v1$3.subVectors( a, b );
+ object.parent = null;
+ this.children.splice( index, 1 );
- // strictly front facing
- return ( _v0$1.cross( _v1$3 ).dot( direction ) < 0 ) ? true : false;
+ object.dispatchEvent( _removedEvent );
}
- } );
+ return this;
- Object.assign( Triangle.prototype, {
+ }
- set: function ( a, b, c ) {
+ removeFromParent() {
- this.a.copy( a );
- this.b.copy( b );
- this.c.copy( c );
+ const parent = this.parent;
- return this;
+ if ( parent !== null ) {
- },
+ parent.remove( this );
- setFromPointsAndIndices: function ( points, i0, i1, i2 ) {
+ }
- this.a.copy( points[ i0 ] );
- this.b.copy( points[ i1 ] );
- this.c.copy( points[ i2 ] );
+ return this;
- return this;
+ }
- },
+ clear() {
- clone: function () {
+ return this.remove( ... this.children );
- return new this.constructor().copy( this );
+ }
- },
+ attach( object ) {
- copy: function ( triangle ) {
+ // adds object as a child of this, while maintaining the object's world transform
- this.a.copy( triangle.a );
- this.b.copy( triangle.b );
- this.c.copy( triangle.c );
+ // Note: This method does not support scene graphs having non-uniformly-scaled nodes(s)
- return this;
+ this.updateWorldMatrix( true, false );
- },
+ _m1$1.copy( this.matrixWorld ).invert();
- getArea: function () {
+ if ( object.parent !== null ) {
- _v0$1.subVectors( this.c, this.b );
- _v1$3.subVectors( this.a, this.b );
+ object.parent.updateWorldMatrix( true, false );
- return _v0$1.cross( _v1$3 ).length() * 0.5;
+ _m1$1.multiply( object.parent.matrixWorld );
- },
+ }
- getMidpoint: function ( target ) {
+ object.applyMatrix4( _m1$1 );
- if ( target === undefined ) {
+ this.add( object );
- console.warn( 'THREE.Triangle: .getMidpoint() target is now required' );
- target = new Vector3();
+ object.updateWorldMatrix( false, true );
- }
+ return this;
- return target.addVectors( this.a, this.b ).add( this.c ).multiplyScalar( 1 / 3 );
+ }
- },
+ getObjectById( id ) {
- getNormal: function ( target ) {
+ return this.getObjectByProperty( 'id', id );
- return Triangle.getNormal( this.a, this.b, this.c, target );
+ }
- },
+ getObjectByName( name ) {
- getPlane: function ( target ) {
+ return this.getObjectByProperty( 'name', name );
- if ( target === undefined ) {
+ }
- console.warn( 'THREE.Triangle: .getPlane() target is now required' );
- target = new Vector3();
+ getObjectByProperty( name, value ) {
- }
+ if ( this[ name ] === value ) return this;
- return target.setFromCoplanarPoints( this.a, this.b, this.c );
+ for ( let i = 0, l = this.children.length; i < l; i ++ ) {
- },
+ const child = this.children[ i ];
+ const object = child.getObjectByProperty( name, value );
- getBarycoord: function ( point, target ) {
+ if ( object !== undefined ) {
- return Triangle.getBarycoord( point, this.a, this.b, this.c, target );
+ return object;
- },
+ }
- getUV: function ( point, uv1, uv2, uv3, target ) {
+ }
- return Triangle.getUV( point, this.a, this.b, this.c, uv1, uv2, uv3, target );
+ return undefined;
- },
+ }
- containsPoint: function ( point ) {
+ getObjectsByProperty( name, value ) {
- return Triangle.containsPoint( point, this.a, this.b, this.c );
+ let result = [];
- },
+ if ( this[ name ] === value ) result.push( this );
- isFrontFacing: function ( direction ) {
+ for ( let i = 0, l = this.children.length; i < l; i ++ ) {
- return Triangle.isFrontFacing( this.a, this.b, this.c, direction );
+ const childResult = this.children[ i ].getObjectsByProperty( name, value );
- },
+ if ( childResult.length > 0 ) {
- intersectsBox: function ( box ) {
+ result = result.concat( childResult );
- return box.intersectsTriangle( this );
+ }
- },
+ }
- closestPointToPoint: function ( p, target ) {
+ return result;
- if ( target === undefined ) {
+ }
- console.warn( 'THREE.Triangle: .closestPointToPoint() target is now required' );
- target = new Vector3();
+ getWorldPosition( target ) {
- }
+ this.updateWorldMatrix( true, false );
- var a = this.a, b = this.b, c = this.c;
- var v, w;
+ return target.setFromMatrixPosition( this.matrixWorld );
- // algorithm thanks to Real-Time Collision Detection by Christer Ericson,
- // published by Morgan Kaufmann Publishers, (c) 2005 Elsevier Inc.,
- // under the accompanying license; see chapter 5.1.5 for detailed explanation.
- // basically, we're distinguishing which of the voronoi regions of the triangle
- // the point lies in with the minimum amount of redundant computation.
+ }
- _vab.subVectors( b, a );
- _vac.subVectors( c, a );
- _vap.subVectors( p, a );
- var d1 = _vab.dot( _vap );
- var d2 = _vac.dot( _vap );
- if ( d1 <= 0 && d2 <= 0 ) {
+ getWorldQuaternion( target ) {
- // vertex region of A; barycentric coords (1, 0, 0)
- return target.copy( a );
+ this.updateWorldMatrix( true, false );
- }
+ this.matrixWorld.decompose( _position$3, target, _scale$2 );
- _vbp.subVectors( p, b );
- var d3 = _vab.dot( _vbp );
- var d4 = _vac.dot( _vbp );
- if ( d3 >= 0 && d4 <= d3 ) {
+ return target;
- // vertex region of B; barycentric coords (0, 1, 0)
- return target.copy( b );
+ }
- }
+ getWorldScale( target ) {
- var vc = d1 * d4 - d3 * d2;
- if ( vc <= 0 && d1 >= 0 && d3 <= 0 ) {
+ this.updateWorldMatrix( true, false );
- v = d1 / ( d1 - d3 );
- // edge region of AB; barycentric coords (1-v, v, 0)
- return target.copy( a ).addScaledVector( _vab, v );
+ this.matrixWorld.decompose( _position$3, _quaternion$2, target );
- }
+ return target;
- _vcp.subVectors( p, c );
- var d5 = _vab.dot( _vcp );
- var d6 = _vac.dot( _vcp );
- if ( d6 >= 0 && d5 <= d6 ) {
+ }
- // vertex region of C; barycentric coords (0, 0, 1)
- return target.copy( c );
+ getWorldDirection( target ) {
- }
+ this.updateWorldMatrix( true, false );
- var vb = d5 * d2 - d1 * d6;
- if ( vb <= 0 && d2 >= 0 && d6 <= 0 ) {
+ const e = this.matrixWorld.elements;
- w = d2 / ( d2 - d6 );
- // edge region of AC; barycentric coords (1-w, 0, w)
- return target.copy( a ).addScaledVector( _vac, w );
+ return target.set( e[ 8 ], e[ 9 ], e[ 10 ] ).normalize();
- }
+ }
- var va = d3 * d6 - d5 * d4;
- if ( va <= 0 && ( d4 - d3 ) >= 0 && ( d5 - d6 ) >= 0 ) {
+ raycast( /* raycaster, intersects */ ) {}
- _vbc.subVectors( c, b );
- w = ( d4 - d3 ) / ( ( d4 - d3 ) + ( d5 - d6 ) );
- // edge region of BC; barycentric coords (0, 1-w, w)
- return target.copy( b ).addScaledVector( _vbc, w ); // edge region of BC
+ traverse( callback ) {
- }
+ callback( this );
- // face region
- var denom = 1 / ( va + vb + vc );
- // u = va * denom
- v = vb * denom;
- w = vc * denom;
+ const children = this.children;
- return target.copy( a ).addScaledVector( _vab, v ).addScaledVector( _vac, w );
+ for ( let i = 0, l = children.length; i < l; i ++ ) {
- },
+ children[ i ].traverse( callback );
- equals: function ( triangle ) {
+ }
- return triangle.a.equals( this.a ) && triangle.b.equals( this.b ) && triangle.c.equals( this.c );
+ }
- }
+ traverseVisible( callback ) {
- } );
+ if ( this.visible === false ) return;
- /**
- * @author mrdoob / http://mrdoob.com/
- */
+ callback( this );
- var _colorKeywords = { 'aliceblue': 0xF0F8FF, 'antiquewhite': 0xFAEBD7, 'aqua': 0x00FFFF, 'aquamarine': 0x7FFFD4, 'azure': 0xF0FFFF,
- 'beige': 0xF5F5DC, 'bisque': 0xFFE4C4, 'black': 0x000000, 'blanchedalmond': 0xFFEBCD, 'blue': 0x0000FF, 'blueviolet': 0x8A2BE2,
- 'brown': 0xA52A2A, 'burlywood': 0xDEB887, 'cadetblue': 0x5F9EA0, 'chartreuse': 0x7FFF00, 'chocolate': 0xD2691E, 'coral': 0xFF7F50,
- 'cornflowerblue': 0x6495ED, 'cornsilk': 0xFFF8DC, 'crimson': 0xDC143C, 'cyan': 0x00FFFF, 'darkblue': 0x00008B, 'darkcyan': 0x008B8B,
- 'darkgoldenrod': 0xB8860B, 'darkgray': 0xA9A9A9, 'darkgreen': 0x006400, 'darkgrey': 0xA9A9A9, 'darkkhaki': 0xBDB76B, 'darkmagenta': 0x8B008B,
- 'darkolivegreen': 0x556B2F, 'darkorange': 0xFF8C00, 'darkorchid': 0x9932CC, 'darkred': 0x8B0000, 'darksalmon': 0xE9967A, 'darkseagreen': 0x8FBC8F,
- 'darkslateblue': 0x483D8B, 'darkslategray': 0x2F4F4F, 'darkslategrey': 0x2F4F4F, 'darkturquoise': 0x00CED1, 'darkviolet': 0x9400D3,
- 'deeppink': 0xFF1493, 'deepskyblue': 0x00BFFF, 'dimgray': 0x696969, 'dimgrey': 0x696969, 'dodgerblue': 0x1E90FF, 'firebrick': 0xB22222,
- 'floralwhite': 0xFFFAF0, 'forestgreen': 0x228B22, 'fuchsia': 0xFF00FF, 'gainsboro': 0xDCDCDC, 'ghostwhite': 0xF8F8FF, 'gold': 0xFFD700,
- 'goldenrod': 0xDAA520, 'gray': 0x808080, 'green': 0x008000, 'greenyellow': 0xADFF2F, 'grey': 0x808080, 'honeydew': 0xF0FFF0, 'hotpink': 0xFF69B4,
- 'indianred': 0xCD5C5C, 'indigo': 0x4B0082, 'ivory': 0xFFFFF0, 'khaki': 0xF0E68C, 'lavender': 0xE6E6FA, 'lavenderblush': 0xFFF0F5, 'lawngreen': 0x7CFC00,
- 'lemonchiffon': 0xFFFACD, 'lightblue': 0xADD8E6, 'lightcoral': 0xF08080, 'lightcyan': 0xE0FFFF, 'lightgoldenrodyellow': 0xFAFAD2, 'lightgray': 0xD3D3D3,
- 'lightgreen': 0x90EE90, 'lightgrey': 0xD3D3D3, 'lightpink': 0xFFB6C1, 'lightsalmon': 0xFFA07A, 'lightseagreen': 0x20B2AA, 'lightskyblue': 0x87CEFA,
- 'lightslategray': 0x778899, 'lightslategrey': 0x778899, 'lightsteelblue': 0xB0C4DE, 'lightyellow': 0xFFFFE0, 'lime': 0x00FF00, 'limegreen': 0x32CD32,
- 'linen': 0xFAF0E6, 'magenta': 0xFF00FF, 'maroon': 0x800000, 'mediumaquamarine': 0x66CDAA, 'mediumblue': 0x0000CD, 'mediumorchid': 0xBA55D3,
- 'mediumpurple': 0x9370DB, 'mediumseagreen': 0x3CB371, 'mediumslateblue': 0x7B68EE, 'mediumspringgreen': 0x00FA9A, 'mediumturquoise': 0x48D1CC,
- 'mediumvioletred': 0xC71585, 'midnightblue': 0x191970, 'mintcream': 0xF5FFFA, 'mistyrose': 0xFFE4E1, 'moccasin': 0xFFE4B5, 'navajowhite': 0xFFDEAD,
- 'navy': 0x000080, 'oldlace': 0xFDF5E6, 'olive': 0x808000, 'olivedrab': 0x6B8E23, 'orange': 0xFFA500, 'orangered': 0xFF4500, 'orchid': 0xDA70D6,
- 'palegoldenrod': 0xEEE8AA, 'palegreen': 0x98FB98, 'paleturquoise': 0xAFEEEE, 'palevioletred': 0xDB7093, 'papayawhip': 0xFFEFD5, 'peachpuff': 0xFFDAB9,
- 'peru': 0xCD853F, 'pink': 0xFFC0CB, 'plum': 0xDDA0DD, 'powderblue': 0xB0E0E6, 'purple': 0x800080, 'rebeccapurple': 0x663399, 'red': 0xFF0000, 'rosybrown': 0xBC8F8F,
- 'royalblue': 0x4169E1, 'saddlebrown': 0x8B4513, 'salmon': 0xFA8072, 'sandybrown': 0xF4A460, 'seagreen': 0x2E8B57, 'seashell': 0xFFF5EE,
- 'sienna': 0xA0522D, 'silver': 0xC0C0C0, 'skyblue': 0x87CEEB, 'slateblue': 0x6A5ACD, 'slategray': 0x708090, 'slategrey': 0x708090, 'snow': 0xFFFAFA,
- 'springgreen': 0x00FF7F, 'steelblue': 0x4682B4, 'tan': 0xD2B48C, 'teal': 0x008080, 'thistle': 0xD8BFD8, 'tomato': 0xFF6347, 'turquoise': 0x40E0D0,
- 'violet': 0xEE82EE, 'wheat': 0xF5DEB3, 'white': 0xFFFFFF, 'whitesmoke': 0xF5F5F5, 'yellow': 0xFFFF00, 'yellowgreen': 0x9ACD32 };
-
- var _hslA = { h: 0, s: 0, l: 0 };
- var _hslB = { h: 0, s: 0, l: 0 };
-
- function Color( r, g, b ) {
+ const children = this.children;
- if ( g === undefined && b === undefined ) {
+ for ( let i = 0, l = children.length; i < l; i ++ ) {
- // r is THREE.Color, hex or string
- return this.set( r );
+ children[ i ].traverseVisible( callback );
}
- return this.setRGB( r, g, b );
-
}
- function hue2rgb( p, q, t ) {
+ traverseAncestors( callback ) {
- if ( t < 0 ) t += 1;
- if ( t > 1 ) t -= 1;
- if ( t < 1 / 6 ) return p + ( q - p ) * 6 * t;
- if ( t < 1 / 2 ) return q;
- if ( t < 2 / 3 ) return p + ( q - p ) * 6 * ( 2 / 3 - t );
- return p;
+ const parent = this.parent;
- }
-
- function SRGBToLinear( c ) {
+ if ( parent !== null ) {
- return ( c < 0.04045 ) ? c * 0.0773993808 : Math.pow( c * 0.9478672986 + 0.0521327014, 2.4 );
-
- }
+ callback( parent );
- function LinearToSRGB( c ) {
+ parent.traverseAncestors( callback );
- return ( c < 0.0031308 ) ? c * 12.92 : 1.055 * ( Math.pow( c, 0.41666 ) ) - 0.055;
+ }
}
- Object.assign( Color.prototype, {
+ updateMatrix() {
- isColor: true,
+ this.matrix.compose( this.position, this.quaternion, this.scale );
- r: 1, g: 1, b: 1,
+ this.matrixWorldNeedsUpdate = true;
- set: function ( value ) {
+ }
- if ( value && value.isColor ) {
+ updateMatrixWorld( force ) {
- this.copy( value );
+ if ( this.matrixAutoUpdate ) this.updateMatrix();
- } else if ( typeof value === 'number' ) {
+ if ( this.matrixWorldNeedsUpdate || force ) {
- this.setHex( value );
+ if ( this.parent === null ) {
- } else if ( typeof value === 'string' ) {
+ this.matrixWorld.copy( this.matrix );
- this.setStyle( value );
+ } else {
+
+ this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );
}
- return this;
+ this.matrixWorldNeedsUpdate = false;
- },
+ force = true;
- setScalar: function ( scalar ) {
+ }
- this.r = scalar;
- this.g = scalar;
- this.b = scalar;
+ // update children
- return this;
+ const children = this.children;
- },
+ for ( let i = 0, l = children.length; i < l; i ++ ) {
- setHex: function ( hex ) {
+ const child = children[ i ];
- hex = Math.floor( hex );
+ if ( child.matrixWorldAutoUpdate === true || force === true ) {
- this.r = ( hex >> 16 & 255 ) / 255;
- this.g = ( hex >> 8 & 255 ) / 255;
- this.b = ( hex & 255 ) / 255;
+ child.updateMatrixWorld( force );
- return this;
+ }
- },
+ }
- setRGB: function ( r, g, b ) {
+ }
- this.r = r;
- this.g = g;
- this.b = b;
+ updateWorldMatrix( updateParents, updateChildren ) {
- return this;
+ const parent = this.parent;
- },
+ if ( updateParents === true && parent !== null && parent.matrixWorldAutoUpdate === true ) {
- setHSL: function ( h, s, l ) {
+ parent.updateWorldMatrix( true, false );
- // h,s,l ranges are in 0.0 - 1.0
- h = _Math.euclideanModulo( h, 1 );
- s = _Math.clamp( s, 0, 1 );
- l = _Math.clamp( l, 0, 1 );
+ }
- if ( s === 0 ) {
+ if ( this.matrixAutoUpdate ) this.updateMatrix();
- this.r = this.g = this.b = l;
+ if ( this.parent === null ) {
- } else {
+ this.matrixWorld.copy( this.matrix );
- var p = l <= 0.5 ? l * ( 1 + s ) : l + s - ( l * s );
- var q = ( 2 * l ) - p;
+ } else {
- this.r = hue2rgb( q, p, h + 1 / 3 );
- this.g = hue2rgb( q, p, h );
- this.b = hue2rgb( q, p, h - 1 / 3 );
+ this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );
- }
+ }
- return this;
+ // update children
- },
+ if ( updateChildren === true ) {
- setStyle: function ( style ) {
+ const children = this.children;
- function handleAlpha( string ) {
+ for ( let i = 0, l = children.length; i < l; i ++ ) {
- if ( string === undefined ) return;
+ const child = children[ i ];
- if ( parseFloat( string ) < 1 ) {
+ if ( child.matrixWorldAutoUpdate === true ) {
- console.warn( 'THREE.Color: Alpha component of ' + style + ' will be ignored.' );
+ child.updateWorldMatrix( false, true );
}
}
+ }
- var m;
+ }
- if ( m = /^((?:rgb|hsl)a?)\(\s*([^\)]*)\)/.exec( style ) ) {
+ toJSON( meta ) {
- // rgb / hsl
+ // meta is a string when called from JSON.stringify
+ const isRootObject = ( meta === undefined || typeof meta === 'string' );
- var color;
- var name = m[ 1 ];
- var components = m[ 2 ];
+ const output = {};
- switch ( name ) {
+ // meta is a hash used to collect geometries, materials.
+ // not providing it implies that this is the root object
+ // being serialized.
+ if ( isRootObject ) {
- case 'rgb':
- case 'rgba':
+ // initialize meta obj
+ meta = {
+ geometries: {},
+ materials: {},
+ textures: {},
+ images: {},
+ shapes: {},
+ skeletons: {},
+ animations: {},
+ nodes: {}
+ };
- if ( color = /^(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec( components ) ) {
+ output.metadata = {
+ version: 4.6,
+ type: 'Object',
+ generator: 'Object3D.toJSON'
+ };
- // 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 ] );
+ // standard Object3D serialization
- return this;
+ const object = {};
- }
+ object.uuid = this.uuid;
+ object.type = this.type;
- if ( color = /^(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec( components ) ) {
+ if ( this.name !== '' ) object.name = this.name;
+ if ( this.castShadow === true ) object.castShadow = true;
+ if ( this.receiveShadow === true ) object.receiveShadow = true;
+ if ( this.visible === false ) object.visible = false;
+ if ( this.frustumCulled === false ) object.frustumCulled = false;
+ if ( this.renderOrder !== 0 ) object.renderOrder = this.renderOrder;
+ if ( Object.keys( this.userData ).length > 0 ) object.userData = this.userData;
- // 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;
+ object.layers = this.layers.mask;
+ object.matrix = this.matrix.toArray();
+ object.up = this.up.toArray();
- handleAlpha( color[ 5 ] );
+ if ( this.matrixAutoUpdate === false ) object.matrixAutoUpdate = false;
- return this;
+ // object specific properties
- }
+ if ( this.isInstancedMesh ) {
- break;
+ object.type = 'InstancedMesh';
+ object.count = this.count;
+ object.instanceMatrix = this.instanceMatrix.toJSON();
+ if ( this.instanceColor !== null ) object.instanceColor = this.instanceColor.toJSON();
- 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 ) ) {
+ //
- // 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;
+ function serialize( library, element ) {
- handleAlpha( color[ 5 ] );
+ if ( library[ element.uuid ] === undefined ) {
- return this.setHSL( h, s, l );
+ library[ element.uuid ] = element.toJSON( meta );
- }
+ }
- break;
+ return element.uuid;
- }
+ }
- } else if ( m = /^\#([A-Fa-f0-9]+)$/.exec( style ) ) {
+ if ( this.isScene ) {
- // hex color
+ if ( this.background ) {
- var hex = m[ 1 ];
- var size = hex.length;
+ if ( this.background.isColor ) {
- if ( size === 3 ) {
+ object.background = this.background.toJSON();
- // #ff0
- this.r = parseInt( hex.charAt( 0 ) + hex.charAt( 0 ), 16 ) / 255;
- this.g = parseInt( hex.charAt( 1 ) + hex.charAt( 1 ), 16 ) / 255;
- this.b = parseInt( hex.charAt( 2 ) + hex.charAt( 2 ), 16 ) / 255;
+ } else if ( this.background.isTexture ) {
- return this;
+ object.background = this.background.toJSON( meta ).uuid;
- } else if ( size === 6 ) {
+ }
- // #ff0000
- this.r = parseInt( hex.charAt( 0 ) + hex.charAt( 1 ), 16 ) / 255;
- this.g = parseInt( hex.charAt( 2 ) + hex.charAt( 3 ), 16 ) / 255;
- this.b = parseInt( hex.charAt( 4 ) + hex.charAt( 5 ), 16 ) / 255;
+ }
- return this;
+ if ( this.environment && this.environment.isTexture && this.environment.isRenderTargetTexture !== true ) {
- }
+ object.environment = this.environment.toJSON( meta ).uuid;
}
- if ( style && style.length > 0 ) {
+ } else if ( this.isMesh || this.isLine || this.isPoints ) {
+
+ object.geometry = serialize( meta.geometries, this.geometry );
+
+ const parameters = this.geometry.parameters;
- // color keywords
- var hex = _colorKeywords[ style ];
+ if ( parameters !== undefined && parameters.shapes !== undefined ) {
- if ( hex !== undefined ) {
+ const shapes = parameters.shapes;
- // red
- this.setHex( hex );
+ if ( Array.isArray( shapes ) ) {
+
+ for ( let i = 0, l = shapes.length; i < l; i ++ ) {
+
+ const shape = shapes[ i ];
+
+ serialize( meta.shapes, shape );
+
+ }
} else {
- // unknown color
- console.warn( 'THREE.Color: Unknown color ' + style );
+ serialize( meta.shapes, shapes );
}
}
- return this;
+ }
- },
+ if ( this.isSkinnedMesh ) {
- clone: function () {
+ object.bindMode = this.bindMode;
+ object.bindMatrix = this.bindMatrix.toArray();
- return new this.constructor( this.r, this.g, this.b );
+ if ( this.skeleton !== undefined ) {
- },
+ serialize( meta.skeletons, this.skeleton );
- copy: function ( color ) {
+ object.skeleton = this.skeleton.uuid;
- this.r = color.r;
- this.g = color.g;
- this.b = color.b;
+ }
- return this;
+ }
- },
+ if ( this.material !== undefined ) {
- copyGammaToLinear: function ( color, gammaFactor ) {
+ if ( Array.isArray( this.material ) ) {
- if ( gammaFactor === undefined ) gammaFactor = 2.0;
+ const uuids = [];
- this.r = Math.pow( color.r, gammaFactor );
- this.g = Math.pow( color.g, gammaFactor );
- this.b = Math.pow( color.b, gammaFactor );
+ for ( let i = 0, l = this.material.length; i < l; i ++ ) {
- return this;
+ uuids.push( serialize( meta.materials, this.material[ i ] ) );
- },
+ }
- copyLinearToGamma: function ( color, gammaFactor ) {
+ object.material = uuids;
- if ( gammaFactor === undefined ) gammaFactor = 2.0;
+ } else {
- var safeInverse = ( gammaFactor > 0 ) ? ( 1.0 / gammaFactor ) : 1.0;
+ object.material = serialize( meta.materials, this.material );
- this.r = Math.pow( color.r, safeInverse );
- this.g = Math.pow( color.g, safeInverse );
- this.b = Math.pow( color.b, safeInverse );
+ }
- return this;
+ }
- },
+ //
- convertGammaToLinear: function ( gammaFactor ) {
+ if ( this.children.length > 0 ) {
- this.copyGammaToLinear( this, gammaFactor );
+ object.children = [];
- return this;
+ for ( let i = 0; i < this.children.length; i ++ ) {
- },
+ object.children.push( this.children[ i ].toJSON( meta ).object );
- convertLinearToGamma: function ( gammaFactor ) {
+ }
- this.copyLinearToGamma( this, gammaFactor );
+ }
- return this;
+ //
- },
+ if ( this.animations.length > 0 ) {
- copySRGBToLinear: function ( color ) {
+ object.animations = [];
- this.r = SRGBToLinear( color.r );
- this.g = SRGBToLinear( color.g );
- this.b = SRGBToLinear( color.b );
+ for ( let i = 0; i < this.animations.length; i ++ ) {
- return this;
+ const animation = this.animations[ i ];
- },
+ object.animations.push( serialize( meta.animations, animation ) );
- copyLinearToSRGB: function ( color ) {
+ }
- this.r = LinearToSRGB( color.r );
- this.g = LinearToSRGB( color.g );
- this.b = LinearToSRGB( color.b );
+ }
- return this;
+ if ( isRootObject ) {
- },
+ const geometries = extractFromCache( meta.geometries );
+ const materials = extractFromCache( meta.materials );
+ const textures = extractFromCache( meta.textures );
+ const images = extractFromCache( meta.images );
+ const shapes = extractFromCache( meta.shapes );
+ const skeletons = extractFromCache( meta.skeletons );
+ const animations = extractFromCache( meta.animations );
+ const nodes = extractFromCache( meta.nodes );
- convertSRGBToLinear: function () {
+ if ( geometries.length > 0 ) output.geometries = geometries;
+ if ( materials.length > 0 ) output.materials = materials;
+ if ( textures.length > 0 ) output.textures = textures;
+ if ( images.length > 0 ) output.images = images;
+ if ( shapes.length > 0 ) output.shapes = shapes;
+ if ( skeletons.length > 0 ) output.skeletons = skeletons;
+ if ( animations.length > 0 ) output.animations = animations;
+ if ( nodes.length > 0 ) output.nodes = nodes;
- this.copySRGBToLinear( this );
+ }
- return this;
+ output.object = object;
- },
+ return output;
- convertLinearToSRGB: function () {
+ // extract data from the cache hash
+ // remove metadata on each item
+ // and return as array
+ function extractFromCache( cache ) {
- this.copyLinearToSRGB( this );
+ const values = [];
+ for ( const key in cache ) {
- return this;
+ const data = cache[ key ];
+ delete data.metadata;
+ values.push( data );
- },
+ }
- getHex: function () {
+ return values;
- return ( this.r * 255 ) << 16 ^ ( this.g * 255 ) << 8 ^ ( this.b * 255 ) << 0;
+ }
- },
+ }
- getHexString: function () {
+ clone( recursive ) {
- return ( '000000' + this.getHex().toString( 16 ) ).slice( - 6 );
+ return new this.constructor().copy( this, recursive );
- },
+ }
+
+ copy( source, recursive = true ) {
+
+ this.name = source.name;
+
+ this.up.copy( source.up );
+
+ this.position.copy( source.position );
+ this.rotation.order = source.rotation.order;
+ this.quaternion.copy( source.quaternion );
+ this.scale.copy( source.scale );
+
+ this.matrix.copy( source.matrix );
+ this.matrixWorld.copy( source.matrixWorld );
+
+ this.matrixAutoUpdate = source.matrixAutoUpdate;
+ this.matrixWorldNeedsUpdate = source.matrixWorldNeedsUpdate;
+
+ this.matrixWorldAutoUpdate = source.matrixWorldAutoUpdate;
+
+ this.layers.mask = source.layers.mask;
+ this.visible = source.visible;
+
+ this.castShadow = source.castShadow;
+ this.receiveShadow = source.receiveShadow;
+
+ this.frustumCulled = source.frustumCulled;
+ this.renderOrder = source.renderOrder;
- getHSL: function ( target ) {
+ this.animations = source.animations.slice();
- // h,s,l ranges are in 0.0 - 1.0
+ this.userData = JSON.parse( JSON.stringify( source.userData ) );
- if ( target === undefined ) {
+ if ( recursive === true ) {
+
+ for ( let i = 0; i < source.children.length; i ++ ) {
- console.warn( 'THREE.Color: .getHSL() target is now required' );
- target = { h: 0, s: 0, l: 0 };
+ const child = source.children[ i ];
+ this.add( child.clone() );
}
- var r = this.r, g = this.g, b = this.b;
+ }
- var max = Math.max( r, g, b );
- var min = Math.min( r, g, b );
+ return this;
- var hue, saturation;
- var lightness = ( min + max ) / 2.0;
+ }
- if ( min === max ) {
+}
- hue = 0;
- saturation = 0;
+Object3D.DEFAULT_UP = /*@__PURE__*/ new Vector3( 0, 1, 0 );
+Object3D.DEFAULT_MATRIX_AUTO_UPDATE = true;
+Object3D.DEFAULT_MATRIX_WORLD_AUTO_UPDATE = true;
- } else {
+const _v0$1 = /*@__PURE__*/ new Vector3();
+const _v1$3 = /*@__PURE__*/ new Vector3();
+const _v2$2 = /*@__PURE__*/ new Vector3();
+const _v3$1 = /*@__PURE__*/ new Vector3();
- var delta = max - min;
+const _vab = /*@__PURE__*/ new Vector3();
+const _vac = /*@__PURE__*/ new Vector3();
+const _vbc = /*@__PURE__*/ new Vector3();
+const _vap = /*@__PURE__*/ new Vector3();
+const _vbp = /*@__PURE__*/ new Vector3();
+const _vcp = /*@__PURE__*/ new Vector3();
- saturation = lightness <= 0.5 ? delta / ( max + min ) : delta / ( 2 - max - min );
+let warnedGetUV = false;
- switch ( max ) {
+class Triangle {
- case r: hue = ( g - b ) / delta + ( g < b ? 6 : 0 ); break;
- case g: hue = ( b - r ) / delta + 2; break;
- case b: hue = ( r - g ) / delta + 4; break;
+ constructor( a = new Vector3(), b = new Vector3(), c = new Vector3() ) {
- }
+ this.a = a;
+ this.b = b;
+ this.c = c;
- hue /= 6;
+ }
- }
+ static getNormal( a, b, c, target ) {
- target.h = hue;
- target.s = saturation;
- target.l = lightness;
+ target.subVectors( c, b );
+ _v0$1.subVectors( a, b );
+ target.cross( _v0$1 );
- return target;
+ const targetLengthSq = target.lengthSq();
+ if ( targetLengthSq > 0 ) {
- },
+ return target.multiplyScalar( 1 / Math.sqrt( targetLengthSq ) );
- getStyle: function () {
+ }
- return 'rgb(' + ( ( this.r * 255 ) | 0 ) + ',' + ( ( this.g * 255 ) | 0 ) + ',' + ( ( this.b * 255 ) | 0 ) + ')';
+ return target.set( 0, 0, 0 );
- },
+ }
- offsetHSL: function ( h, s, l ) {
+ // static/instance method to calculate barycentric coordinates
+ // based on: http://www.blackpawn.com/texts/pointinpoly/default.html
+ static getBarycoord( point, a, b, c, target ) {
- this.getHSL( _hslA );
+ _v0$1.subVectors( c, a );
+ _v1$3.subVectors( b, a );
+ _v2$2.subVectors( point, a );
- _hslA.h += h; _hslA.s += s; _hslA.l += l;
+ const dot00 = _v0$1.dot( _v0$1 );
+ const dot01 = _v0$1.dot( _v1$3 );
+ const dot02 = _v0$1.dot( _v2$2 );
+ const dot11 = _v1$3.dot( _v1$3 );
+ const dot12 = _v1$3.dot( _v2$2 );
- this.setHSL( _hslA.h, _hslA.s, _hslA.l );
+ const denom = ( dot00 * dot11 - dot01 * dot01 );
- return this;
+ // collinear or singular triangle
+ if ( denom === 0 ) {
- },
+ // arbitrary location outside of triangle?
+ // not sure if this is the best idea, maybe should be returning undefined
+ return target.set( - 2, - 1, - 1 );
- add: function ( color ) {
+ }
- this.r += color.r;
- this.g += color.g;
- this.b += color.b;
+ const invDenom = 1 / denom;
+ const u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom;
+ const v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom;
- return this;
+ // barycentric coordinates must always sum to 1
+ return target.set( 1 - u - v, v, u );
- },
+ }
- addColors: function ( color1, color2 ) {
+ static containsPoint( point, a, b, c ) {
- this.r = color1.r + color2.r;
- this.g = color1.g + color2.g;
- this.b = color1.b + color2.b;
+ this.getBarycoord( point, a, b, c, _v3$1 );
- return this;
+ return ( _v3$1.x >= 0 ) && ( _v3$1.y >= 0 ) && ( ( _v3$1.x + _v3$1.y ) <= 1 );
- },
+ }
- addScalar: function ( s ) {
+ static getUV( point, p1, p2, p3, uv1, uv2, uv3, target ) { // @deprecated, r151
- this.r += s;
- this.g += s;
- this.b += s;
+ if ( warnedGetUV === false ) {
- return this;
+ console.warn( 'THREE.Triangle.getUV() has been renamed to THREE.Triangle.getInterpolation().' );
- },
+ warnedGetUV = true;
- sub: function ( color ) {
+ }
- this.r = Math.max( 0, this.r - color.r );
- this.g = Math.max( 0, this.g - color.g );
- this.b = Math.max( 0, this.b - color.b );
+ return this.getInterpolation( point, p1, p2, p3, uv1, uv2, uv3, target );
- return this;
+ }
- },
+ static getInterpolation( point, p1, p2, p3, v1, v2, v3, target ) {
- multiply: function ( color ) {
+ this.getBarycoord( point, p1, p2, p3, _v3$1 );
- this.r *= color.r;
- this.g *= color.g;
- this.b *= color.b;
+ target.setScalar( 0 );
+ target.addScaledVector( v1, _v3$1.x );
+ target.addScaledVector( v2, _v3$1.y );
+ target.addScaledVector( v3, _v3$1.z );
- return this;
+ return target;
- },
+ }
- multiplyScalar: function ( s ) {
+ static isFrontFacing( a, b, c, direction ) {
- this.r *= s;
- this.g *= s;
- this.b *= s;
+ _v0$1.subVectors( c, b );
+ _v1$3.subVectors( a, b );
- return this;
+ // strictly front facing
+ return ( _v0$1.cross( _v1$3 ).dot( direction ) < 0 ) ? true : false;
- },
+ }
- lerp: function ( color, alpha ) {
+ set( a, b, c ) {
- this.r += ( color.r - this.r ) * alpha;
- this.g += ( color.g - this.g ) * alpha;
- this.b += ( color.b - this.b ) * alpha;
+ this.a.copy( a );
+ this.b.copy( b );
+ this.c.copy( c );
- return this;
+ return this;
- },
+ }
- lerpHSL: function ( color, alpha ) {
+ setFromPointsAndIndices( points, i0, i1, i2 ) {
- this.getHSL( _hslA );
- color.getHSL( _hslB );
+ this.a.copy( points[ i0 ] );
+ this.b.copy( points[ i1 ] );
+ this.c.copy( points[ i2 ] );
+
+ return this;
- var h = _Math.lerp( _hslA.h, _hslB.h, alpha );
- var s = _Math.lerp( _hslA.s, _hslB.s, alpha );
- var l = _Math.lerp( _hslA.l, _hslB.l, alpha );
+ }
- this.setHSL( h, s, l );
+ setFromAttributeAndIndices( attribute, i0, i1, i2 ) {
- return this;
+ this.a.fromBufferAttribute( attribute, i0 );
+ this.b.fromBufferAttribute( attribute, i1 );
+ this.c.fromBufferAttribute( attribute, i2 );
- },
+ return this;
- equals: function ( c ) {
+ }
- return ( c.r === this.r ) && ( c.g === this.g ) && ( c.b === this.b );
+ clone() {
- },
+ return new this.constructor().copy( this );
- fromArray: function ( array, offset ) {
+ }
- if ( offset === undefined ) offset = 0;
+ copy( triangle ) {
- this.r = array[ offset ];
- this.g = array[ offset + 1 ];
- this.b = array[ offset + 2 ];
+ this.a.copy( triangle.a );
+ this.b.copy( triangle.b );
+ this.c.copy( triangle.c );
- return this;
+ return this;
- },
+ }
- toArray: function ( array, offset ) {
+ getArea() {
- if ( array === undefined ) array = [];
- if ( offset === undefined ) offset = 0;
+ _v0$1.subVectors( this.c, this.b );
+ _v1$3.subVectors( this.a, this.b );
- array[ offset ] = this.r;
- array[ offset + 1 ] = this.g;
- array[ offset + 2 ] = this.b;
+ return _v0$1.cross( _v1$3 ).length() * 0.5;
- return array;
+ }
- },
+ getMidpoint( target ) {
+
+ return target.addVectors( this.a, this.b ).add( this.c ).multiplyScalar( 1 / 3 );
+
+ }
+
+ getNormal( target ) {
+
+ return Triangle.getNormal( this.a, this.b, this.c, target );
+
+ }
+
+ getPlane( target ) {
+
+ return target.setFromCoplanarPoints( this.a, this.b, this.c );
+
+ }
+
+ getBarycoord( point, target ) {
+
+ return Triangle.getBarycoord( point, this.a, this.b, this.c, target );
+
+ }
+
+ getUV( point, uv1, uv2, uv3, target ) { // @deprecated, r151
- toJSON: function () {
+ if ( warnedGetUV === false ) {
- return this.getHex();
+ console.warn( 'THREE.Triangle.getUV() has been renamed to THREE.Triangle.getInterpolation().' );
+
+ warnedGetUV = true;
}
- } );
+ return Triangle.getInterpolation( point, this.a, this.b, this.c, uv1, uv2, uv3, target );
- /**
- * @author mrdoob / http://mrdoob.com/
- * @author alteredq / http://alteredqualia.com/
- */
+ }
- function Face3( a, b, c, normal, color, materialIndex ) {
+ getInterpolation( point, v1, v2, v3, target ) {
- this.a = a;
- this.b = b;
- this.c = c;
+ return Triangle.getInterpolation( point, this.a, this.b, this.c, v1, v2, v3, target );
- this.normal = ( normal && normal.isVector3 ) ? normal : new Vector3();
- this.vertexNormals = Array.isArray( normal ) ? normal : [];
+ }
- this.color = ( color && color.isColor ) ? color : new Color();
- this.vertexColors = Array.isArray( color ) ? color : [];
+ containsPoint( point ) {
- this.materialIndex = materialIndex !== undefined ? materialIndex : 0;
+ return Triangle.containsPoint( point, this.a, this.b, this.c );
}
- Object.assign( Face3.prototype, {
+ isFrontFacing( direction ) {
+
+ return Triangle.isFrontFacing( this.a, this.b, this.c, direction );
- clone: function () {
+ }
- return new this.constructor().copy( this );
+ intersectsBox( box ) {
- },
+ return box.intersectsTriangle( this );
- copy: function ( source ) {
+ }
- this.a = source.a;
- this.b = source.b;
- this.c = source.c;
+ closestPointToPoint( p, target ) {
- this.normal.copy( source.normal );
- this.color.copy( source.color );
+ const a = this.a, b = this.b, c = this.c;
+ let v, w;
- this.materialIndex = source.materialIndex;
+ // algorithm thanks to Real-Time Collision Detection by Christer Ericson,
+ // published by Morgan Kaufmann Publishers, (c) 2005 Elsevier Inc.,
+ // under the accompanying license; see chapter 5.1.5 for detailed explanation.
+ // basically, we're distinguishing which of the voronoi regions of the triangle
+ // the point lies in with the minimum amount of redundant computation.
- for ( var i = 0, il = source.vertexNormals.length; i < il; i ++ ) {
+ _vab.subVectors( b, a );
+ _vac.subVectors( c, a );
+ _vap.subVectors( p, a );
+ const d1 = _vab.dot( _vap );
+ const d2 = _vac.dot( _vap );
+ if ( d1 <= 0 && d2 <= 0 ) {
- this.vertexNormals[ i ] = source.vertexNormals[ i ].clone();
+ // vertex region of A; barycentric coords (1, 0, 0)
+ return target.copy( a );
- }
+ }
- for ( var i = 0, il = source.vertexColors.length; i < il; i ++ ) {
+ _vbp.subVectors( p, b );
+ const d3 = _vab.dot( _vbp );
+ const d4 = _vac.dot( _vbp );
+ if ( d3 >= 0 && d4 <= d3 ) {
- this.vertexColors[ i ] = source.vertexColors[ i ].clone();
+ // vertex region of B; barycentric coords (0, 1, 0)
+ return target.copy( b );
- }
+ }
- return this;
+ const vc = d1 * d4 - d3 * d2;
+ if ( vc <= 0 && d1 >= 0 && d3 <= 0 ) {
+
+ v = d1 / ( d1 - d3 );
+ // edge region of AB; barycentric coords (1-v, v, 0)
+ return target.copy( a ).addScaledVector( _vab, v );
}
- } );
+ _vcp.subVectors( p, c );
+ const d5 = _vab.dot( _vcp );
+ const d6 = _vac.dot( _vcp );
+ if ( d6 >= 0 && d5 <= d6 ) {
- /**
- * @author mrdoob / http://mrdoob.com/
- * @author alteredq / http://alteredqualia.com/
- */
+ // vertex region of C; barycentric coords (0, 0, 1)
+ return target.copy( c );
- var materialId = 0;
+ }
+
+ const vb = d5 * d2 - d1 * d6;
+ if ( vb <= 0 && d2 >= 0 && d6 <= 0 ) {
+
+ w = d2 / ( d2 - d6 );
+ // edge region of AC; barycentric coords (1-w, 0, w)
+ return target.copy( a ).addScaledVector( _vac, w );
+
+ }
+
+ const va = d3 * d6 - d5 * d4;
+ if ( va <= 0 && ( d4 - d3 ) >= 0 && ( d5 - d6 ) >= 0 ) {
+
+ _vbc.subVectors( c, b );
+ w = ( d4 - d3 ) / ( ( d4 - d3 ) + ( d5 - d6 ) );
+ // edge region of BC; barycentric coords (0, 1-w, w)
+ return target.copy( b ).addScaledVector( _vbc, w ); // edge region of BC
+
+ }
+
+ // face region
+ const denom = 1 / ( va + vb + vc );
+ // u = va * denom
+ v = vb * denom;
+ w = vc * denom;
+
+ return target.copy( a ).addScaledVector( _vab, v ).addScaledVector( _vac, w );
+
+ }
+
+ equals( triangle ) {
+
+ return triangle.a.equals( this.a ) && triangle.b.equals( this.b ) && triangle.c.equals( this.c );
+
+ }
+
+}
+
+let _materialId = 0;
+
+class Material extends EventDispatcher {
- function Material() {
+ constructor() {
- Object.defineProperty( this, 'id', { value: materialId ++ } );
+ super();
- this.uuid = _Math.generateUUID();
+ this.isMaterial = true;
+
+ Object.defineProperty( this, 'id', { value: _materialId ++ } );
+
+ this.uuid = generateUUID();
this.name = '';
this.type = 'Material';
- this.fog = true;
- this.lights = true;
-
this.blending = NormalBlending;
this.side = FrontSide;
- this.flatShading = false;
- this.vertexTangents = false;
- this.vertexColors = NoColors; // THREE.NoColors, THREE.VertexColors, THREE.FaceColors
+ this.vertexColors = false;
this.opacity = 1;
this.transparent = false;
+ this.alphaHash = false;
this.blendSrc = SrcAlphaFactor;
this.blendDst = OneMinusSrcAlphaFactor;
@@ -8330,9 +8457,10 @@
this.depthTest = true;
this.depthWrite = true;
+ this.stencilWriteMask = 0xff;
this.stencilFunc = AlwaysStencilFunc;
this.stencilRef = 0;
- this.stencilMask = 0xff;
+ this.stencilFuncMask = 0xff;
this.stencilFail = KeepStencilOp;
this.stencilZFail = KeepStencilOp;
this.stencilZPass = KeepStencilOp;
@@ -8354,8 +8482,9 @@
this.dithering = false;
- this.alphaTest = 0;
+ this.alphaToCoverage = false;
this.premultipliedAlpha = false;
+ this.forceSinglePass = false;
this.visible = true;
@@ -8363,15825 +8492,16226 @@
this.userData = {};
- this.needsUpdate = true;
+ this.version = 0;
+
+ this._alphaTest = 0;
}
- Material.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
+ get alphaTest() {
- constructor: Material,
+ return this._alphaTest;
- isMaterial: true,
+ }
- onBeforeCompile: function () {},
+ set alphaTest( value ) {
- setValues: function ( values ) {
+ if ( this._alphaTest > 0 !== value > 0 ) {
- if ( values === undefined ) return;
+ this.version ++;
- for ( var key in values ) {
+ }
- var newValue = values[ key ];
+ this._alphaTest = value;
- if ( newValue === undefined ) {
+ }
- console.warn( "THREE.Material: '" + key + "' parameter is undefined." );
- continue;
+ onBuild( /* shaderobject, renderer */ ) {}
- }
+ onBeforeRender( /* renderer, scene, camera, geometry, object, group */ ) {}
- // for backward compatability if shading is set in the constructor
- if ( key === 'shading' ) {
+ onBeforeCompile( /* shaderobject, renderer */ ) {}
- console.warn( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' );
- this.flatShading = ( newValue === FlatShading ) ? true : false;
- continue;
+ customProgramCacheKey() {
- }
+ return this.onBeforeCompile.toString();
- var currentValue = this[ key ];
+ }
- if ( currentValue === undefined ) {
+ setValues( values ) {
- console.warn( "THREE." + this.type + ": '" + key + "' is not a property of this material." );
- continue;
+ if ( values === undefined ) return;
- }
+ for ( const key in values ) {
- if ( currentValue && currentValue.isColor ) {
+ const newValue = values[ key ];
- currentValue.set( newValue );
+ if ( newValue === undefined ) {
- } else if ( ( currentValue && currentValue.isVector3 ) && ( newValue && newValue.isVector3 ) ) {
+ console.warn( `THREE.Material: parameter '${ key }' has value of undefined.` );
+ continue;
- currentValue.copy( newValue );
+ }
- } else {
+ const currentValue = this[ key ];
- this[ key ] = newValue;
+ if ( currentValue === undefined ) {
- }
+ console.warn( `THREE.Material: '${ key }' is not a property of THREE.${ this.type }.` );
+ continue;
}
- },
-
- toJSON: function ( meta ) {
+ if ( currentValue && currentValue.isColor ) {
- var isRoot = ( meta === undefined || typeof meta === 'string' );
+ currentValue.set( newValue );
- if ( isRoot ) {
+ } else if ( ( currentValue && currentValue.isVector3 ) && ( newValue && newValue.isVector3 ) ) {
- meta = {
- textures: {},
- images: {}
- };
+ currentValue.copy( newValue );
- }
+ } else {
- var data = {
- metadata: {
- version: 4.5,
- type: 'Material',
- generator: 'Material.toJSON'
- }
- };
+ this[ key ] = newValue;
- // standard Material serialization
- data.uuid = this.uuid;
- data.type = this.type;
+ }
- if ( this.name !== '' ) data.name = this.name;
+ }
- if ( this.color && this.color.isColor ) data.color = this.color.getHex();
+ }
- if ( this.roughness !== undefined ) data.roughness = this.roughness;
- if ( this.metalness !== undefined ) data.metalness = this.metalness;
+ toJSON( meta ) {
- if ( this.emissive && this.emissive.isColor ) data.emissive = this.emissive.getHex();
- if ( this.emissiveIntensity && this.emissiveIntensity !== 1 ) data.emissiveIntensity = this.emissiveIntensity;
+ const isRootObject = ( meta === undefined || typeof meta === 'string' );
- if ( this.specular && this.specular.isColor ) data.specular = this.specular.getHex();
- if ( this.shininess !== undefined ) data.shininess = this.shininess;
- if ( this.clearcoat !== undefined ) data.clearcoat = this.clearcoat;
- if ( this.clearcoatRoughness !== undefined ) data.clearcoatRoughness = this.clearcoatRoughness;
+ if ( isRootObject ) {
- if ( this.clearcoatNormalMap && this.clearcoatNormalMap.isTexture ) {
+ meta = {
+ textures: {},
+ images: {}
+ };
- data.clearcoatNormalMap = this.clearcoatNormalMap.toJSON( meta ).uuid;
- data.clearcoatNormalScale = this.clearcoatNormalScale.toArray();
+ }
+ const data = {
+ metadata: {
+ version: 4.6,
+ type: 'Material',
+ generator: 'Material.toJSON'
}
+ };
- if ( this.map && this.map.isTexture ) data.map = this.map.toJSON( meta ).uuid;
- if ( this.matcap && this.matcap.isTexture ) data.matcap = this.matcap.toJSON( meta ).uuid;
- if ( this.alphaMap && this.alphaMap.isTexture ) data.alphaMap = this.alphaMap.toJSON( meta ).uuid;
- if ( this.lightMap && this.lightMap.isTexture ) data.lightMap = this.lightMap.toJSON( meta ).uuid;
-
- if ( this.aoMap && this.aoMap.isTexture ) {
+ // standard Material serialization
+ data.uuid = this.uuid;
+ data.type = this.type;
- data.aoMap = this.aoMap.toJSON( meta ).uuid;
- data.aoMapIntensity = this.aoMapIntensity;
+ if ( this.name !== '' ) data.name = this.name;
- }
+ if ( this.color && this.color.isColor ) data.color = this.color.getHex();
- if ( this.bumpMap && this.bumpMap.isTexture ) {
+ if ( this.roughness !== undefined ) data.roughness = this.roughness;
+ if ( this.metalness !== undefined ) data.metalness = this.metalness;
- data.bumpMap = this.bumpMap.toJSON( meta ).uuid;
- data.bumpScale = this.bumpScale;
+ if ( this.sheen !== undefined ) data.sheen = this.sheen;
+ if ( this.sheenColor && this.sheenColor.isColor ) data.sheenColor = this.sheenColor.getHex();
+ if ( this.sheenRoughness !== undefined ) data.sheenRoughness = this.sheenRoughness;
+ if ( this.emissive && this.emissive.isColor ) data.emissive = this.emissive.getHex();
+ if ( this.emissiveIntensity && this.emissiveIntensity !== 1 ) data.emissiveIntensity = this.emissiveIntensity;
- }
+ if ( this.specular && this.specular.isColor ) data.specular = this.specular.getHex();
+ if ( this.specularIntensity !== undefined ) data.specularIntensity = this.specularIntensity;
+ if ( this.specularColor && this.specularColor.isColor ) data.specularColor = this.specularColor.getHex();
+ if ( this.shininess !== undefined ) data.shininess = this.shininess;
+ if ( this.clearcoat !== undefined ) data.clearcoat = this.clearcoat;
+ if ( this.clearcoatRoughness !== undefined ) data.clearcoatRoughness = this.clearcoatRoughness;
- if ( this.normalMap && this.normalMap.isTexture ) {
+ if ( this.clearcoatMap && this.clearcoatMap.isTexture ) {
- data.normalMap = this.normalMap.toJSON( meta ).uuid;
- data.normalMapType = this.normalMapType;
- data.normalScale = this.normalScale.toArray();
+ data.clearcoatMap = this.clearcoatMap.toJSON( meta ).uuid;
- }
+ }
- if ( this.displacementMap && this.displacementMap.isTexture ) {
+ if ( this.clearcoatRoughnessMap && this.clearcoatRoughnessMap.isTexture ) {
- data.displacementMap = this.displacementMap.toJSON( meta ).uuid;
- data.displacementScale = this.displacementScale;
- data.displacementBias = this.displacementBias;
+ data.clearcoatRoughnessMap = this.clearcoatRoughnessMap.toJSON( meta ).uuid;
- }
+ }
- if ( this.roughnessMap && this.roughnessMap.isTexture ) data.roughnessMap = this.roughnessMap.toJSON( meta ).uuid;
- if ( this.metalnessMap && this.metalnessMap.isTexture ) data.metalnessMap = this.metalnessMap.toJSON( meta ).uuid;
+ if ( this.clearcoatNormalMap && this.clearcoatNormalMap.isTexture ) {
- if ( this.emissiveMap && this.emissiveMap.isTexture ) data.emissiveMap = this.emissiveMap.toJSON( meta ).uuid;
- if ( this.specularMap && this.specularMap.isTexture ) data.specularMap = this.specularMap.toJSON( meta ).uuid;
+ data.clearcoatNormalMap = this.clearcoatNormalMap.toJSON( meta ).uuid;
+ data.clearcoatNormalScale = this.clearcoatNormalScale.toArray();
- if ( this.envMap && this.envMap.isTexture ) {
+ }
- data.envMap = this.envMap.toJSON( meta ).uuid;
- data.reflectivity = this.reflectivity; // Scale behind envMap
- data.refractionRatio = this.refractionRatio;
+ if ( this.iridescence !== undefined ) data.iridescence = this.iridescence;
+ if ( this.iridescenceIOR !== undefined ) data.iridescenceIOR = this.iridescenceIOR;
+ if ( this.iridescenceThicknessRange !== undefined ) data.iridescenceThicknessRange = this.iridescenceThicknessRange;
- if ( this.combine !== undefined ) data.combine = this.combine;
- if ( this.envMapIntensity !== undefined ) data.envMapIntensity = this.envMapIntensity;
+ if ( this.iridescenceMap && this.iridescenceMap.isTexture ) {
- }
+ data.iridescenceMap = this.iridescenceMap.toJSON( meta ).uuid;
- if ( this.gradientMap && this.gradientMap.isTexture ) {
+ }
- data.gradientMap = this.gradientMap.toJSON( meta ).uuid;
+ if ( this.iridescenceThicknessMap && this.iridescenceThicknessMap.isTexture ) {
- }
+ data.iridescenceThicknessMap = this.iridescenceThicknessMap.toJSON( meta ).uuid;
- if ( this.size !== undefined ) data.size = this.size;
- if ( this.sizeAttenuation !== undefined ) data.sizeAttenuation = this.sizeAttenuation;
+ }
- if ( this.blending !== NormalBlending ) data.blending = this.blending;
- if ( this.flatShading === true ) data.flatShading = this.flatShading;
- if ( this.side !== FrontSide ) data.side = this.side;
- if ( this.vertexColors !== NoColors ) data.vertexColors = this.vertexColors;
+ if ( this.anisotropy !== undefined ) data.anisotropy = this.anisotropy;
+ if ( this.anisotropyRotation !== undefined ) data.anisotropyRotation = this.anisotropyRotation;
- if ( this.opacity < 1 ) data.opacity = this.opacity;
- if ( this.transparent === true ) data.transparent = this.transparent;
+ if ( this.anisotropyMap && this.anisotropyMap.isTexture ) {
- data.depthFunc = this.depthFunc;
- data.depthTest = this.depthTest;
- data.depthWrite = this.depthWrite;
+ data.anisotropyMap = this.anisotropyMap.toJSON( meta ).uuid;
- data.stencilWrite = this.stencilWrite;
- data.stencilFunc = this.stencilFunc;
- data.stencilRef = this.stencilRef;
- data.stencilMask = this.stencilMask;
- data.stencilFail = this.stencilFail;
- data.stencilZFail = this.stencilZFail;
- data.stencilZPass = this.stencilZPass;
+ }
- // rotation (SpriteMaterial)
- if ( this.rotation && this.rotation !== 0 ) data.rotation = this.rotation;
+ if ( this.map && this.map.isTexture ) data.map = this.map.toJSON( meta ).uuid;
+ if ( this.matcap && this.matcap.isTexture ) data.matcap = this.matcap.toJSON( meta ).uuid;
+ if ( this.alphaMap && this.alphaMap.isTexture ) data.alphaMap = this.alphaMap.toJSON( meta ).uuid;
- if ( this.polygonOffset === true ) data.polygonOffset = true;
- if ( this.polygonOffsetFactor !== 0 ) data.polygonOffsetFactor = this.polygonOffsetFactor;
- if ( this.polygonOffsetUnits !== 0 ) data.polygonOffsetUnits = this.polygonOffsetUnits;
+ if ( this.lightMap && this.lightMap.isTexture ) {
- if ( this.linewidth && this.linewidth !== 1 ) data.linewidth = this.linewidth;
- if ( this.dashSize !== undefined ) data.dashSize = this.dashSize;
- if ( this.gapSize !== undefined ) data.gapSize = this.gapSize;
- if ( this.scale !== undefined ) data.scale = this.scale;
+ data.lightMap = this.lightMap.toJSON( meta ).uuid;
+ data.lightMapIntensity = this.lightMapIntensity;
- if ( this.dithering === true ) data.dithering = true;
+ }
- if ( this.alphaTest > 0 ) data.alphaTest = this.alphaTest;
- if ( this.premultipliedAlpha === true ) data.premultipliedAlpha = this.premultipliedAlpha;
+ if ( this.aoMap && this.aoMap.isTexture ) {
- if ( this.wireframe === true ) data.wireframe = this.wireframe;
- if ( this.wireframeLinewidth > 1 ) data.wireframeLinewidth = this.wireframeLinewidth;
- if ( this.wireframeLinecap !== 'round' ) data.wireframeLinecap = this.wireframeLinecap;
- if ( this.wireframeLinejoin !== 'round' ) data.wireframeLinejoin = this.wireframeLinejoin;
+ data.aoMap = this.aoMap.toJSON( meta ).uuid;
+ data.aoMapIntensity = this.aoMapIntensity;
- if ( this.morphTargets === true ) data.morphTargets = true;
- if ( this.morphNormals === true ) data.morphNormals = true;
- if ( this.skinning === true ) data.skinning = true;
+ }
- if ( this.visible === false ) data.visible = false;
+ if ( this.bumpMap && this.bumpMap.isTexture ) {
- if ( this.toneMapped === false ) data.toneMapped = false;
+ data.bumpMap = this.bumpMap.toJSON( meta ).uuid;
+ data.bumpScale = this.bumpScale;
- if ( JSON.stringify( this.userData ) !== '{}' ) data.userData = this.userData;
+ }
- // TODO: Copied from Object3D.toJSON
+ if ( this.normalMap && this.normalMap.isTexture ) {
- function extractFromCache( cache ) {
+ data.normalMap = this.normalMap.toJSON( meta ).uuid;
+ data.normalMapType = this.normalMapType;
+ data.normalScale = this.normalScale.toArray();
- var values = [];
+ }
- for ( var key in cache ) {
+ if ( this.displacementMap && this.displacementMap.isTexture ) {
- var data = cache[ key ];
- delete data.metadata;
- values.push( data );
+ data.displacementMap = this.displacementMap.toJSON( meta ).uuid;
+ data.displacementScale = this.displacementScale;
+ data.displacementBias = this.displacementBias;
- }
+ }
- return values;
+ if ( this.roughnessMap && this.roughnessMap.isTexture ) data.roughnessMap = this.roughnessMap.toJSON( meta ).uuid;
+ if ( this.metalnessMap && this.metalnessMap.isTexture ) data.metalnessMap = this.metalnessMap.toJSON( meta ).uuid;
- }
+ if ( this.emissiveMap && this.emissiveMap.isTexture ) data.emissiveMap = this.emissiveMap.toJSON( meta ).uuid;
+ if ( this.specularMap && this.specularMap.isTexture ) data.specularMap = this.specularMap.toJSON( meta ).uuid;
+ if ( this.specularIntensityMap && this.specularIntensityMap.isTexture ) data.specularIntensityMap = this.specularIntensityMap.toJSON( meta ).uuid;
+ if ( this.specularColorMap && this.specularColorMap.isTexture ) data.specularColorMap = this.specularColorMap.toJSON( meta ).uuid;
- if ( isRoot ) {
+ if ( this.envMap && this.envMap.isTexture ) {
- var textures = extractFromCache( meta.textures );
- var images = extractFromCache( meta.images );
+ data.envMap = this.envMap.toJSON( meta ).uuid;
- if ( textures.length > 0 ) data.textures = textures;
- if ( images.length > 0 ) data.images = images;
+ if ( this.combine !== undefined ) data.combine = this.combine;
- }
+ }
- return data;
+ if ( this.envMapIntensity !== undefined ) data.envMapIntensity = this.envMapIntensity;
+ if ( this.reflectivity !== undefined ) data.reflectivity = this.reflectivity;
+ if ( this.refractionRatio !== undefined ) data.refractionRatio = this.refractionRatio;
- },
+ if ( this.gradientMap && this.gradientMap.isTexture ) {
- clone: function () {
+ data.gradientMap = this.gradientMap.toJSON( meta ).uuid;
- return new this.constructor().copy( this );
+ }
- },
+ if ( this.transmission !== undefined ) data.transmission = this.transmission;
+ if ( this.transmissionMap && this.transmissionMap.isTexture ) data.transmissionMap = this.transmissionMap.toJSON( meta ).uuid;
+ if ( this.thickness !== undefined ) data.thickness = this.thickness;
+ if ( this.thicknessMap && this.thicknessMap.isTexture ) data.thicknessMap = this.thicknessMap.toJSON( meta ).uuid;
+ if ( this.attenuationDistance !== undefined && this.attenuationDistance !== Infinity ) data.attenuationDistance = this.attenuationDistance;
+ if ( this.attenuationColor !== undefined ) data.attenuationColor = this.attenuationColor.getHex();
- copy: function ( source ) {
+ if ( this.size !== undefined ) data.size = this.size;
+ if ( this.shadowSide !== null ) data.shadowSide = this.shadowSide;
+ if ( this.sizeAttenuation !== undefined ) data.sizeAttenuation = this.sizeAttenuation;
- this.name = source.name;
+ if ( this.blending !== NormalBlending ) data.blending = this.blending;
+ if ( this.side !== FrontSide ) data.side = this.side;
+ if ( this.vertexColors === true ) data.vertexColors = true;
- this.fog = source.fog;
- this.lights = source.lights;
+ if ( this.opacity < 1 ) data.opacity = this.opacity;
+ if ( this.transparent === true ) data.transparent = true;
- this.blending = source.blending;
- this.side = source.side;
- this.flatShading = source.flatShading;
- this.vertexColors = source.vertexColors;
+ data.depthFunc = this.depthFunc;
+ data.depthTest = this.depthTest;
+ data.depthWrite = this.depthWrite;
+ data.colorWrite = this.colorWrite;
- this.opacity = source.opacity;
- this.transparent = source.transparent;
+ data.stencilWrite = this.stencilWrite;
+ data.stencilWriteMask = this.stencilWriteMask;
+ data.stencilFunc = this.stencilFunc;
+ data.stencilRef = this.stencilRef;
+ data.stencilFuncMask = this.stencilFuncMask;
+ data.stencilFail = this.stencilFail;
+ data.stencilZFail = this.stencilZFail;
+ data.stencilZPass = this.stencilZPass;
- this.blendSrc = source.blendSrc;
- this.blendDst = source.blendDst;
- this.blendEquation = source.blendEquation;
- this.blendSrcAlpha = source.blendSrcAlpha;
- this.blendDstAlpha = source.blendDstAlpha;
- this.blendEquationAlpha = source.blendEquationAlpha;
+ // rotation (SpriteMaterial)
+ if ( this.rotation !== undefined && this.rotation !== 0 ) data.rotation = this.rotation;
- this.depthFunc = source.depthFunc;
- this.depthTest = source.depthTest;
- this.depthWrite = source.depthWrite;
+ if ( this.polygonOffset === true ) data.polygonOffset = true;
+ if ( this.polygonOffsetFactor !== 0 ) data.polygonOffsetFactor = this.polygonOffsetFactor;
+ if ( this.polygonOffsetUnits !== 0 ) data.polygonOffsetUnits = this.polygonOffsetUnits;
- this.stencilWrite = source.stencilWrite;
- this.stencilFunc = source.stencilFunc;
- this.stencilRef = source.stencilRef;
- this.stencilMask = source.stencilMask;
- this.stencilFail = source.stencilFail;
- this.stencilZFail = source.stencilZFail;
- this.stencilZPass = source.stencilZPass;
+ if ( this.linewidth !== undefined && this.linewidth !== 1 ) data.linewidth = this.linewidth;
+ if ( this.dashSize !== undefined ) data.dashSize = this.dashSize;
+ if ( this.gapSize !== undefined ) data.gapSize = this.gapSize;
+ if ( this.scale !== undefined ) data.scale = this.scale;
- this.colorWrite = source.colorWrite;
+ if ( this.dithering === true ) data.dithering = true;
- this.precision = source.precision;
+ if ( this.alphaTest > 0 ) data.alphaTest = this.alphaTest;
+ if ( this.alphaHash === true ) data.alphaHash = true;
+ if ( this.alphaToCoverage === true ) data.alphaToCoverage = true;
+ if ( this.premultipliedAlpha === true ) data.premultipliedAlpha = true;
+ if ( this.forceSinglePass === true ) data.forceSinglePass = true;
- this.polygonOffset = source.polygonOffset;
- this.polygonOffsetFactor = source.polygonOffsetFactor;
- this.polygonOffsetUnits = source.polygonOffsetUnits;
+ if ( this.wireframe === true ) data.wireframe = true;
+ if ( this.wireframeLinewidth > 1 ) data.wireframeLinewidth = this.wireframeLinewidth;
+ if ( this.wireframeLinecap !== 'round' ) data.wireframeLinecap = this.wireframeLinecap;
+ if ( this.wireframeLinejoin !== 'round' ) data.wireframeLinejoin = this.wireframeLinejoin;
- this.dithering = source.dithering;
+ if ( this.flatShading === true ) data.flatShading = true;
- this.alphaTest = source.alphaTest;
- this.premultipliedAlpha = source.premultipliedAlpha;
+ if ( this.visible === false ) data.visible = false;
- this.visible = source.visible;
+ if ( this.toneMapped === false ) data.toneMapped = false;
- this.toneMapped = source.toneMapped;
+ if ( this.fog === false ) data.fog = false;
- this.userData = JSON.parse( JSON.stringify( source.userData ) );
+ if ( Object.keys( this.userData ).length > 0 ) data.userData = this.userData;
- this.clipShadows = source.clipShadows;
- this.clipIntersection = source.clipIntersection;
+ // TODO: Copied from Object3D.toJSON
- var srcPlanes = source.clippingPlanes,
- dstPlanes = null;
+ function extractFromCache( cache ) {
- if ( srcPlanes !== null ) {
+ const values = [];
- var n = srcPlanes.length;
- dstPlanes = new Array( n );
+ for ( const key in cache ) {
- for ( var i = 0; i !== n; ++ i )
- dstPlanes[ i ] = srcPlanes[ i ].clone();
+ const data = cache[ key ];
+ delete data.metadata;
+ values.push( data );
}
- this.clippingPlanes = dstPlanes;
+ return values;
- this.shadowSide = source.shadowSide;
-
- return this;
+ }
- },
+ if ( isRootObject ) {
- dispose: function () {
+ const textures = extractFromCache( meta.textures );
+ const images = extractFromCache( meta.images );
- this.dispatchEvent( { type: 'dispose' } );
+ if ( textures.length > 0 ) data.textures = textures;
+ if ( images.length > 0 ) data.images = images;
}
- } );
+ return data;
- /**
- * @author mrdoob / http://mrdoob.com/
- * @author alteredq / http://alteredqualia.com/
- *
- * parameters = {
- * color: ,
- * opacity: ,
- * map: new THREE.Texture( ),
- *
- * lightMap: new THREE.Texture( ),
- * lightMapIntensity:
- *
- * aoMap: new THREE.Texture( ),
- * aoMapIntensity:
- *
- * specularMap: new THREE.Texture( ),
- *
- * alphaMap: new THREE.Texture( ),
- *
- * envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ),
- * combine: THREE.Multiply,
- * reflectivity: ,
- * refractionRatio: ,
- *
- * depthTest: ,
- * depthWrite: ,
- *
- * wireframe: ,
- * wireframeLinewidth: ,
- *
- * skinning: ,
- * morphTargets:
- * }
- */
+ }
- function MeshBasicMaterial( parameters ) {
+ clone() {
- Material.call( this );
+ return new this.constructor().copy( this );
- this.type = 'MeshBasicMaterial';
+ }
- this.color = new Color( 0xffffff ); // emissive
+ copy( source ) {
- this.map = null;
+ this.name = source.name;
- this.lightMap = null;
- this.lightMapIntensity = 1.0;
+ this.blending = source.blending;
+ this.side = source.side;
+ this.vertexColors = source.vertexColors;
- this.aoMap = null;
- this.aoMapIntensity = 1.0;
+ this.opacity = source.opacity;
+ this.transparent = source.transparent;
- this.specularMap = null;
+ this.blendSrc = source.blendSrc;
+ this.blendDst = source.blendDst;
+ this.blendEquation = source.blendEquation;
+ this.blendSrcAlpha = source.blendSrcAlpha;
+ this.blendDstAlpha = source.blendDstAlpha;
+ this.blendEquationAlpha = source.blendEquationAlpha;
- this.alphaMap = null;
+ this.depthFunc = source.depthFunc;
+ this.depthTest = source.depthTest;
+ this.depthWrite = source.depthWrite;
- this.envMap = null;
- this.combine = MultiplyOperation;
- this.reflectivity = 1;
- this.refractionRatio = 0.98;
+ this.stencilWriteMask = source.stencilWriteMask;
+ this.stencilFunc = source.stencilFunc;
+ this.stencilRef = source.stencilRef;
+ this.stencilFuncMask = source.stencilFuncMask;
+ this.stencilFail = source.stencilFail;
+ this.stencilZFail = source.stencilZFail;
+ this.stencilZPass = source.stencilZPass;
+ this.stencilWrite = source.stencilWrite;
- this.wireframe = false;
- this.wireframeLinewidth = 1;
- this.wireframeLinecap = 'round';
- this.wireframeLinejoin = 'round';
+ const srcPlanes = source.clippingPlanes;
+ let dstPlanes = null;
- this.skinning = false;
- this.morphTargets = false;
+ if ( srcPlanes !== null ) {
- this.lights = false;
+ const n = srcPlanes.length;
+ dstPlanes = new Array( n );
- this.setValues( parameters );
+ for ( let i = 0; i !== n; ++ i ) {
- }
+ dstPlanes[ i ] = srcPlanes[ i ].clone();
- MeshBasicMaterial.prototype = Object.create( Material.prototype );
- MeshBasicMaterial.prototype.constructor = MeshBasicMaterial;
+ }
- MeshBasicMaterial.prototype.isMeshBasicMaterial = true;
+ }
- MeshBasicMaterial.prototype.copy = function ( source ) {
+ this.clippingPlanes = dstPlanes;
+ this.clipIntersection = source.clipIntersection;
+ this.clipShadows = source.clipShadows;
- Material.prototype.copy.call( this, source );
+ this.shadowSide = source.shadowSide;
- this.color.copy( source.color );
+ this.colorWrite = source.colorWrite;
- this.map = source.map;
+ this.precision = source.precision;
- this.lightMap = source.lightMap;
- this.lightMapIntensity = source.lightMapIntensity;
+ this.polygonOffset = source.polygonOffset;
+ this.polygonOffsetFactor = source.polygonOffsetFactor;
+ this.polygonOffsetUnits = source.polygonOffsetUnits;
- this.aoMap = source.aoMap;
- this.aoMapIntensity = source.aoMapIntensity;
-
- this.specularMap = source.specularMap;
+ this.dithering = source.dithering;
- this.alphaMap = source.alphaMap;
+ this.alphaTest = source.alphaTest;
+ this.alphaHash = source.alphaHash;
+ this.alphaToCoverage = source.alphaToCoverage;
+ this.premultipliedAlpha = source.premultipliedAlpha;
+ this.forceSinglePass = source.forceSinglePass;
- this.envMap = source.envMap;
- this.combine = source.combine;
- this.reflectivity = source.reflectivity;
- this.refractionRatio = source.refractionRatio;
+ this.visible = source.visible;
- this.wireframe = source.wireframe;
- this.wireframeLinewidth = source.wireframeLinewidth;
- this.wireframeLinecap = source.wireframeLinecap;
- this.wireframeLinejoin = source.wireframeLinejoin;
+ this.toneMapped = source.toneMapped;
- this.skinning = source.skinning;
- this.morphTargets = source.morphTargets;
+ this.userData = JSON.parse( JSON.stringify( source.userData ) );
return this;
- };
+ }
- /**
- * @author mrdoob / http://mrdoob.com/
- */
+ dispose() {
- function BufferAttribute( array, itemSize, normalized ) {
+ this.dispatchEvent( { type: 'dispose' } );
- if ( Array.isArray( array ) ) {
+ }
- throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' );
+ set needsUpdate( value ) {
- }
+ if ( value === true ) this.version ++;
- this.name = '';
+ }
- this.array = array;
- this.itemSize = itemSize;
- this.count = array !== undefined ? array.length / itemSize : 0;
- this.normalized = normalized === true;
+}
- this.dynamic = false;
- this.updateRange = { offset: 0, count: - 1 };
+const _colorKeywords = { 'aliceblue': 0xF0F8FF, 'antiquewhite': 0xFAEBD7, 'aqua': 0x00FFFF, 'aquamarine': 0x7FFFD4, 'azure': 0xF0FFFF,
+ 'beige': 0xF5F5DC, 'bisque': 0xFFE4C4, 'black': 0x000000, 'blanchedalmond': 0xFFEBCD, 'blue': 0x0000FF, 'blueviolet': 0x8A2BE2,
+ 'brown': 0xA52A2A, 'burlywood': 0xDEB887, 'cadetblue': 0x5F9EA0, 'chartreuse': 0x7FFF00, 'chocolate': 0xD2691E, 'coral': 0xFF7F50,
+ 'cornflowerblue': 0x6495ED, 'cornsilk': 0xFFF8DC, 'crimson': 0xDC143C, 'cyan': 0x00FFFF, 'darkblue': 0x00008B, 'darkcyan': 0x008B8B,
+ 'darkgoldenrod': 0xB8860B, 'darkgray': 0xA9A9A9, 'darkgreen': 0x006400, 'darkgrey': 0xA9A9A9, 'darkkhaki': 0xBDB76B, 'darkmagenta': 0x8B008B,
+ 'darkolivegreen': 0x556B2F, 'darkorange': 0xFF8C00, 'darkorchid': 0x9932CC, 'darkred': 0x8B0000, 'darksalmon': 0xE9967A, 'darkseagreen': 0x8FBC8F,
+ 'darkslateblue': 0x483D8B, 'darkslategray': 0x2F4F4F, 'darkslategrey': 0x2F4F4F, 'darkturquoise': 0x00CED1, 'darkviolet': 0x9400D3,
+ 'deeppink': 0xFF1493, 'deepskyblue': 0x00BFFF, 'dimgray': 0x696969, 'dimgrey': 0x696969, 'dodgerblue': 0x1E90FF, 'firebrick': 0xB22222,
+ 'floralwhite': 0xFFFAF0, 'forestgreen': 0x228B22, 'fuchsia': 0xFF00FF, 'gainsboro': 0xDCDCDC, 'ghostwhite': 0xF8F8FF, 'gold': 0xFFD700,
+ 'goldenrod': 0xDAA520, 'gray': 0x808080, 'green': 0x008000, 'greenyellow': 0xADFF2F, 'grey': 0x808080, 'honeydew': 0xF0FFF0, 'hotpink': 0xFF69B4,
+ 'indianred': 0xCD5C5C, 'indigo': 0x4B0082, 'ivory': 0xFFFFF0, 'khaki': 0xF0E68C, 'lavender': 0xE6E6FA, 'lavenderblush': 0xFFF0F5, 'lawngreen': 0x7CFC00,
+ 'lemonchiffon': 0xFFFACD, 'lightblue': 0xADD8E6, 'lightcoral': 0xF08080, 'lightcyan': 0xE0FFFF, 'lightgoldenrodyellow': 0xFAFAD2, 'lightgray': 0xD3D3D3,
+ 'lightgreen': 0x90EE90, 'lightgrey': 0xD3D3D3, 'lightpink': 0xFFB6C1, 'lightsalmon': 0xFFA07A, 'lightseagreen': 0x20B2AA, 'lightskyblue': 0x87CEFA,
+ 'lightslategray': 0x778899, 'lightslategrey': 0x778899, 'lightsteelblue': 0xB0C4DE, 'lightyellow': 0xFFFFE0, 'lime': 0x00FF00, 'limegreen': 0x32CD32,
+ 'linen': 0xFAF0E6, 'magenta': 0xFF00FF, 'maroon': 0x800000, 'mediumaquamarine': 0x66CDAA, 'mediumblue': 0x0000CD, 'mediumorchid': 0xBA55D3,
+ 'mediumpurple': 0x9370DB, 'mediumseagreen': 0x3CB371, 'mediumslateblue': 0x7B68EE, 'mediumspringgreen': 0x00FA9A, 'mediumturquoise': 0x48D1CC,
+ 'mediumvioletred': 0xC71585, 'midnightblue': 0x191970, 'mintcream': 0xF5FFFA, 'mistyrose': 0xFFE4E1, 'moccasin': 0xFFE4B5, 'navajowhite': 0xFFDEAD,
+ 'navy': 0x000080, 'oldlace': 0xFDF5E6, 'olive': 0x808000, 'olivedrab': 0x6B8E23, 'orange': 0xFFA500, 'orangered': 0xFF4500, 'orchid': 0xDA70D6,
+ 'palegoldenrod': 0xEEE8AA, 'palegreen': 0x98FB98, 'paleturquoise': 0xAFEEEE, 'palevioletred': 0xDB7093, 'papayawhip': 0xFFEFD5, 'peachpuff': 0xFFDAB9,
+ 'peru': 0xCD853F, 'pink': 0xFFC0CB, 'plum': 0xDDA0DD, 'powderblue': 0xB0E0E6, 'purple': 0x800080, 'rebeccapurple': 0x663399, 'red': 0xFF0000, 'rosybrown': 0xBC8F8F,
+ 'royalblue': 0x4169E1, 'saddlebrown': 0x8B4513, 'salmon': 0xFA8072, 'sandybrown': 0xF4A460, 'seagreen': 0x2E8B57, 'seashell': 0xFFF5EE,
+ 'sienna': 0xA0522D, 'silver': 0xC0C0C0, 'skyblue': 0x87CEEB, 'slateblue': 0x6A5ACD, 'slategray': 0x708090, 'slategrey': 0x708090, 'snow': 0xFFFAFA,
+ 'springgreen': 0x00FF7F, 'steelblue': 0x4682B4, 'tan': 0xD2B48C, 'teal': 0x008080, 'thistle': 0xD8BFD8, 'tomato': 0xFF6347, 'turquoise': 0x40E0D0,
+ 'violet': 0xEE82EE, 'wheat': 0xF5DEB3, 'white': 0xFFFFFF, 'whitesmoke': 0xF5F5F5, 'yellow': 0xFFFF00, 'yellowgreen': 0x9ACD32 };
- this.version = 0;
+const _hslA = { h: 0, s: 0, l: 0 };
+const _hslB = { h: 0, s: 0, l: 0 };
- }
+function hue2rgb( p, q, t ) {
- Object.defineProperty( BufferAttribute.prototype, 'needsUpdate', {
+ if ( t < 0 ) t += 1;
+ if ( t > 1 ) t -= 1;
+ if ( t < 1 / 6 ) return p + ( q - p ) * 6 * t;
+ if ( t < 1 / 2 ) return q;
+ if ( t < 2 / 3 ) return p + ( q - p ) * 6 * ( 2 / 3 - t );
+ return p;
- set: function ( value ) {
+}
- if ( value === true ) this.version ++;
+class Color {
- }
+ constructor( r, g, b ) {
- } );
+ this.isColor = true;
- Object.assign( BufferAttribute.prototype, {
+ this.r = 1;
+ this.g = 1;
+ this.b = 1;
- isBufferAttribute: true,
+ return this.set( r, g, b );
- onUploadCallback: function () {},
+ }
- setArray: function ( array ) {
+ set( r, g, b ) {
- if ( Array.isArray( array ) ) {
+ if ( g === undefined && b === undefined ) {
- throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' );
+ // r is THREE.Color, hex or string
- }
+ const value = r;
- this.count = array !== undefined ? array.length / this.itemSize : 0;
- this.array = array;
+ if ( value && value.isColor ) {
- return this;
+ this.copy( value );
- },
+ } else if ( typeof value === 'number' ) {
- setDynamic: function ( value ) {
+ this.setHex( value );
- this.dynamic = value;
+ } else if ( typeof value === 'string' ) {
- return this;
+ this.setStyle( value );
- },
+ }
- copy: function ( source ) {
+ } else {
- this.name = source.name;
- this.array = new source.array.constructor( source.array );
- this.itemSize = source.itemSize;
- this.count = source.count;
- this.normalized = source.normalized;
+ this.setRGB( r, g, b );
- this.dynamic = source.dynamic;
+ }
- return this;
+ return this;
- },
+ }
- copyAt: function ( index1, attribute, index2 ) {
+ setScalar( scalar ) {
- index1 *= this.itemSize;
- index2 *= attribute.itemSize;
+ this.r = scalar;
+ this.g = scalar;
+ this.b = scalar;
- for ( var i = 0, l = this.itemSize; i < l; i ++ ) {
+ return this;
- this.array[ index1 + i ] = attribute.array[ index2 + i ];
+ }
- }
+ setHex( hex, colorSpace = SRGBColorSpace ) {
- return this;
+ hex = Math.floor( hex );
- },
+ this.r = ( hex >> 16 & 255 ) / 255;
+ this.g = ( hex >> 8 & 255 ) / 255;
+ this.b = ( hex & 255 ) / 255;
- copyArray: function ( array ) {
+ ColorManagement.toWorkingColorSpace( this, colorSpace );
- this.array.set( array );
+ return this;
- return this;
+ }
- },
+ setRGB( r, g, b, colorSpace = ColorManagement.workingColorSpace ) {
- copyColorsArray: function ( colors ) {
+ this.r = r;
+ this.g = g;
+ this.b = b;
- var array = this.array, offset = 0;
+ ColorManagement.toWorkingColorSpace( this, colorSpace );
- for ( var i = 0, l = colors.length; i < l; i ++ ) {
+ return this;
- var color = colors[ i ];
+ }
- if ( color === undefined ) {
+ setHSL( h, s, l, colorSpace = ColorManagement.workingColorSpace ) {
- console.warn( 'THREE.BufferAttribute.copyColorsArray(): color is undefined', i );
- color = new Color();
+ // h,s,l ranges are in 0.0 - 1.0
+ h = euclideanModulo( h, 1 );
+ s = clamp( s, 0, 1 );
+ l = clamp( l, 0, 1 );
- }
+ if ( s === 0 ) {
- array[ offset ++ ] = color.r;
- array[ offset ++ ] = color.g;
- array[ offset ++ ] = color.b;
+ this.r = this.g = this.b = l;
- }
+ } else {
- return this;
+ const p = l <= 0.5 ? l * ( 1 + s ) : l + s - ( l * s );
+ const q = ( 2 * l ) - p;
- },
+ this.r = hue2rgb( q, p, h + 1 / 3 );
+ this.g = hue2rgb( q, p, h );
+ this.b = hue2rgb( q, p, h - 1 / 3 );
- copyVector2sArray: function ( vectors ) {
+ }
- var array = this.array, offset = 0;
+ ColorManagement.toWorkingColorSpace( this, colorSpace );
- for ( var i = 0, l = vectors.length; i < l; i ++ ) {
+ return this;
- var vector = vectors[ i ];
+ }
- if ( vector === undefined ) {
+ setStyle( style, colorSpace = SRGBColorSpace ) {
- console.warn( 'THREE.BufferAttribute.copyVector2sArray(): vector is undefined', i );
- vector = new Vector2();
+ function handleAlpha( string ) {
- }
+ if ( string === undefined ) return;
- array[ offset ++ ] = vector.x;
- array[ offset ++ ] = vector.y;
+ if ( parseFloat( string ) < 1 ) {
+
+ console.warn( 'THREE.Color: Alpha component of ' + style + ' will be ignored.' );
}
- return this;
+ }
- },
- copyVector3sArray: function ( vectors ) {
+ let m;
- var array = this.array, offset = 0;
+ if ( m = /^(\w+)\(([^\)]*)\)/.exec( style ) ) {
- for ( var i = 0, l = vectors.length; i < l; i ++ ) {
+ // rgb / hsl
- var vector = vectors[ i ];
+ let color;
+ const name = m[ 1 ];
+ const components = m[ 2 ];
- if ( vector === undefined ) {
+ switch ( name ) {
- console.warn( 'THREE.BufferAttribute.copyVector3sArray(): vector is undefined', i );
- vector = new Vector3();
+ case 'rgb':
+ case 'rgba':
- }
+ if ( color = /^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) {
- array[ offset ++ ] = vector.x;
- array[ offset ++ ] = vector.y;
- array[ offset ++ ] = vector.z;
+ // rgb(255,0,0) rgba(255,0,0,0.5)
- }
+ handleAlpha( color[ 4 ] );
- return this;
+ return this.setRGB(
+ Math.min( 255, parseInt( color[ 1 ], 10 ) ) / 255,
+ Math.min( 255, parseInt( color[ 2 ], 10 ) ) / 255,
+ Math.min( 255, parseInt( color[ 3 ], 10 ) ) / 255,
+ colorSpace
+ );
- },
+ }
- copyVector4sArray: function ( vectors ) {
+ if ( color = /^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) {
- var array = this.array, offset = 0;
+ // rgb(100%,0%,0%) rgba(100%,0%,0%,0.5)
- for ( var i = 0, l = vectors.length; i < l; i ++ ) {
+ handleAlpha( color[ 4 ] );
- var vector = vectors[ i ];
+ return this.setRGB(
+ Math.min( 100, parseInt( color[ 1 ], 10 ) ) / 100,
+ Math.min( 100, parseInt( color[ 2 ], 10 ) ) / 100,
+ Math.min( 100, parseInt( color[ 3 ], 10 ) ) / 100,
+ colorSpace
+ );
- if ( vector === undefined ) {
+ }
- console.warn( 'THREE.BufferAttribute.copyVector4sArray(): vector is undefined', i );
- vector = new Vector4();
+ break;
- }
+ case 'hsl':
+ case 'hsla':
- array[ offset ++ ] = vector.x;
- array[ offset ++ ] = vector.y;
- array[ offset ++ ] = vector.z;
- array[ offset ++ ] = vector.w;
+ if ( color = /^\s*(\d*\.?\d+)\s*,\s*(\d*\.?\d+)\%\s*,\s*(\d*\.?\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) {
- }
+ // hsl(120,50%,50%) hsla(120,50%,50%,0.5)
- return this;
+ handleAlpha( color[ 4 ] );
- },
+ return this.setHSL(
+ parseFloat( color[ 1 ] ) / 360,
+ parseFloat( color[ 2 ] ) / 100,
+ parseFloat( color[ 3 ] ) / 100,
+ colorSpace
+ );
- set: function ( value, offset ) {
+ }
- if ( offset === undefined ) offset = 0;
+ break;
- this.array.set( value, offset );
+ default:
- return this;
+ console.warn( 'THREE.Color: Unknown color model ' + style );
- },
+ }
- getX: function ( index ) {
+ } else if ( m = /^\#([A-Fa-f\d]+)$/.exec( style ) ) {
- return this.array[ index * this.itemSize ];
+ // hex color
- },
+ const hex = m[ 1 ];
+ const size = hex.length;
- setX: function ( index, x ) {
+ if ( size === 3 ) {
- this.array[ index * this.itemSize ] = x;
+ // #ff0
+ return this.setRGB(
+ parseInt( hex.charAt( 0 ), 16 ) / 15,
+ parseInt( hex.charAt( 1 ), 16 ) / 15,
+ parseInt( hex.charAt( 2 ), 16 ) / 15,
+ colorSpace
+ );
- return this;
+ } else if ( size === 6 ) {
- },
+ // #ff0000
+ return this.setHex( parseInt( hex, 16 ), colorSpace );
- getY: function ( index ) {
+ } else {
- return this.array[ index * this.itemSize + 1 ];
+ console.warn( 'THREE.Color: Invalid hex color ' + style );
- },
+ }
- setY: function ( index, y ) {
+ } else if ( style && style.length > 0 ) {
- this.array[ index * this.itemSize + 1 ] = y;
+ return this.setColorName( style, colorSpace );
- return this;
+ }
- },
+ return this;
- getZ: function ( index ) {
+ }
- return this.array[ index * this.itemSize + 2 ];
+ setColorName( style, colorSpace = SRGBColorSpace ) {
- },
+ // color keywords
+ const hex = _colorKeywords[ style.toLowerCase() ];
- setZ: function ( index, z ) {
+ if ( hex !== undefined ) {
- this.array[ index * this.itemSize + 2 ] = z;
+ // red
+ this.setHex( hex, colorSpace );
- return this;
+ } else {
- },
+ // unknown color
+ console.warn( 'THREE.Color: Unknown color ' + style );
- getW: function ( index ) {
+ }
- return this.array[ index * this.itemSize + 3 ];
+ return this;
- },
+ }
- setW: function ( index, w ) {
+ clone() {
- this.array[ index * this.itemSize + 3 ] = w;
+ return new this.constructor( this.r, this.g, this.b );
- return this;
+ }
- },
+ copy( color ) {
- setXY: function ( index, x, y ) {
+ this.r = color.r;
+ this.g = color.g;
+ this.b = color.b;
- index *= this.itemSize;
+ return this;
- this.array[ index + 0 ] = x;
- this.array[ index + 1 ] = y;
+ }
- return this;
+ copySRGBToLinear( color ) {
- },
+ this.r = SRGBToLinear( color.r );
+ this.g = SRGBToLinear( color.g );
+ this.b = SRGBToLinear( color.b );
- setXYZ: function ( index, x, y, z ) {
+ return this;
- index *= this.itemSize;
+ }
- this.array[ index + 0 ] = x;
- this.array[ index + 1 ] = y;
- this.array[ index + 2 ] = z;
+ copyLinearToSRGB( color ) {
- return this;
+ this.r = LinearToSRGB( color.r );
+ this.g = LinearToSRGB( color.g );
+ this.b = LinearToSRGB( color.b );
- },
+ return this;
- setXYZW: function ( index, x, y, z, w ) {
+ }
- index *= this.itemSize;
+ convertSRGBToLinear() {
- this.array[ index + 0 ] = x;
- this.array[ index + 1 ] = y;
- this.array[ index + 2 ] = z;
- this.array[ index + 3 ] = w;
+ this.copySRGBToLinear( this );
- return this;
+ return this;
- },
+ }
- onUpload: function ( callback ) {
+ convertLinearToSRGB() {
- this.onUploadCallback = callback;
+ this.copyLinearToSRGB( this );
- return this;
+ return this;
- },
+ }
- clone: function () {
+ getHex( colorSpace = SRGBColorSpace ) {
- return new this.constructor( this.array, this.itemSize ).copy( this );
+ ColorManagement.fromWorkingColorSpace( _color.copy( this ), colorSpace );
- },
+ return Math.round( clamp( _color.r * 255, 0, 255 ) ) * 65536 + Math.round( clamp( _color.g * 255, 0, 255 ) ) * 256 + Math.round( clamp( _color.b * 255, 0, 255 ) );
- toJSON: function () {
+ }
- return {
- itemSize: this.itemSize,
- type: this.array.constructor.name,
- array: Array.prototype.slice.call( this.array ),
- normalized: this.normalized
- };
+ getHexString( colorSpace = SRGBColorSpace ) {
- }
+ return ( '000000' + this.getHex( colorSpace ).toString( 16 ) ).slice( - 6 );
- } );
+ }
- //
+ getHSL( target, colorSpace = ColorManagement.workingColorSpace ) {
- function Int8BufferAttribute( array, itemSize, normalized ) {
+ // h,s,l ranges are in 0.0 - 1.0
- BufferAttribute.call( this, new Int8Array( array ), itemSize, normalized );
+ ColorManagement.fromWorkingColorSpace( _color.copy( this ), colorSpace );
- }
+ const r = _color.r, g = _color.g, b = _color.b;
- Int8BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
- Int8BufferAttribute.prototype.constructor = Int8BufferAttribute;
+ const max = Math.max( r, g, b );
+ const min = Math.min( r, g, b );
+ let hue, saturation;
+ const lightness = ( min + max ) / 2.0;
- function Uint8BufferAttribute( array, itemSize, normalized ) {
+ if ( min === max ) {
- BufferAttribute.call( this, new Uint8Array( array ), itemSize, normalized );
+ hue = 0;
+ saturation = 0;
- }
+ } else {
- Uint8BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
- Uint8BufferAttribute.prototype.constructor = Uint8BufferAttribute;
+ const delta = max - min;
+ saturation = lightness <= 0.5 ? delta / ( max + min ) : delta / ( 2 - max - min );
- function Uint8ClampedBufferAttribute( array, itemSize, normalized ) {
+ switch ( max ) {
- BufferAttribute.call( this, new Uint8ClampedArray( array ), itemSize, normalized );
+ case r: hue = ( g - b ) / delta + ( g < b ? 6 : 0 ); break;
+ case g: hue = ( b - r ) / delta + 2; break;
+ case b: hue = ( r - g ) / delta + 4; break;
- }
+ }
- Uint8ClampedBufferAttribute.prototype = Object.create( BufferAttribute.prototype );
- Uint8ClampedBufferAttribute.prototype.constructor = Uint8ClampedBufferAttribute;
+ hue /= 6;
+ }
- function Int16BufferAttribute( array, itemSize, normalized ) {
+ target.h = hue;
+ target.s = saturation;
+ target.l = lightness;
- BufferAttribute.call( this, new Int16Array( array ), itemSize, normalized );
+ return target;
}
- Int16BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
- Int16BufferAttribute.prototype.constructor = Int16BufferAttribute;
+ getRGB( target, colorSpace = ColorManagement.workingColorSpace ) {
+ ColorManagement.fromWorkingColorSpace( _color.copy( this ), colorSpace );
- function Uint16BufferAttribute( array, itemSize, normalized ) {
+ target.r = _color.r;
+ target.g = _color.g;
+ target.b = _color.b;
- BufferAttribute.call( this, new Uint16Array( array ), itemSize, normalized );
+ return target;
}
- Uint16BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
- Uint16BufferAttribute.prototype.constructor = Uint16BufferAttribute;
+ getStyle( colorSpace = SRGBColorSpace ) {
+ ColorManagement.fromWorkingColorSpace( _color.copy( this ), colorSpace );
- function Int32BufferAttribute( array, itemSize, normalized ) {
+ const r = _color.r, g = _color.g, b = _color.b;
- BufferAttribute.call( this, new Int32Array( array ), itemSize, normalized );
+ if ( colorSpace !== SRGBColorSpace ) {
- }
+ // Requires CSS Color Module Level 4 (https://www.w3.org/TR/css-color-4/).
+ return `color(${ colorSpace } ${ r.toFixed( 3 ) } ${ g.toFixed( 3 ) } ${ b.toFixed( 3 ) })`;
- Int32BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
- Int32BufferAttribute.prototype.constructor = Int32BufferAttribute;
+ }
+
+ return `rgb(${ Math.round( r * 255 ) },${ Math.round( g * 255 ) },${ Math.round( b * 255 ) })`;
+ }
- function Uint32BufferAttribute( array, itemSize, normalized ) {
+ offsetHSL( h, s, l ) {
- BufferAttribute.call( this, new Uint32Array( array ), itemSize, normalized );
+ this.getHSL( _hslA );
- }
+ return this.setHSL( _hslA.h + h, _hslA.s + s, _hslA.l + l );
- Uint32BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
- Uint32BufferAttribute.prototype.constructor = Uint32BufferAttribute;
+ }
+ add( color ) {
- function Float32BufferAttribute( array, itemSize, normalized ) {
+ this.r += color.r;
+ this.g += color.g;
+ this.b += color.b;
- BufferAttribute.call( this, new Float32Array( array ), itemSize, normalized );
+ return this;
}
- Float32BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
- Float32BufferAttribute.prototype.constructor = Float32BufferAttribute;
+ addColors( color1, color2 ) {
+ this.r = color1.r + color2.r;
+ this.g = color1.g + color2.g;
+ this.b = color1.b + color2.b;
- function Float64BufferAttribute( array, itemSize, normalized ) {
-
- BufferAttribute.call( this, new Float64Array( array ), itemSize, normalized );
+ return this;
}
- Float64BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
- Float64BufferAttribute.prototype.constructor = Float64BufferAttribute;
+ addScalar( s ) {
- /**
- * @author mrdoob / http://mrdoob.com/
- */
+ this.r += s;
+ this.g += s;
+ this.b += s;
- function DirectGeometry() {
+ return this;
- this.vertices = [];
- this.normals = [];
- this.colors = [];
- this.uvs = [];
- this.uvs2 = [];
+ }
- this.groups = [];
+ sub( color ) {
- this.morphTargets = {};
+ this.r = Math.max( 0, this.r - color.r );
+ this.g = Math.max( 0, this.g - color.g );
+ this.b = Math.max( 0, this.b - color.b );
- this.skinWeights = [];
- this.skinIndices = [];
+ return this;
- // this.lineDistances = [];
+ }
- this.boundingBox = null;
- this.boundingSphere = null;
+ multiply( color ) {
- // update flags
+ this.r *= color.r;
+ this.g *= color.g;
+ this.b *= color.b;
- this.verticesNeedUpdate = false;
- this.normalsNeedUpdate = false;
- this.colorsNeedUpdate = false;
- this.uvsNeedUpdate = false;
- this.groupsNeedUpdate = false;
+ return this;
}
- Object.assign( DirectGeometry.prototype, {
+ multiplyScalar( s ) {
- computeGroups: function ( geometry ) {
+ this.r *= s;
+ this.g *= s;
+ this.b *= s;
- var group;
- var groups = [];
- var materialIndex = undefined;
+ return this;
- var faces = geometry.faces;
+ }
- for ( var i = 0; i < faces.length; i ++ ) {
+ lerp( color, alpha ) {
- var face = faces[ i ];
+ this.r += ( color.r - this.r ) * alpha;
+ this.g += ( color.g - this.g ) * alpha;
+ this.b += ( color.b - this.b ) * alpha;
- // materials
+ return this;
- if ( face.materialIndex !== materialIndex ) {
+ }
- materialIndex = face.materialIndex;
+ lerpColors( color1, color2, alpha ) {
- if ( group !== undefined ) {
+ 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;
- group.count = ( i * 3 ) - group.start;
- groups.push( group );
+ return this;
- }
+ }
- group = {
- start: i * 3,
- materialIndex: materialIndex
- };
+ lerpHSL( color, alpha ) {
- }
+ this.getHSL( _hslA );
+ color.getHSL( _hslB );
- }
+ const h = lerp( _hslA.h, _hslB.h, alpha );
+ const s = lerp( _hslA.s, _hslB.s, alpha );
+ const l = lerp( _hslA.l, _hslB.l, alpha );
- if ( group !== undefined ) {
+ this.setHSL( h, s, l );
- group.count = ( i * 3 ) - group.start;
- groups.push( group );
+ return this;
- }
+ }
- this.groups = groups;
+ setFromVector3( v ) {
- },
+ this.r = v.x;
+ this.g = v.y;
+ this.b = v.z;
- fromGeometry: function ( geometry ) {
+ return this;
- 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;
+ applyMatrix3( m ) {
- // morphs
+ const r = this.r, g = this.g, b = this.b;
+ const e = m.elements;
- var morphTargets = geometry.morphTargets;
- var morphTargetsLength = morphTargets.length;
+ this.r = e[ 0 ] * r + e[ 3 ] * g + e[ 6 ] * b;
+ this.g = e[ 1 ] * r + e[ 4 ] * g + e[ 7 ] * b;
+ this.b = e[ 2 ] * r + e[ 5 ] * g + e[ 8 ] * b;
- var morphTargetsPosition;
+ return this;
- if ( morphTargetsLength > 0 ) {
+ }
- morphTargetsPosition = [];
+ equals( c ) {
- for ( var i = 0; i < morphTargetsLength; i ++ ) {
+ return ( c.r === this.r ) && ( c.g === this.g ) && ( c.b === this.b );
- morphTargetsPosition[ i ] = {
- name: morphTargets[ i ].name,
- data: []
- };
+ }
- }
+ fromArray( array, offset = 0 ) {
- this.morphTargets.position = morphTargetsPosition;
+ this.r = array[ offset ];
+ this.g = array[ offset + 1 ];
+ this.b = array[ offset + 2 ];
- }
+ return this;
- var morphNormals = geometry.morphNormals;
- var morphNormalsLength = morphNormals.length;
+ }
- var morphTargetsNormal;
+ toArray( array = [], offset = 0 ) {
- if ( morphNormalsLength > 0 ) {
+ array[ offset ] = this.r;
+ array[ offset + 1 ] = this.g;
+ array[ offset + 2 ] = this.b;
- morphTargetsNormal = [];
+ return array;
- for ( var i = 0; i < morphNormalsLength; i ++ ) {
+ }
- morphTargetsNormal[ i ] = {
- name: morphNormals[ i ].name,
- data: []
- };
+ fromBufferAttribute( attribute, index ) {
- }
+ this.r = attribute.getX( index );
+ this.g = attribute.getY( index );
+ this.b = attribute.getZ( index );
- this.morphTargets.normal = morphTargetsNormal;
+ return this;
- }
+ }
- // skins
+ toJSON() {
- var skinIndices = geometry.skinIndices;
- var skinWeights = geometry.skinWeights;
+ return this.getHex();
- var hasSkinIndices = skinIndices.length === vertices.length;
- var hasSkinWeights = skinWeights.length === vertices.length;
+ }
- //
+ *[ Symbol.iterator ]() {
- if ( vertices.length > 0 && faces.length === 0 ) {
+ yield this.r;
+ yield this.g;
+ yield this.b;
- console.error( 'THREE.DirectGeometry: Faceless geometries are not supported.' );
+ }
- }
+}
- for ( var i = 0; i < faces.length; i ++ ) {
+const _color = /*@__PURE__*/ new Color();
- var face = faces[ i ];
+Color.NAMES = _colorKeywords;
- this.vertices.push( vertices[ face.a ], vertices[ face.b ], vertices[ face.c ] );
+class MeshBasicMaterial extends Material {
- var vertexNormals = face.vertexNormals;
+ constructor( parameters ) {
- if ( vertexNormals.length === 3 ) {
+ super();
- this.normals.push( vertexNormals[ 0 ], vertexNormals[ 1 ], vertexNormals[ 2 ] );
+ this.isMeshBasicMaterial = true;
- } else {
+ this.type = 'MeshBasicMaterial';
- var normal = face.normal;
+ this.color = new Color( 0xffffff ); // emissive
- this.normals.push( normal, normal, normal );
+ this.map = null;
- }
+ this.lightMap = null;
+ this.lightMapIntensity = 1.0;
- var vertexColors = face.vertexColors;
+ this.aoMap = null;
+ this.aoMapIntensity = 1.0;
- if ( vertexColors.length === 3 ) {
+ this.specularMap = null;
- this.colors.push( vertexColors[ 0 ], vertexColors[ 1 ], vertexColors[ 2 ] );
+ this.alphaMap = null;
- } else {
+ this.envMap = null;
+ this.combine = MultiplyOperation;
+ this.reflectivity = 1;
+ this.refractionRatio = 0.98;
- var color = face.color;
+ this.wireframe = false;
+ this.wireframeLinewidth = 1;
+ this.wireframeLinecap = 'round';
+ this.wireframeLinejoin = 'round';
- this.colors.push( color, color, color );
+ this.fog = true;
- }
+ this.setValues( parameters );
- if ( hasFaceVertexUv === true ) {
+ }
- var vertexUvs = faceVertexUvs[ 0 ][ i ];
+ copy( source ) {
- if ( vertexUvs !== undefined ) {
+ super.copy( source );
- this.uvs.push( vertexUvs[ 0 ], vertexUvs[ 1 ], vertexUvs[ 2 ] );
+ this.color.copy( source.color );
- } else {
+ this.map = source.map;
- console.warn( 'THREE.DirectGeometry.fromGeometry(): Undefined vertexUv ', i );
+ this.lightMap = source.lightMap;
+ this.lightMapIntensity = source.lightMapIntensity;
- this.uvs.push( new Vector2(), new Vector2(), new Vector2() );
+ this.aoMap = source.aoMap;
+ this.aoMapIntensity = source.aoMapIntensity;
- }
+ this.specularMap = source.specularMap;
- }
+ this.alphaMap = source.alphaMap;
- if ( hasFaceVertexUv2 === true ) {
+ this.envMap = source.envMap;
+ this.combine = source.combine;
+ this.reflectivity = source.reflectivity;
+ this.refractionRatio = source.refractionRatio;
- var vertexUvs = faceVertexUvs[ 1 ][ i ];
+ this.wireframe = source.wireframe;
+ this.wireframeLinewidth = source.wireframeLinewidth;
+ this.wireframeLinecap = source.wireframeLinecap;
+ this.wireframeLinejoin = source.wireframeLinejoin;
- if ( vertexUvs !== undefined ) {
+ this.fog = source.fog;
- this.uvs2.push( vertexUvs[ 0 ], vertexUvs[ 1 ], vertexUvs[ 2 ] );
+ return this;
- } else {
+ }
- console.warn( 'THREE.DirectGeometry.fromGeometry(): Undefined vertexUv2 ', i );
+}
- this.uvs2.push( new Vector2(), new Vector2(), new Vector2() );
+// Fast Half Float Conversions, http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf
- }
+const _tables = /*@__PURE__*/ _generateTables();
- }
+function _generateTables() {
- // morphs
+ // float32 to float16 helpers
- for ( var j = 0; j < morphTargetsLength; j ++ ) {
+ const buffer = new ArrayBuffer( 4 );
+ const floatView = new Float32Array( buffer );
+ const uint32View = new Uint32Array( buffer );
- var morphTarget = morphTargets[ j ].vertices;
+ const baseTable = new Uint32Array( 512 );
+ const shiftTable = new Uint32Array( 512 );
- morphTargetsPosition[ j ].data.push( morphTarget[ face.a ], morphTarget[ face.b ], morphTarget[ face.c ] );
+ for ( let i = 0; i < 256; ++ i ) {
- }
+ const e = i - 127;
- for ( var j = 0; j < morphNormalsLength; j ++ ) {
+ // very small number (0, -0)
- var morphNormal = morphNormals[ j ].vertexNormals[ i ];
+ if ( e < - 27 ) {
- morphTargetsNormal[ j ].data.push( morphNormal.a, morphNormal.b, morphNormal.c );
+ baseTable[ i ] = 0x0000;
+ baseTable[ i | 0x100 ] = 0x8000;
+ shiftTable[ i ] = 24;
+ shiftTable[ i | 0x100 ] = 24;
- }
+ // small number (denorm)
- // skins
+ } else if ( e < - 14 ) {
- if ( hasSkinIndices ) {
+ baseTable[ i ] = 0x0400 >> ( - e - 14 );
+ baseTable[ i | 0x100 ] = ( 0x0400 >> ( - e - 14 ) ) | 0x8000;
+ shiftTable[ i ] = - e - 1;
+ shiftTable[ i | 0x100 ] = - e - 1;
- this.skinIndices.push( skinIndices[ face.a ], skinIndices[ face.b ], skinIndices[ face.c ] );
+ // normal number
- }
+ } else if ( e <= 15 ) {
- if ( hasSkinWeights ) {
+ baseTable[ i ] = ( e + 15 ) << 10;
+ baseTable[ i | 0x100 ] = ( ( e + 15 ) << 10 ) | 0x8000;
+ shiftTable[ i ] = 13;
+ shiftTable[ i | 0x100 ] = 13;
- this.skinWeights.push( skinWeights[ face.a ], skinWeights[ face.b ], skinWeights[ face.c ] );
+ // large number (Infinity, -Infinity)
- }
+ } else if ( e < 128 ) {
- }
-
- this.computeGroups( geometry );
+ baseTable[ i ] = 0x7c00;
+ baseTable[ i | 0x100 ] = 0xfc00;
+ shiftTable[ i ] = 24;
+ shiftTable[ i | 0x100 ] = 24;
- this.verticesNeedUpdate = geometry.verticesNeedUpdate;
- this.normalsNeedUpdate = geometry.normalsNeedUpdate;
- this.colorsNeedUpdate = geometry.colorsNeedUpdate;
- this.uvsNeedUpdate = geometry.uvsNeedUpdate;
- this.groupsNeedUpdate = geometry.groupsNeedUpdate;
+ // stay (NaN, Infinity, -Infinity)
- if ( geometry.boundingSphere !== null ) {
-
- this.boundingSphere = geometry.boundingSphere.clone();
+ } else {
- }
+ baseTable[ i ] = 0x7c00;
+ baseTable[ i | 0x100 ] = 0xfc00;
+ shiftTable[ i ] = 13;
+ shiftTable[ i | 0x100 ] = 13;
- if ( geometry.boundingBox !== null ) {
+ }
- this.boundingBox = geometry.boundingBox.clone();
+ }
- }
+ // float16 to float32 helpers
- return this;
+ const mantissaTable = new Uint32Array( 2048 );
+ const exponentTable = new Uint32Array( 64 );
+ const offsetTable = new Uint32Array( 64 );
- }
+ for ( let i = 1; i < 1024; ++ i ) {
- } );
+ let m = i << 13; // zero pad mantissa bits
+ let e = 0; // zero exponent
- /**
- * @author mrdoob / http://mrdoob.com/
- */
+ // normalized
+ while ( ( m & 0x00800000 ) === 0 ) {
- function arrayMax( array ) {
+ m <<= 1;
+ e -= 0x00800000; // decrement exponent
- if ( array.length === 0 ) return - Infinity;
+ }
- var max = array[ 0 ];
+ m &= ~ 0x00800000; // clear leading 1 bit
+ e += 0x38800000; // adjust bias
- for ( var i = 1, l = array.length; i < l; ++ i ) {
+ mantissaTable[ i ] = m | e;
- if ( array[ i ] > max ) max = array[ i ];
+ }
- }
+ for ( let i = 1024; i < 2048; ++ i ) {
- return max;
+ mantissaTable[ i ] = 0x38000000 + ( ( i - 1024 ) << 13 );
}
- /**
- * @author alteredq / http://alteredqualia.com/
- * @author mrdoob / http://mrdoob.com/
- */
+ for ( let i = 1; i < 31; ++ i ) {
- var _bufferGeometryId = 1; // BufferGeometry uses odd numbers as Id
+ exponentTable[ i ] = i << 23;
- var _m1$2 = new Matrix4();
- var _obj = new Object3D();
- var _offset = new Vector3();
- var _box$1 = new Box3();
- var _boxMorphTargets = new Box3();
- var _vector$4 = new Vector3();
-
- function BufferGeometry() {
+ }
- Object.defineProperty( this, 'id', { value: _bufferGeometryId += 2 } );
+ exponentTable[ 31 ] = 0x47800000;
+ exponentTable[ 32 ] = 0x80000000;
- this.uuid = _Math.generateUUID();
+ for ( let i = 33; i < 63; ++ i ) {
- this.name = '';
- this.type = 'BufferGeometry';
+ exponentTable[ i ] = 0x80000000 + ( ( i - 32 ) << 23 );
- this.index = null;
- this.attributes = {};
+ }
- this.morphAttributes = {};
+ exponentTable[ 63 ] = 0xc7800000;
- this.groups = [];
+ for ( let i = 1; i < 64; ++ i ) {
- this.boundingBox = null;
- this.boundingSphere = null;
+ if ( i !== 32 ) {
- this.drawRange = { start: 0, count: Infinity };
+ offsetTable[ i ] = 1024;
- this.userData = {};
+ }
}
- BufferGeometry.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
+ return {
+ floatView: floatView,
+ uint32View: uint32View,
+ baseTable: baseTable,
+ shiftTable: shiftTable,
+ mantissaTable: mantissaTable,
+ exponentTable: exponentTable,
+ offsetTable: offsetTable
+ };
- constructor: BufferGeometry,
+}
- isBufferGeometry: true,
+// float32 to float16
- getIndex: function () {
+function toHalfFloat( val ) {
- return this.index;
+ if ( Math.abs( val ) > 65504 ) console.warn( 'THREE.DataUtils.toHalfFloat(): Value out of range.' );
- },
+ val = clamp( val, - 65504, 65504 );
- setIndex: function ( index ) {
+ _tables.floatView[ 0 ] = val;
+ const f = _tables.uint32View[ 0 ];
+ const e = ( f >> 23 ) & 0x1ff;
+ return _tables.baseTable[ e ] + ( ( f & 0x007fffff ) >> _tables.shiftTable[ e ] );
- if ( Array.isArray( index ) ) {
+}
- this.index = new ( arrayMax( index ) > 65535 ? Uint32BufferAttribute : Uint16BufferAttribute )( index, 1 );
+// float16 to float32
- } else {
+function fromHalfFloat( val ) {
- this.index = index;
+ const m = val >> 10;
+ _tables.uint32View[ 0 ] = _tables.mantissaTable[ _tables.offsetTable[ m ] + ( val & 0x3ff ) ] + _tables.exponentTable[ m ];
+ return _tables.floatView[ 0 ];
- }
+}
- },
+const DataUtils = {
+ toHalfFloat: toHalfFloat,
+ fromHalfFloat: fromHalfFloat,
+};
- addAttribute: function ( name, attribute ) {
+const _vector$8 = /*@__PURE__*/ new Vector3();
+const _vector2$1 = /*@__PURE__*/ new Vector2();
- if ( ! ( attribute && attribute.isBufferAttribute ) && ! ( attribute && attribute.isInterleavedBufferAttribute ) ) {
+class BufferAttribute {
- console.warn( 'THREE.BufferGeometry: .addAttribute() now expects ( name, attribute ).' );
+ constructor( array, itemSize, normalized = false ) {
- return this.addAttribute( name, new BufferAttribute( arguments[ 1 ], arguments[ 2 ] ) );
+ if ( Array.isArray( array ) ) {
- }
+ throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' );
- if ( name === 'index' ) {
+ }
- console.warn( 'THREE.BufferGeometry.addAttribute: Use .setIndex() for index attribute.' );
- this.setIndex( attribute );
+ this.isBufferAttribute = true;
- return this;
+ this.name = '';
- }
+ this.array = array;
+ this.itemSize = itemSize;
+ this.count = array !== undefined ? array.length / itemSize : 0;
+ this.normalized = normalized;
- this.attributes[ name ] = attribute;
+ this.usage = StaticDrawUsage;
+ this.updateRange = { offset: 0, count: - 1 };
+ this.gpuType = FloatType;
- return this;
+ this.version = 0;
- },
+ }
- getAttribute: function ( name ) {
+ onUploadCallback() {}
- return this.attributes[ name ];
+ set needsUpdate( value ) {
- },
+ if ( value === true ) this.version ++;
- removeAttribute: function ( name ) {
+ }
- delete this.attributes[ name ];
+ setUsage( value ) {
- return this;
+ this.usage = value;
- },
+ return this;
- addGroup: function ( start, count, materialIndex ) {
+ }
- this.groups.push( {
+ copy( source ) {
- start: start,
- count: count,
- materialIndex: materialIndex !== undefined ? materialIndex : 0
+ this.name = source.name;
+ this.array = new source.array.constructor( source.array );
+ this.itemSize = source.itemSize;
+ this.count = source.count;
+ this.normalized = source.normalized;
- } );
+ this.usage = source.usage;
+ this.gpuType = source.gpuType;
- },
+ return this;
- clearGroups: function () {
+ }
- this.groups = [];
+ copyAt( index1, attribute, index2 ) {
- },
+ index1 *= this.itemSize;
+ index2 *= attribute.itemSize;
- setDrawRange: function ( start, count ) {
+ for ( let i = 0, l = this.itemSize; i < l; i ++ ) {
- this.drawRange.start = start;
- this.drawRange.count = count;
+ this.array[ index1 + i ] = attribute.array[ index2 + i ];
- },
+ }
- applyMatrix: function ( matrix ) {
+ return this;
- var position = this.attributes.position;
+ }
- if ( position !== undefined ) {
+ copyArray( array ) {
- matrix.applyToBufferAttribute( position );
- position.needsUpdate = true;
+ this.array.set( array );
- }
+ return this;
- var normal = this.attributes.normal;
+ }
+
+ applyMatrix3( m ) {
- if ( normal !== undefined ) {
+ if ( this.itemSize === 2 ) {
- var normalMatrix = new Matrix3().getNormalMatrix( matrix );
+ for ( let i = 0, l = this.count; i < l; i ++ ) {
- normalMatrix.applyToBufferAttribute( normal );
- normal.needsUpdate = true;
+ _vector2$1.fromBufferAttribute( this, i );
+ _vector2$1.applyMatrix3( m );
+
+ this.setXY( i, _vector2$1.x, _vector2$1.y );
}
- var tangent = this.attributes.tangent;
+ } else if ( this.itemSize === 3 ) {
- if ( tangent !== undefined ) {
+ for ( let i = 0, l = this.count; i < l; i ++ ) {
- var normalMatrix = new Matrix3().getNormalMatrix( matrix );
+ _vector$8.fromBufferAttribute( this, i );
+ _vector$8.applyMatrix3( m );
- // Tangent is vec4, but the '.w' component is a sign value (+1/-1).
- normalMatrix.applyToBufferAttribute( tangent );
- tangent.needsUpdate = true;
+ this.setXYZ( i, _vector$8.x, _vector$8.y, _vector$8.z );
}
- if ( this.boundingBox !== null ) {
+ }
- this.computeBoundingBox();
+ return this;
- }
+ }
- if ( this.boundingSphere !== null ) {
+ applyMatrix4( m ) {
- this.computeBoundingSphere();
+ for ( let i = 0, l = this.count; i < l; i ++ ) {
- }
+ _vector$8.fromBufferAttribute( this, i );
- return this;
+ _vector$8.applyMatrix4( m );
- },
+ this.setXYZ( i, _vector$8.x, _vector$8.y, _vector$8.z );
- rotateX: function ( angle ) {
+ }
- // rotate geometry around world x-axis
+ return this;
- _m1$2.makeRotationX( angle );
+ }
- this.applyMatrix( _m1$2 );
+ applyNormalMatrix( m ) {
- return this;
+ for ( let i = 0, l = this.count; i < l; i ++ ) {
- },
+ _vector$8.fromBufferAttribute( this, i );
- rotateY: function ( angle ) {
+ _vector$8.applyNormalMatrix( m );
- // rotate geometry around world y-axis
+ this.setXYZ( i, _vector$8.x, _vector$8.y, _vector$8.z );
- _m1$2.makeRotationY( angle );
+ }
- this.applyMatrix( _m1$2 );
+ return this;
- return this;
+ }
- },
+ transformDirection( m ) {
- rotateZ: function ( angle ) {
+ for ( let i = 0, l = this.count; i < l; i ++ ) {
- // rotate geometry around world z-axis
+ _vector$8.fromBufferAttribute( this, i );
- _m1$2.makeRotationZ( angle );
+ _vector$8.transformDirection( m );
- this.applyMatrix( _m1$2 );
+ this.setXYZ( i, _vector$8.x, _vector$8.y, _vector$8.z );
- return this;
+ }
- },
+ return this;
- translate: function ( x, y, z ) {
+ }
- // translate geometry
+ set( value, offset = 0 ) {
- _m1$2.makeTranslation( x, y, z );
+ // Matching BufferAttribute constructor, do not normalize the array.
+ this.array.set( value, offset );
- this.applyMatrix( _m1$2 );
+ return this;
- return this;
+ }
- },
+ getComponent( index, component ) {
- scale: function ( x, y, z ) {
+ let value = this.array[ index * this.itemSize + component ];
- // scale geometry
+ if ( this.normalized ) value = denormalize( value, this.array );
- _m1$2.makeScale( x, y, z );
+ return value;
- this.applyMatrix( _m1$2 );
+ }
- return this;
+ setComponent( index, component, value ) {
- },
+ if ( this.normalized ) value = normalize( value, this.array );
- lookAt: function ( vector ) {
+ this.array[ index * this.itemSize + component ] = value;
- _obj.lookAt( vector );
+ return this;
- _obj.updateMatrix();
+ }
- this.applyMatrix( _obj.matrix );
+ getX( index ) {
- return this;
+ let x = this.array[ index * this.itemSize ];
- },
+ if ( this.normalized ) x = denormalize( x, this.array );
- center: function () {
+ return x;
- this.computeBoundingBox();
+ }
- this.boundingBox.getCenter( _offset ).negate();
+ setX( index, x ) {
- this.translate( _offset.x, _offset.y, _offset.z );
+ if ( this.normalized ) x = normalize( x, this.array );
- return this;
+ this.array[ index * this.itemSize ] = x;
- },
+ return this;
- setFromObject: function ( object ) {
+ }
- // console.log( 'THREE.BufferGeometry.setFromObject(). Converting', object, this );
+ getY( index ) {
- var geometry = object.geometry;
+ let y = this.array[ index * this.itemSize + 1 ];
- if ( object.isPoints || object.isLine ) {
+ if ( this.normalized ) y = denormalize( y, this.array );
- var positions = new Float32BufferAttribute( geometry.vertices.length * 3, 3 );
- var colors = new Float32BufferAttribute( geometry.colors.length * 3, 3 );
+ return y;
- this.addAttribute( 'position', positions.copyVector3sArray( geometry.vertices ) );
- this.addAttribute( 'color', colors.copyColorsArray( geometry.colors ) );
+ }
- if ( geometry.lineDistances && geometry.lineDistances.length === geometry.vertices.length ) {
+ setY( index, y ) {
- var lineDistances = new Float32BufferAttribute( geometry.lineDistances.length, 1 );
+ if ( this.normalized ) y = normalize( y, this.array );
- this.addAttribute( 'lineDistance', lineDistances.copyArray( geometry.lineDistances ) );
+ this.array[ index * this.itemSize + 1 ] = y;
- }
+ return this;
- if ( geometry.boundingSphere !== null ) {
+ }
- this.boundingSphere = geometry.boundingSphere.clone();
+ getZ( index ) {
- }
+ let z = this.array[ index * this.itemSize + 2 ];
- if ( geometry.boundingBox !== null ) {
+ if ( this.normalized ) z = denormalize( z, this.array );
- this.boundingBox = geometry.boundingBox.clone();
+ return z;
- }
+ }
- } else if ( object.isMesh ) {
+ setZ( index, z ) {
- if ( geometry && geometry.isGeometry ) {
+ if ( this.normalized ) z = normalize( z, this.array );
- this.fromGeometry( geometry );
+ this.array[ index * this.itemSize + 2 ] = z;
- }
+ return this;
- }
+ }
- return this;
+ getW( index ) {
- },
+ let w = this.array[ index * this.itemSize + 3 ];
- setFromPoints: function ( points ) {
+ if ( this.normalized ) w = denormalize( w, this.array );
- var position = [];
+ return w;
- for ( var i = 0, l = points.length; i < l; i ++ ) {
+ }
- var point = points[ i ];
- position.push( point.x, point.y, point.z || 0 );
+ setW( index, w ) {
- }
+ if ( this.normalized ) w = normalize( w, this.array );
- this.addAttribute( 'position', new Float32BufferAttribute( position, 3 ) );
+ this.array[ index * this.itemSize + 3 ] = w;
- return this;
+ return this;
- },
+ }
- updateFromObject: function ( object ) {
+ setXY( index, x, y ) {
- var geometry = object.geometry;
+ index *= this.itemSize;
- if ( object.isMesh ) {
+ if ( this.normalized ) {
- var direct = geometry.__directGeometry;
+ x = normalize( x, this.array );
+ y = normalize( y, this.array );
- if ( geometry.elementsNeedUpdate === true ) {
+ }
- direct = undefined;
- geometry.elementsNeedUpdate = false;
+ this.array[ index + 0 ] = x;
+ this.array[ index + 1 ] = y;
- }
+ return this;
- if ( direct === undefined ) {
+ }
- return this.fromGeometry( geometry );
+ setXYZ( index, x, y, z ) {
- }
+ index *= this.itemSize;
- direct.verticesNeedUpdate = geometry.verticesNeedUpdate;
- direct.normalsNeedUpdate = geometry.normalsNeedUpdate;
- direct.colorsNeedUpdate = geometry.colorsNeedUpdate;
- direct.uvsNeedUpdate = geometry.uvsNeedUpdate;
- direct.groupsNeedUpdate = geometry.groupsNeedUpdate;
+ if ( this.normalized ) {
- geometry.verticesNeedUpdate = false;
- geometry.normalsNeedUpdate = false;
- geometry.colorsNeedUpdate = false;
- geometry.uvsNeedUpdate = false;
- geometry.groupsNeedUpdate = false;
+ x = normalize( x, this.array );
+ y = normalize( y, this.array );
+ z = normalize( z, this.array );
- geometry = direct;
+ }
- }
+ this.array[ index + 0 ] = x;
+ this.array[ index + 1 ] = y;
+ this.array[ index + 2 ] = z;
- var attribute;
+ return this;
- if ( geometry.verticesNeedUpdate === true ) {
+ }
- attribute = this.attributes.position;
+ setXYZW( index, x, y, z, w ) {
- if ( attribute !== undefined ) {
+ index *= this.itemSize;
- attribute.copyVector3sArray( geometry.vertices );
- attribute.needsUpdate = true;
+ if ( this.normalized ) {
- }
+ x = normalize( x, this.array );
+ y = normalize( y, this.array );
+ z = normalize( z, this.array );
+ w = normalize( w, this.array );
- geometry.verticesNeedUpdate = false;
+ }
- }
+ this.array[ index + 0 ] = x;
+ this.array[ index + 1 ] = y;
+ this.array[ index + 2 ] = z;
+ this.array[ index + 3 ] = w;
- if ( geometry.normalsNeedUpdate === true ) {
+ return this;
- attribute = this.attributes.normal;
+ }
- if ( attribute !== undefined ) {
+ onUpload( callback ) {
- attribute.copyVector3sArray( geometry.normals );
- attribute.needsUpdate = true;
+ this.onUploadCallback = callback;
- }
+ return this;
- geometry.normalsNeedUpdate = false;
+ }
- }
+ clone() {
- if ( geometry.colorsNeedUpdate === true ) {
+ return new this.constructor( this.array, this.itemSize ).copy( this );
- attribute = this.attributes.color;
+ }
- if ( attribute !== undefined ) {
+ toJSON() {
- attribute.copyColorsArray( geometry.colors );
- attribute.needsUpdate = true;
+ const data = {
+ itemSize: this.itemSize,
+ type: this.array.constructor.name,
+ array: Array.from( this.array ),
+ normalized: this.normalized
+ };
- }
+ if ( this.name !== '' ) data.name = this.name;
+ if ( this.usage !== StaticDrawUsage ) data.usage = this.usage;
+ if ( this.updateRange.offset !== 0 || this.updateRange.count !== - 1 ) data.updateRange = this.updateRange;
- geometry.colorsNeedUpdate = false;
+ return data;
- }
+ }
- if ( geometry.uvsNeedUpdate ) {
+}
- attribute = this.attributes.uv;
+//
- if ( attribute !== undefined ) {
+class Int8BufferAttribute extends BufferAttribute {
- attribute.copyVector2sArray( geometry.uvs );
- attribute.needsUpdate = true;
+ constructor( array, itemSize, normalized ) {
- }
+ super( new Int8Array( array ), itemSize, normalized );
- geometry.uvsNeedUpdate = false;
+ }
- }
+}
- if ( geometry.lineDistancesNeedUpdate ) {
+class Uint8BufferAttribute extends BufferAttribute {
- attribute = this.attributes.lineDistance;
+ constructor( array, itemSize, normalized ) {
- if ( attribute !== undefined ) {
+ super( new Uint8Array( array ), itemSize, normalized );
- attribute.copyArray( geometry.lineDistances );
- attribute.needsUpdate = true;
+ }
- }
+}
- geometry.lineDistancesNeedUpdate = false;
+class Uint8ClampedBufferAttribute extends BufferAttribute {
- }
+ constructor( array, itemSize, normalized ) {
- if ( geometry.groupsNeedUpdate ) {
+ super( new Uint8ClampedArray( array ), itemSize, normalized );
- geometry.computeGroups( object.geometry );
- this.groups = geometry.groups;
+ }
- geometry.groupsNeedUpdate = false;
+}
- }
+class Int16BufferAttribute extends BufferAttribute {
- return this;
+ constructor( array, itemSize, normalized ) {
- },
+ super( new Int16Array( array ), itemSize, normalized );
- fromGeometry: function ( geometry ) {
+ }
- geometry.__directGeometry = new DirectGeometry().fromGeometry( geometry );
+}
- return this.fromDirectGeometry( geometry.__directGeometry );
+class Uint16BufferAttribute extends BufferAttribute {
- },
+ constructor( array, itemSize, normalized ) {
- fromDirectGeometry: function ( geometry ) {
+ super( new Uint16Array( array ), itemSize, normalized );
- var positions = new Float32Array( geometry.vertices.length * 3 );
- this.addAttribute( 'position', new BufferAttribute( positions, 3 ).copyVector3sArray( geometry.vertices ) );
+ }
- if ( geometry.normals.length > 0 ) {
+}
- var normals = new Float32Array( geometry.normals.length * 3 );
- this.addAttribute( 'normal', new BufferAttribute( normals, 3 ).copyVector3sArray( geometry.normals ) );
+class Int32BufferAttribute extends BufferAttribute {
- }
+ constructor( array, itemSize, normalized ) {
- if ( geometry.colors.length > 0 ) {
+ super( new Int32Array( array ), itemSize, normalized );
- var colors = new Float32Array( geometry.colors.length * 3 );
- this.addAttribute( 'color', new BufferAttribute( colors, 3 ).copyColorsArray( geometry.colors ) );
+ }
- }
+}
- if ( geometry.uvs.length > 0 ) {
+class Uint32BufferAttribute extends BufferAttribute {
- var uvs = new Float32Array( geometry.uvs.length * 2 );
- this.addAttribute( 'uv', new BufferAttribute( uvs, 2 ).copyVector2sArray( geometry.uvs ) );
+ constructor( array, itemSize, normalized ) {
- }
+ super( new Uint32Array( array ), itemSize, normalized );
- if ( geometry.uvs2.length > 0 ) {
+ }
- var uvs2 = new Float32Array( geometry.uvs2.length * 2 );
- this.addAttribute( 'uv2', new BufferAttribute( uvs2, 2 ).copyVector2sArray( geometry.uvs2 ) );
+}
- }
+class Float16BufferAttribute extends BufferAttribute {
- // groups
+ constructor( array, itemSize, normalized ) {
- this.groups = geometry.groups;
+ super( new Uint16Array( array ), itemSize, normalized );
- // morphs
+ this.isFloat16BufferAttribute = true;
- for ( var name in geometry.morphTargets ) {
+ }
- var array = [];
- var morphTargets = geometry.morphTargets[ name ];
+ getX( index ) {
- for ( var i = 0, l = morphTargets.length; i < l; i ++ ) {
+ let x = fromHalfFloat( this.array[ index * this.itemSize ] );
- var morphTarget = morphTargets[ i ];
+ if ( this.normalized ) x = denormalize( x, this.array );
- var attribute = new Float32BufferAttribute( morphTarget.data.length * 3, 3 );
- attribute.name = morphTarget.name;
+ return x;
- array.push( attribute.copyVector3sArray( morphTarget.data ) );
+ }
- }
+ setX( index, x ) {
- this.morphAttributes[ name ] = array;
+ if ( this.normalized ) x = normalize( x, this.array );
- }
+ this.array[ index * this.itemSize ] = toHalfFloat( x );
- // skinning
+ return this;
- if ( geometry.skinIndices.length > 0 ) {
+ }
- var skinIndices = new Float32BufferAttribute( geometry.skinIndices.length * 4, 4 );
- this.addAttribute( 'skinIndex', skinIndices.copyVector4sArray( geometry.skinIndices ) );
+ getY( index ) {
- }
+ let y = fromHalfFloat( this.array[ index * this.itemSize + 1 ] );
- if ( geometry.skinWeights.length > 0 ) {
+ if ( this.normalized ) y = denormalize( y, this.array );
- var skinWeights = new Float32BufferAttribute( geometry.skinWeights.length * 4, 4 );
- this.addAttribute( 'skinWeight', skinWeights.copyVector4sArray( geometry.skinWeights ) );
+ return y;
- }
+ }
- //
+ setY( index, y ) {
- if ( geometry.boundingSphere !== null ) {
+ if ( this.normalized ) y = normalize( y, this.array );
- this.boundingSphere = geometry.boundingSphere.clone();
+ this.array[ index * this.itemSize + 1 ] = toHalfFloat( y );
- }
+ return this;
- if ( geometry.boundingBox !== null ) {
+ }
- this.boundingBox = geometry.boundingBox.clone();
+ getZ( index ) {
- }
+ let z = fromHalfFloat( this.array[ index * this.itemSize + 2 ] );
- return this;
+ if ( this.normalized ) z = denormalize( z, this.array );
- },
+ return z;
- computeBoundingBox: function () {
+ }
- if ( this.boundingBox === null ) {
+ setZ( index, z ) {
- this.boundingBox = new Box3();
+ if ( this.normalized ) z = normalize( z, this.array );
- }
+ this.array[ index * this.itemSize + 2 ] = toHalfFloat( z );
- var position = this.attributes.position;
- var morphAttributesPosition = this.morphAttributes.position;
+ return this;
- if ( position !== undefined ) {
+ }
- this.boundingBox.setFromBufferAttribute( position );
+ getW( index ) {
- // process morph attributes if present
+ let w = fromHalfFloat( this.array[ index * this.itemSize + 3 ] );
- if ( morphAttributesPosition ) {
+ if ( this.normalized ) w = denormalize( w, this.array );
- for ( var i = 0, il = morphAttributesPosition.length; i < il; i ++ ) {
+ return w;
- var morphAttribute = morphAttributesPosition[ i ];
- _box$1.setFromBufferAttribute( morphAttribute );
+ }
- this.boundingBox.expandByPoint( _box$1.min );
- this.boundingBox.expandByPoint( _box$1.max );
+ setW( index, w ) {
- }
+ if ( this.normalized ) w = normalize( w, this.array );
- }
+ this.array[ index * this.itemSize + 3 ] = toHalfFloat( w );
- } else {
+ return this;
- this.boundingBox.makeEmpty();
+ }
- }
+ setXY( index, x, y ) {
- if ( isNaN( this.boundingBox.min.x ) || isNaN( this.boundingBox.min.y ) || isNaN( this.boundingBox.min.z ) ) {
+ index *= this.itemSize;
- console.error( 'THREE.BufferGeometry.computeBoundingBox: Computed min/max have NaN values. The "position" attribute is likely to have NaN values.', this );
+ if ( this.normalized ) {
- }
+ x = normalize( x, this.array );
+ y = normalize( y, this.array );
- },
+ }
- computeBoundingSphere: function () {
+ this.array[ index + 0 ] = toHalfFloat( x );
+ this.array[ index + 1 ] = toHalfFloat( y );
- if ( this.boundingSphere === null ) {
+ return this;
- this.boundingSphere = new Sphere();
+ }
- }
+ setXYZ( index, x, y, z ) {
- var position = this.attributes.position;
- var morphAttributesPosition = this.morphAttributes.position;
+ index *= this.itemSize;
- if ( position ) {
+ if ( this.normalized ) {
- // first, find the center of the bounding sphere
+ x = normalize( x, this.array );
+ y = normalize( y, this.array );
+ z = normalize( z, this.array );
- var center = this.boundingSphere.center;
+ }
- _box$1.setFromBufferAttribute( position );
+ this.array[ index + 0 ] = toHalfFloat( x );
+ this.array[ index + 1 ] = toHalfFloat( y );
+ this.array[ index + 2 ] = toHalfFloat( z );
- // process morph attributes if present
+ return this;
- if ( morphAttributesPosition ) {
+ }
- for ( var i = 0, il = morphAttributesPosition.length; i < il; i ++ ) {
+ setXYZW( index, x, y, z, w ) {
- var morphAttribute = morphAttributesPosition[ i ];
- _boxMorphTargets.setFromBufferAttribute( morphAttribute );
+ index *= this.itemSize;
- _box$1.expandByPoint( _boxMorphTargets.min );
- _box$1.expandByPoint( _boxMorphTargets.max );
+ if ( this.normalized ) {
- }
+ x = normalize( x, this.array );
+ y = normalize( y, this.array );
+ z = normalize( z, this.array );
+ w = normalize( w, this.array );
- }
+ }
- _box$1.getCenter( center );
+ this.array[ index + 0 ] = toHalfFloat( x );
+ this.array[ index + 1 ] = toHalfFloat( y );
+ this.array[ index + 2 ] = toHalfFloat( z );
+ this.array[ index + 3 ] = toHalfFloat( w );
- // second, try to find a boundingSphere with a radius smaller than the
- // boundingSphere of the boundingBox: sqrt(3) smaller in the best case
+ return this;
- var maxRadiusSq = 0;
+ }
- for ( var i = 0, il = position.count; i < il; i ++ ) {
+}
- _vector$4.fromBufferAttribute( position, i );
- maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$4 ) );
+class Float32BufferAttribute extends BufferAttribute {
- }
+ constructor( array, itemSize, normalized ) {
- // process morph attributes if present
+ super( new Float32Array( array ), itemSize, normalized );
- if ( morphAttributesPosition ) {
+ }
- for ( var i = 0, il = morphAttributesPosition.length; i < il; i ++ ) {
+}
- var morphAttribute = morphAttributesPosition[ i ];
+class Float64BufferAttribute extends BufferAttribute {
- for ( var j = 0, jl = morphAttribute.count; j < jl; j ++ ) {
+ constructor( array, itemSize, normalized ) {
- _vector$4.fromBufferAttribute( morphAttribute, j );
+ super( new Float64Array( array ), itemSize, normalized );
- maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$4 ) );
+ }
- }
+}
- }
+let _id$2 = 0;
- }
+const _m1 = /*@__PURE__*/ new Matrix4();
+const _obj = /*@__PURE__*/ new Object3D();
+const _offset = /*@__PURE__*/ new Vector3();
+const _box$1 = /*@__PURE__*/ new Box3();
+const _boxMorphTargets = /*@__PURE__*/ new Box3();
+const _vector$7 = /*@__PURE__*/ new Vector3();
- this.boundingSphere.radius = Math.sqrt( maxRadiusSq );
+class BufferGeometry extends EventDispatcher {
- if ( isNaN( this.boundingSphere.radius ) ) {
+ constructor() {
- console.error( 'THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The "position" attribute is likely to have NaN values.', this );
+ super();
- }
+ this.isBufferGeometry = true;
- }
+ Object.defineProperty( this, 'id', { value: _id$2 ++ } );
- },
+ this.uuid = generateUUID();
- computeFaceNormals: function () {
+ this.name = '';
+ this.type = 'BufferGeometry';
- // backwards compatibility
+ this.index = null;
+ this.attributes = {};
- },
+ this.morphAttributes = {};
+ this.morphTargetsRelative = false;
- computeVertexNormals: function () {
+ this.groups = [];
- var index = this.index;
- var attributes = this.attributes;
+ this.boundingBox = null;
+ this.boundingSphere = null;
- if ( attributes.position ) {
+ this.drawRange = { start: 0, count: Infinity };
- var positions = attributes.position.array;
+ this.userData = {};
- if ( attributes.normal === undefined ) {
+ }
- this.addAttribute( 'normal', new BufferAttribute( new Float32Array( positions.length ), 3 ) );
+ getIndex() {
- } else {
+ return this.index;
- // reset existing normals to zero
+ }
- var array = attributes.normal.array;
+ setIndex( index ) {
- for ( var i = 0, il = array.length; i < il; i ++ ) {
+ if ( Array.isArray( index ) ) {
- array[ i ] = 0;
+ this.index = new ( arrayNeedsUint32( index ) ? Uint32BufferAttribute : Uint16BufferAttribute )( index, 1 );
- }
+ } else {
- }
+ this.index = index;
- var normals = attributes.normal.array;
+ }
- var vA, vB, vC;
- var pA = new Vector3(), pB = new Vector3(), pC = new Vector3();
- var cb = new Vector3(), ab = new Vector3();
+ return this;
- // indexed elements
+ }
- if ( index ) {
+ getAttribute( name ) {
- var indices = index.array;
+ return this.attributes[ name ];
- for ( var i = 0, il = index.count; i < il; i += 3 ) {
+ }
- vA = indices[ i + 0 ] * 3;
- vB = indices[ i + 1 ] * 3;
- vC = indices[ i + 2 ] * 3;
+ setAttribute( name, attribute ) {
- pA.fromArray( positions, vA );
- pB.fromArray( positions, vB );
- pC.fromArray( positions, vC );
+ this.attributes[ name ] = attribute;
- cb.subVectors( pC, pB );
- ab.subVectors( pA, pB );
- cb.cross( ab );
+ return this;
- normals[ vA ] += cb.x;
- normals[ vA + 1 ] += cb.y;
- normals[ vA + 2 ] += cb.z;
+ }
- normals[ vB ] += cb.x;
- normals[ vB + 1 ] += cb.y;
- normals[ vB + 2 ] += cb.z;
+ deleteAttribute( name ) {
- normals[ vC ] += cb.x;
- normals[ vC + 1 ] += cb.y;
- normals[ vC + 2 ] += cb.z;
+ delete this.attributes[ name ];
- }
+ return this;
- } else {
+ }
- // non-indexed elements (unconnected triangle soup)
+ hasAttribute( name ) {
- for ( var i = 0, il = positions.length; i < il; i += 9 ) {
+ return this.attributes[ name ] !== undefined;
- pA.fromArray( positions, i );
- pB.fromArray( positions, i + 3 );
- pC.fromArray( positions, i + 6 );
+ }
- cb.subVectors( pC, pB );
- ab.subVectors( pA, pB );
- cb.cross( ab );
+ addGroup( start, count, materialIndex = 0 ) {
- normals[ i ] = cb.x;
- normals[ i + 1 ] = cb.y;
- normals[ i + 2 ] = cb.z;
+ this.groups.push( {
- normals[ i + 3 ] = cb.x;
- normals[ i + 4 ] = cb.y;
- normals[ i + 5 ] = cb.z;
+ start: start,
+ count: count,
+ materialIndex: materialIndex
- normals[ i + 6 ] = cb.x;
- normals[ i + 7 ] = cb.y;
- normals[ i + 8 ] = cb.z;
+ } );
- }
+ }
- }
+ clearGroups() {
- this.normalizeNormals();
+ this.groups = [];
- attributes.normal.needsUpdate = true;
+ }
- }
+ setDrawRange( start, count ) {
- },
+ this.drawRange.start = start;
+ this.drawRange.count = count;
- merge: function ( geometry, offset ) {
+ }
- if ( ! ( geometry && geometry.isBufferGeometry ) ) {
+ applyMatrix4( matrix ) {
- console.error( 'THREE.BufferGeometry.merge(): geometry not an instance of THREE.BufferGeometry.', geometry );
- return;
+ const position = this.attributes.position;
- }
+ if ( position !== undefined ) {
- if ( offset === undefined ) {
+ position.applyMatrix4( matrix );
- offset = 0;
+ position.needsUpdate = true;
- console.warn(
- 'THREE.BufferGeometry.merge(): Overwriting original geometry, starting at offset=0. '
- + 'Use BufferGeometryUtils.mergeBufferGeometries() for lossless merge.'
- );
+ }
- }
+ const normal = this.attributes.normal;
- var attributes = this.attributes;
+ if ( normal !== undefined ) {
- for ( var key in attributes ) {
+ const normalMatrix = new Matrix3().getNormalMatrix( matrix );
- if ( geometry.attributes[ key ] === undefined ) continue;
+ normal.applyNormalMatrix( normalMatrix );
- var attribute1 = attributes[ key ];
- var attributeArray1 = attribute1.array;
+ normal.needsUpdate = true;
- var attribute2 = geometry.attributes[ key ];
- var attributeArray2 = attribute2.array;
+ }
- var attributeOffset = attribute2.itemSize * offset;
- var length = Math.min( attributeArray2.length, attributeArray1.length - attributeOffset );
+ const tangent = this.attributes.tangent;
- for ( var i = 0, j = attributeOffset; i < length; i ++, j ++ ) {
+ if ( tangent !== undefined ) {
- attributeArray1[ j ] = attributeArray2[ i ];
+ tangent.transformDirection( matrix );
- }
+ tangent.needsUpdate = true;
- }
+ }
- return this;
+ if ( this.boundingBox !== null ) {
- },
+ this.computeBoundingBox();
- normalizeNormals: function () {
+ }
- var normals = this.attributes.normal;
+ if ( this.boundingSphere !== null ) {
- for ( var i = 0, il = normals.count; i < il; i ++ ) {
+ this.computeBoundingSphere();
- _vector$4.x = normals.getX( i );
- _vector$4.y = normals.getY( i );
- _vector$4.z = normals.getZ( i );
+ }
- _vector$4.normalize();
+ return this;
- normals.setXYZ( i, _vector$4.x, _vector$4.y, _vector$4.z );
+ }
- }
+ applyQuaternion( q ) {
- },
+ _m1.makeRotationFromQuaternion( q );
- toNonIndexed: function () {
+ this.applyMatrix4( _m1 );
- function convertBufferAttribute( attribute, indices ) {
+ return this;
- var array = attribute.array;
- var itemSize = attribute.itemSize;
+ }
- var array2 = new array.constructor( indices.length * itemSize );
+ rotateX( angle ) {
- var index = 0, index2 = 0;
+ // rotate geometry around world x-axis
- for ( var i = 0, l = indices.length; i < l; i ++ ) {
+ _m1.makeRotationX( angle );
- index = indices[ i ] * itemSize;
+ this.applyMatrix4( _m1 );
- for ( var j = 0; j < itemSize; j ++ ) {
+ return this;
- array2[ index2 ++ ] = array[ index ++ ];
+ }
- }
+ rotateY( angle ) {
- }
+ // rotate geometry around world y-axis
- return new BufferAttribute( array2, itemSize );
+ _m1.makeRotationY( angle );
- }
+ this.applyMatrix4( _m1 );
- //
+ return this;
- if ( this.index === null ) {
+ }
- console.warn( 'THREE.BufferGeometry.toNonIndexed(): Geometry is already non-indexed.' );
- return this;
+ rotateZ( angle ) {
- }
+ // rotate geometry around world z-axis
- var geometry2 = new BufferGeometry();
+ _m1.makeRotationZ( angle );
- var indices = this.index.array;
- var attributes = this.attributes;
+ this.applyMatrix4( _m1 );
- // attributes
+ return this;
- for ( var name in attributes ) {
+ }
- var attribute = attributes[ name ];
+ translate( x, y, z ) {
- var newAttribute = convertBufferAttribute( attribute, indices );
+ // translate geometry
- geometry2.addAttribute( name, newAttribute );
+ _m1.makeTranslation( x, y, z );
- }
+ this.applyMatrix4( _m1 );
- // morph attributes
+ return this;
- var morphAttributes = this.morphAttributes;
+ }
- for ( name in morphAttributes ) {
+ scale( x, y, z ) {
- var morphArray = [];
- var morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes
+ // scale geometry
- for ( var i = 0, il = morphAttribute.length; i < il; i ++ ) {
+ _m1.makeScale( x, y, z );
- var attribute = morphAttribute[ i ];
+ this.applyMatrix4( _m1 );
- var newAttribute = convertBufferAttribute( attribute, indices );
+ return this;
- morphArray.push( newAttribute );
+ }
- }
+ lookAt( vector ) {
- geometry2.morphAttributes[ name ] = morphArray;
+ _obj.lookAt( vector );
- }
+ _obj.updateMatrix();
- // groups
+ this.applyMatrix4( _obj.matrix );
- var groups = this.groups;
+ return this;
- for ( var i = 0, l = groups.length; i < l; i ++ ) {
+ }
- var group = groups[ i ];
- geometry2.addGroup( group.start, group.count, group.materialIndex );
+ center() {
- }
+ this.computeBoundingBox();
- return geometry2;
+ this.boundingBox.getCenter( _offset ).negate();
- },
+ this.translate( _offset.x, _offset.y, _offset.z );
- toJSON: function () {
+ return this;
- var data = {
- metadata: {
- version: 4.5,
- type: 'BufferGeometry',
- generator: 'BufferGeometry.toJSON'
- }
- };
+ }
- // standard BufferGeometry serialization
+ setFromPoints( points ) {
- data.uuid = this.uuid;
- data.type = this.type;
- if ( this.name !== '' ) data.name = this.name;
- if ( Object.keys( this.userData ).length > 0 ) data.userData = this.userData;
+ const position = [];
- if ( this.parameters !== undefined ) {
+ for ( let i = 0, l = points.length; i < l; i ++ ) {
- var parameters = this.parameters;
+ const point = points[ i ];
+ position.push( point.x, point.y, point.z || 0 );
- for ( var key in parameters ) {
+ }
- if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ];
+ this.setAttribute( 'position', new Float32BufferAttribute( position, 3 ) );
- }
+ return this;
- return data;
+ }
- }
+ computeBoundingBox() {
- data.data = { attributes: {} };
+ if ( this.boundingBox === null ) {
- var index = this.index;
+ this.boundingBox = new Box3();
- if ( index !== null ) {
+ }
- data.data.index = {
- type: index.array.constructor.name,
- array: Array.prototype.slice.call( index.array )
- };
+ const position = this.attributes.position;
+ const morphAttributesPosition = this.morphAttributes.position;
- }
+ if ( position && position.isGLBufferAttribute ) {
- var attributes = this.attributes;
+ console.error( 'THREE.BufferGeometry.computeBoundingBox(): GLBufferAttribute requires a manual bounding box. Alternatively set "mesh.frustumCulled" to "false".', this );
- for ( var key in attributes ) {
+ this.boundingBox.set(
+ new Vector3( - Infinity, - Infinity, - Infinity ),
+ new Vector3( + Infinity, + Infinity, + Infinity )
+ );
- var attribute = attributes[ key ];
+ return;
- var attributeData = attribute.toJSON();
+ }
- if ( attribute.name !== '' ) attributeData.name = attribute.name;
+ if ( position !== undefined ) {
- data.data.attributes[ key ] = attributeData;
+ this.boundingBox.setFromBufferAttribute( position );
- }
+ // process morph attributes if present
- var morphAttributes = {};
- var hasMorphAttributes = false;
+ if ( morphAttributesPosition ) {
- for ( var key in this.morphAttributes ) {
+ for ( let i = 0, il = morphAttributesPosition.length; i < il; i ++ ) {
- var attributeArray = this.morphAttributes[ key ];
+ const morphAttribute = morphAttributesPosition[ i ];
+ _box$1.setFromBufferAttribute( morphAttribute );
- var array = [];
+ if ( this.morphTargetsRelative ) {
- for ( var i = 0, il = attributeArray.length; i < il; i ++ ) {
+ _vector$7.addVectors( this.boundingBox.min, _box$1.min );
+ this.boundingBox.expandByPoint( _vector$7 );
- var attribute = attributeArray[ i ];
+ _vector$7.addVectors( this.boundingBox.max, _box$1.max );
+ this.boundingBox.expandByPoint( _vector$7 );
- var attributeData = attribute.toJSON();
+ } else {
- if ( attribute.name !== '' ) attributeData.name = attribute.name;
+ this.boundingBox.expandByPoint( _box$1.min );
+ this.boundingBox.expandByPoint( _box$1.max );
- array.push( attributeData );
+ }
}
- if ( array.length > 0 ) {
+ }
- morphAttributes[ key ] = array;
+ } else {
- hasMorphAttributes = true;
+ this.boundingBox.makeEmpty();
- }
+ }
- }
+ if ( isNaN( this.boundingBox.min.x ) || isNaN( this.boundingBox.min.y ) || isNaN( this.boundingBox.min.z ) ) {
- if ( hasMorphAttributes ) data.data.morphAttributes = morphAttributes;
+ console.error( 'THREE.BufferGeometry.computeBoundingBox(): Computed min/max have NaN values. The "position" attribute is likely to have NaN values.', this );
+
+ }
- var groups = this.groups;
+ }
- if ( groups.length > 0 ) {
+ computeBoundingSphere() {
- data.data.groups = JSON.parse( JSON.stringify( groups ) );
+ if ( this.boundingSphere === null ) {
- }
+ this.boundingSphere = new Sphere();
- var boundingSphere = this.boundingSphere;
+ }
- if ( boundingSphere !== null ) {
+ const position = this.attributes.position;
+ const morphAttributesPosition = this.morphAttributes.position;
- data.data.boundingSphere = {
- center: boundingSphere.center.toArray(),
- radius: boundingSphere.radius
- };
+ if ( position && position.isGLBufferAttribute ) {
- }
+ console.error( 'THREE.BufferGeometry.computeBoundingSphere(): GLBufferAttribute requires a manual bounding sphere. Alternatively set "mesh.frustumCulled" to "false".', this );
- return data;
+ this.boundingSphere.set( new Vector3(), Infinity );
- },
+ return;
- clone: function () {
+ }
- /*
- // Handle primitives
+ if ( position ) {
- var parameters = this.parameters;
+ // first, find the center of the bounding sphere
- if ( parameters !== undefined ) {
+ const center = this.boundingSphere.center;
- var values = [];
+ _box$1.setFromBufferAttribute( position );
- for ( var key in parameters ) {
+ // process morph attributes if present
- values.push( parameters[ key ] );
+ if ( morphAttributesPosition ) {
- }
+ for ( let i = 0, il = morphAttributesPosition.length; i < il; i ++ ) {
- var geometry = Object.create( this.constructor.prototype );
- this.constructor.apply( geometry, values );
- return geometry;
+ const morphAttribute = morphAttributesPosition[ i ];
+ _boxMorphTargets.setFromBufferAttribute( morphAttribute );
- }
+ if ( this.morphTargetsRelative ) {
- return new this.constructor().copy( this );
- */
+ _vector$7.addVectors( _box$1.min, _boxMorphTargets.min );
+ _box$1.expandByPoint( _vector$7 );
- return new BufferGeometry().copy( this );
+ _vector$7.addVectors( _box$1.max, _boxMorphTargets.max );
+ _box$1.expandByPoint( _vector$7 );
- },
+ } else {
- copy: function ( source ) {
+ _box$1.expandByPoint( _boxMorphTargets.min );
+ _box$1.expandByPoint( _boxMorphTargets.max );
- var name, i, l;
+ }
- // reset
+ }
- this.index = null;
- this.attributes = {};
- this.morphAttributes = {};
- this.groups = [];
- this.boundingBox = null;
- this.boundingSphere = null;
+ }
- // name
+ _box$1.getCenter( center );
- this.name = source.name;
+ // second, try to find a boundingSphere with a radius smaller than the
+ // boundingSphere of the boundingBox: sqrt(3) smaller in the best case
- // index
+ let maxRadiusSq = 0;
- var index = source.index;
+ for ( let i = 0, il = position.count; i < il; i ++ ) {
- if ( index !== null ) {
+ _vector$7.fromBufferAttribute( position, i );
- this.setIndex( index.clone() );
+ maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$7 ) );
}
- // attributes
+ // process morph attributes if present
- var attributes = source.attributes;
+ if ( morphAttributesPosition ) {
- for ( name in attributes ) {
+ for ( let i = 0, il = morphAttributesPosition.length; i < il; i ++ ) {
- var attribute = attributes[ name ];
- this.addAttribute( name, attribute.clone() );
+ const morphAttribute = morphAttributesPosition[ i ];
+ const morphTargetsRelative = this.morphTargetsRelative;
- }
+ for ( let j = 0, jl = morphAttribute.count; j < jl; j ++ ) {
- // morph attributes
+ _vector$7.fromBufferAttribute( morphAttribute, j );
- var morphAttributes = source.morphAttributes;
+ if ( morphTargetsRelative ) {
- for ( name in morphAttributes ) {
+ _offset.fromBufferAttribute( position, j );
+ _vector$7.add( _offset );
- var array = [];
- var morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes
+ }
- for ( i = 0, l = morphAttribute.length; i < l; i ++ ) {
+ maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$7 ) );
- array.push( morphAttribute[ i ].clone() );
+ }
}
- this.morphAttributes[ name ] = array;
-
}
- // groups
+ this.boundingSphere.radius = Math.sqrt( maxRadiusSq );
- var groups = source.groups;
+ if ( isNaN( this.boundingSphere.radius ) ) {
- for ( i = 0, l = groups.length; i < l; i ++ ) {
-
- var group = groups[ i ];
- this.addGroup( group.start, group.count, group.materialIndex );
+ console.error( 'THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The "position" attribute is likely to have NaN values.', this );
}
- // bounding box
-
- var boundingBox = source.boundingBox;
+ }
- if ( boundingBox !== null ) {
+ }
- this.boundingBox = boundingBox.clone();
+ computeTangents() {
- }
+ const index = this.index;
+ const attributes = this.attributes;
- // bounding sphere
+ // based on http://www.terathon.com/code/tangent.html
+ // (per vertex tangents)
- var boundingSphere = source.boundingSphere;
+ if ( index === null ||
+ attributes.position === undefined ||
+ attributes.normal === undefined ||
+ attributes.uv === undefined ) {
- if ( boundingSphere !== null ) {
+ console.error( 'THREE.BufferGeometry: .computeTangents() failed. Missing required attributes (index, position, normal or uv)' );
+ return;
- this.boundingSphere = boundingSphere.clone();
+ }
- }
+ const indices = index.array;
+ const positions = attributes.position.array;
+ const normals = attributes.normal.array;
+ const uvs = attributes.uv.array;
- // draw range
+ const nVertices = positions.length / 3;
- this.drawRange.start = source.drawRange.start;
- this.drawRange.count = source.drawRange.count;
+ if ( this.hasAttribute( 'tangent' ) === false ) {
- // user data
+ this.setAttribute( 'tangent', new BufferAttribute( new Float32Array( 4 * nVertices ), 4 ) );
- this.userData = source.userData;
+ }
- return this;
+ const tangents = this.getAttribute( 'tangent' ).array;
- },
+ const tan1 = [], tan2 = [];
- dispose: function () {
+ for ( let i = 0; i < nVertices; i ++ ) {
- this.dispatchEvent( { type: 'dispose' } );
+ tan1[ i ] = new Vector3();
+ tan2[ i ] = new Vector3();
}
- } );
+ const vA = new Vector3(),
+ vB = new Vector3(),
+ vC = new Vector3(),
- /**
- * @author mrdoob / http://mrdoob.com/
- * @author alteredq / http://alteredqualia.com/
- * @author mikael emtinger / http://gomo.se/
- * @author jonobr1 / http://jonobr1.com/
- */
+ uvA = new Vector2(),
+ uvB = new Vector2(),
+ uvC = new Vector2(),
- var _inverseMatrix = new Matrix4();
- var _ray = new Ray();
- var _sphere = new Sphere();
+ sdir = new Vector3(),
+ tdir = new Vector3();
- var _vA = new Vector3();
- var _vB = new Vector3();
- var _vC = new Vector3();
+ function handleTriangle( a, b, c ) {
- var _tempA = new Vector3();
- var _tempB = new Vector3();
- var _tempC = new Vector3();
+ vA.fromArray( positions, a * 3 );
+ vB.fromArray( positions, b * 3 );
+ vC.fromArray( positions, c * 3 );
- var _morphA = new Vector3();
- var _morphB = new Vector3();
- var _morphC = new Vector3();
+ uvA.fromArray( uvs, a * 2 );
+ uvB.fromArray( uvs, b * 2 );
+ uvC.fromArray( uvs, c * 2 );
- var _uvA = new Vector2();
- var _uvB = new Vector2();
- var _uvC = new Vector2();
+ vB.sub( vA );
+ vC.sub( vA );
- var _intersectionPoint = new Vector3();
- var _intersectionPointWorld = new Vector3();
+ uvB.sub( uvA );
+ uvC.sub( uvA );
- function Mesh( geometry, material ) {
+ const r = 1.0 / ( uvB.x * uvC.y - uvC.x * uvB.y );
- Object3D.call( this );
+ // silently ignore degenerate uv triangles having coincident or colinear vertices
- this.type = 'Mesh';
+ if ( ! isFinite( r ) ) return;
- this.geometry = geometry !== undefined ? geometry : new BufferGeometry();
- this.material = material !== undefined ? material : new MeshBasicMaterial( { color: Math.random() * 0xffffff } );
+ sdir.copy( vB ).multiplyScalar( uvC.y ).addScaledVector( vC, - uvB.y ).multiplyScalar( r );
+ tdir.copy( vC ).multiplyScalar( uvB.x ).addScaledVector( vB, - uvC.x ).multiplyScalar( r );
- this.drawMode = TrianglesDrawMode;
+ tan1[ a ].add( sdir );
+ tan1[ b ].add( sdir );
+ tan1[ c ].add( sdir );
- this.updateMorphTargets();
+ tan2[ a ].add( tdir );
+ tan2[ b ].add( tdir );
+ tan2[ c ].add( tdir );
- }
+ }
- Mesh.prototype = Object.assign( Object.create( Object3D.prototype ), {
+ let groups = this.groups;
- constructor: Mesh,
+ if ( groups.length === 0 ) {
- isMesh: true,
+ groups = [ {
+ start: 0,
+ count: indices.length
+ } ];
- setDrawMode: function ( value ) {
+ }
- this.drawMode = value;
+ for ( let i = 0, il = groups.length; i < il; ++ i ) {
- },
+ const group = groups[ i ];
- copy: function ( source ) {
+ const start = group.start;
+ const count = group.count;
- Object3D.prototype.copy.call( this, source );
+ for ( let j = start, jl = start + count; j < jl; j += 3 ) {
- this.drawMode = source.drawMode;
+ handleTriangle(
+ indices[ j + 0 ],
+ indices[ j + 1 ],
+ indices[ j + 2 ]
+ );
- if ( source.morphTargetInfluences !== undefined ) {
+ }
- this.morphTargetInfluences = source.morphTargetInfluences.slice();
+ }
- }
+ const tmp = new Vector3(), tmp2 = new Vector3();
+ const n = new Vector3(), n2 = new Vector3();
- if ( source.morphTargetDictionary !== undefined ) {
+ function handleVertex( v ) {
- this.morphTargetDictionary = Object.assign( {}, source.morphTargetDictionary );
+ n.fromArray( normals, v * 3 );
+ n2.copy( n );
- }
+ const t = tan1[ v ];
- return this;
+ // Gram-Schmidt orthogonalize
- },
+ tmp.copy( t );
+ tmp.sub( n.multiplyScalar( n.dot( t ) ) ).normalize();
- updateMorphTargets: function () {
+ // Calculate handedness
- var geometry = this.geometry;
- var m, ml, name;
+ tmp2.crossVectors( n2, t );
+ const test = tmp2.dot( tan2[ v ] );
+ const w = ( test < 0.0 ) ? - 1.0 : 1.0;
- if ( geometry.isBufferGeometry ) {
+ tangents[ v * 4 ] = tmp.x;
+ tangents[ v * 4 + 1 ] = tmp.y;
+ tangents[ v * 4 + 2 ] = tmp.z;
+ tangents[ v * 4 + 3 ] = w;
- var morphAttributes = geometry.morphAttributes;
- var keys = Object.keys( morphAttributes );
+ }
- if ( keys.length > 0 ) {
+ for ( let i = 0, il = groups.length; i < il; ++ i ) {
- var morphAttribute = morphAttributes[ keys[ 0 ] ];
+ const group = groups[ i ];
- if ( morphAttribute !== undefined ) {
+ const start = group.start;
+ const count = group.count;
- this.morphTargetInfluences = [];
- this.morphTargetDictionary = {};
+ for ( let j = start, jl = start + count; j < jl; j += 3 ) {
- for ( m = 0, ml = morphAttribute.length; m < ml; m ++ ) {
+ handleVertex( indices[ j + 0 ] );
+ handleVertex( indices[ j + 1 ] );
+ handleVertex( indices[ j + 2 ] );
- name = morphAttribute[ m ].name || String( m );
+ }
- this.morphTargetInfluences.push( 0 );
- this.morphTargetDictionary[ name ] = m;
+ }
- }
+ }
- }
+ computeVertexNormals() {
- }
+ const index = this.index;
+ const positionAttribute = this.getAttribute( 'position' );
+
+ if ( positionAttribute !== undefined ) {
+
+ let normalAttribute = this.getAttribute( 'normal' );
+
+ if ( normalAttribute === undefined ) {
+
+ normalAttribute = new BufferAttribute( new Float32Array( positionAttribute.count * 3 ), 3 );
+ this.setAttribute( 'normal', normalAttribute );
} else {
- var morphTargets = geometry.morphTargets;
+ // reset existing normals to zero
- if ( morphTargets !== undefined && morphTargets.length > 0 ) {
+ for ( let i = 0, il = normalAttribute.count; i < il; i ++ ) {
- console.error( 'THREE.Mesh.updateMorphTargets() no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.' );
+ normalAttribute.setXYZ( i, 0, 0, 0 );
}
}
- },
+ const pA = new Vector3(), pB = new Vector3(), pC = new Vector3();
+ const nA = new Vector3(), nB = new Vector3(), nC = new Vector3();
+ const cb = new Vector3(), ab = new Vector3();
- raycast: function ( raycaster, intersects ) {
+ // indexed elements
- var geometry = this.geometry;
- var material = this.material;
- var matrixWorld = this.matrixWorld;
+ if ( index ) {
- if ( material === undefined ) return;
+ for ( let i = 0, il = index.count; i < il; i += 3 ) {
- // Checking boundingSphere distance to ray
+ const vA = index.getX( i + 0 );
+ const vB = index.getX( i + 1 );
+ const vC = index.getX( i + 2 );
- if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
+ pA.fromBufferAttribute( positionAttribute, vA );
+ pB.fromBufferAttribute( positionAttribute, vB );
+ pC.fromBufferAttribute( positionAttribute, vC );
- _sphere.copy( geometry.boundingSphere );
- _sphere.applyMatrix4( matrixWorld );
+ cb.subVectors( pC, pB );
+ ab.subVectors( pA, pB );
+ cb.cross( ab );
- if ( raycaster.ray.intersectsSphere( _sphere ) === false ) return;
+ nA.fromBufferAttribute( normalAttribute, vA );
+ nB.fromBufferAttribute( normalAttribute, vB );
+ nC.fromBufferAttribute( normalAttribute, vC );
- //
+ nA.add( cb );
+ nB.add( cb );
+ nC.add( cb );
- _inverseMatrix.getInverse( matrixWorld );
- _ray.copy( raycaster.ray ).applyMatrix4( _inverseMatrix );
+ normalAttribute.setXYZ( vA, nA.x, nA.y, nA.z );
+ normalAttribute.setXYZ( vB, nB.x, nB.y, nB.z );
+ normalAttribute.setXYZ( vC, nC.x, nC.y, nC.z );
- // Check boundingBox before continuing
+ }
- if ( geometry.boundingBox !== null ) {
+ } else {
- if ( _ray.intersectsBox( geometry.boundingBox ) === false ) return;
+ // non-indexed elements (unconnected triangle soup)
- }
+ for ( let i = 0, il = positionAttribute.count; i < il; i += 3 ) {
- var intersection;
+ pA.fromBufferAttribute( positionAttribute, i + 0 );
+ pB.fromBufferAttribute( positionAttribute, i + 1 );
+ pC.fromBufferAttribute( positionAttribute, i + 2 );
- if ( geometry.isBufferGeometry ) {
+ cb.subVectors( pC, pB );
+ ab.subVectors( pA, pB );
+ cb.cross( ab );
- var a, b, c;
- var index = geometry.index;
- var position = geometry.attributes.position;
- var morphPosition = geometry.morphAttributes.position;
- var uv = geometry.attributes.uv;
- var uv2 = geometry.attributes.uv2;
- var groups = geometry.groups;
- var drawRange = geometry.drawRange;
- var i, j, il, jl;
- var group, groupMaterial;
- var start, end;
+ normalAttribute.setXYZ( i + 0, cb.x, cb.y, cb.z );
+ normalAttribute.setXYZ( i + 1, cb.x, cb.y, cb.z );
+ normalAttribute.setXYZ( i + 2, cb.x, cb.y, cb.z );
- if ( index !== null ) {
+ }
- // indexed buffer geometry
+ }
- if ( Array.isArray( material ) ) {
+ this.normalizeNormals();
- for ( i = 0, il = groups.length; i < il; i ++ ) {
+ normalAttribute.needsUpdate = true;
- group = groups[ i ];
- groupMaterial = material[ group.materialIndex ];
+ }
- start = Math.max( group.start, drawRange.start );
- end = Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) );
+ }
- for ( j = start, jl = end; j < jl; j += 3 ) {
+ normalizeNormals() {
- a = index.getX( j );
- b = index.getX( j + 1 );
- c = index.getX( j + 2 );
+ const normals = this.attributes.normal;
- intersection = checkBufferGeometryIntersection( this, groupMaterial, raycaster, _ray, position, morphPosition, uv, uv2, a, b, c );
+ for ( let i = 0, il = normals.count; i < il; i ++ ) {
- if ( intersection ) {
+ _vector$7.fromBufferAttribute( normals, i );
- intersection.faceIndex = Math.floor( j / 3 ); // triangle number in indexed buffer semantics
- intersection.face.materialIndex = group.materialIndex;
- intersects.push( intersection );
+ _vector$7.normalize();
- }
+ normals.setXYZ( i, _vector$7.x, _vector$7.y, _vector$7.z );
- }
+ }
- }
+ }
- } else {
+ toNonIndexed() {
- start = Math.max( 0, drawRange.start );
- end = Math.min( index.count, ( drawRange.start + drawRange.count ) );
+ function convertBufferAttribute( attribute, indices ) {
- for ( i = start, il = end; i < il; i += 3 ) {
+ const array = attribute.array;
+ const itemSize = attribute.itemSize;
+ const normalized = attribute.normalized;
- a = index.getX( i );
- b = index.getX( i + 1 );
- c = index.getX( i + 2 );
+ const array2 = new array.constructor( indices.length * itemSize );
- intersection = checkBufferGeometryIntersection( this, material, raycaster, _ray, position, morphPosition, uv, uv2, a, b, c );
+ let index = 0, index2 = 0;
- if ( intersection ) {
+ for ( let i = 0, l = indices.length; i < l; i ++ ) {
- intersection.faceIndex = Math.floor( i / 3 ); // triangle number in indexed buffer semantics
- intersects.push( intersection );
+ if ( attribute.isInterleavedBufferAttribute ) {
- }
+ index = indices[ i ] * attribute.data.stride + attribute.offset;
- }
+ } else {
- }
+ index = indices[ i ] * itemSize;
- } else if ( position !== undefined ) {
+ }
- // non-indexed buffer geometry
+ for ( let j = 0; j < itemSize; j ++ ) {
- if ( Array.isArray( material ) ) {
+ array2[ index2 ++ ] = array[ index ++ ];
- for ( i = 0, il = groups.length; i < il; i ++ ) {
+ }
- group = groups[ i ];
- groupMaterial = material[ group.materialIndex ];
+ }
- start = Math.max( group.start, drawRange.start );
- end = Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) );
+ return new BufferAttribute( array2, itemSize, normalized );
- for ( j = start, jl = end; j < jl; j += 3 ) {
+ }
- a = j;
- b = j + 1;
- c = j + 2;
+ //
- intersection = checkBufferGeometryIntersection( this, groupMaterial, raycaster, _ray, position, morphPosition, uv, uv2, a, b, c );
+ if ( this.index === null ) {
- if ( intersection ) {
+ console.warn( 'THREE.BufferGeometry.toNonIndexed(): BufferGeometry is already non-indexed.' );
+ return this;
- intersection.faceIndex = Math.floor( j / 3 ); // triangle number in non-indexed buffer semantics
- intersection.face.materialIndex = group.materialIndex;
- intersects.push( intersection );
+ }
- }
+ const geometry2 = new BufferGeometry();
- }
+ const indices = this.index.array;
+ const attributes = this.attributes;
- }
+ // attributes
- } else {
+ for ( const name in attributes ) {
- start = Math.max( 0, drawRange.start );
- end = Math.min( position.count, ( drawRange.start + drawRange.count ) );
+ const attribute = attributes[ name ];
- for ( i = start, il = end; i < il; i += 3 ) {
+ const newAttribute = convertBufferAttribute( attribute, indices );
- a = i;
- b = i + 1;
- c = i + 2;
+ geometry2.setAttribute( name, newAttribute );
- intersection = checkBufferGeometryIntersection( this, material, raycaster, _ray, position, morphPosition, uv, uv2, a, b, c );
+ }
- if ( intersection ) {
+ // morph attributes
- intersection.faceIndex = Math.floor( i / 3 ); // triangle number in non-indexed buffer semantics
- intersects.push( intersection );
+ const morphAttributes = this.morphAttributes;
- }
+ for ( const name in morphAttributes ) {
- }
+ const morphArray = [];
+ const morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes
- }
+ for ( let i = 0, il = morphAttribute.length; i < il; i ++ ) {
- }
+ const attribute = morphAttribute[ i ];
- } else if ( geometry.isGeometry ) {
+ const newAttribute = convertBufferAttribute( attribute, indices );
- var fvA, fvB, fvC;
- var isMultiMaterial = Array.isArray( material );
+ morphArray.push( newAttribute );
- var vertices = geometry.vertices;
- var faces = geometry.faces;
- var uvs;
+ }
- var faceVertexUvs = geometry.faceVertexUvs[ 0 ];
- if ( faceVertexUvs.length > 0 ) uvs = faceVertexUvs;
+ geometry2.morphAttributes[ name ] = morphArray;
- for ( var f = 0, fl = faces.length; f < fl; f ++ ) {
+ }
- var face = faces[ f ];
- var faceMaterial = isMultiMaterial ? material[ face.materialIndex ] : material;
+ geometry2.morphTargetsRelative = this.morphTargetsRelative;
- if ( faceMaterial === undefined ) continue;
+ // groups
- fvA = vertices[ face.a ];
- fvB = vertices[ face.b ];
- fvC = vertices[ face.c ];
+ const groups = this.groups;
- intersection = checkIntersection( this, faceMaterial, raycaster, _ray, fvA, fvB, fvC, _intersectionPoint );
+ for ( let i = 0, l = groups.length; i < l; i ++ ) {
- if ( intersection ) {
+ const group = groups[ i ];
+ geometry2.addGroup( group.start, group.count, group.materialIndex );
- if ( uvs && uvs[ f ] ) {
+ }
- var uvs_f = uvs[ f ];
- _uvA.copy( uvs_f[ 0 ] );
- _uvB.copy( uvs_f[ 1 ] );
- _uvC.copy( uvs_f[ 2 ] );
+ return geometry2;
- intersection.uv = Triangle.getUV( _intersectionPoint, fvA, fvB, fvC, _uvA, _uvB, _uvC, new Vector2() );
+ }
- }
+ toJSON() {
- intersection.face = face;
- intersection.faceIndex = f;
- intersects.push( intersection );
+ const data = {
+ metadata: {
+ version: 4.6,
+ type: 'BufferGeometry',
+ generator: 'BufferGeometry.toJSON'
+ }
+ };
- }
+ // standard BufferGeometry serialization
- }
+ data.uuid = this.uuid;
+ data.type = this.type;
+ if ( this.name !== '' ) data.name = this.name;
+ if ( Object.keys( this.userData ).length > 0 ) data.userData = this.userData;
- }
+ if ( this.parameters !== undefined ) {
- },
+ const parameters = this.parameters;
- clone: function () {
+ for ( const key in parameters ) {
- return new this.constructor( this.geometry, this.material ).copy( this );
+ if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ];
- }
+ }
- } );
+ return data;
- function checkIntersection( object, material, raycaster, ray, pA, pB, pC, point ) {
+ }
- var intersect;
+ // for simplicity the code assumes attributes are not shared across geometries, see #15811
- if ( material.side === BackSide ) {
+ data.data = { attributes: {} };
- intersect = ray.intersectTriangle( pC, pB, pA, true, point );
+ const index = this.index;
- } else {
+ if ( index !== null ) {
- intersect = ray.intersectTriangle( pA, pB, pC, material.side !== DoubleSide, point );
+ data.data.index = {
+ type: index.array.constructor.name,
+ array: Array.prototype.slice.call( index.array )
+ };
}
- if ( intersect === null ) return null;
+ const attributes = this.attributes;
- _intersectionPointWorld.copy( point );
- _intersectionPointWorld.applyMatrix4( object.matrixWorld );
+ for ( const key in attributes ) {
- var distance = raycaster.ray.origin.distanceTo( _intersectionPointWorld );
+ const attribute = attributes[ key ];
- if ( distance < raycaster.near || distance > raycaster.far ) return null;
+ data.data.attributes[ key ] = attribute.toJSON( data.data );
- return {
- distance: distance,
- point: _intersectionPointWorld.clone(),
- object: object
- };
+ }
- }
+ const morphAttributes = {};
+ let hasMorphAttributes = false;
- function checkBufferGeometryIntersection( object, material, raycaster, ray, position, morphPosition, uv, uv2, a, b, c ) {
+ for ( const key in this.morphAttributes ) {
- _vA.fromBufferAttribute( position, a );
- _vB.fromBufferAttribute( position, b );
- _vC.fromBufferAttribute( position, c );
+ const attributeArray = this.morphAttributes[ key ];
- var morphInfluences = object.morphTargetInfluences;
+ const array = [];
- if ( material.morphTargets && morphPosition && morphInfluences ) {
+ for ( let i = 0, il = attributeArray.length; i < il; i ++ ) {
- _morphA.set( 0, 0, 0 );
- _morphB.set( 0, 0, 0 );
- _morphC.set( 0, 0, 0 );
+ const attribute = attributeArray[ i ];
- for ( var i = 0, il = morphPosition.length; i < il; i ++ ) {
+ array.push( attribute.toJSON( data.data ) );
- var influence = morphInfluences[ i ];
- var morphAttribute = morphPosition[ i ];
+ }
- if ( influence === 0 ) continue;
+ if ( array.length > 0 ) {
- _tempA.fromBufferAttribute( morphAttribute, a );
- _tempB.fromBufferAttribute( morphAttribute, b );
- _tempC.fromBufferAttribute( morphAttribute, c );
+ morphAttributes[ key ] = array;
- _morphA.addScaledVector( _tempA.sub( _vA ), influence );
- _morphB.addScaledVector( _tempB.sub( _vB ), influence );
- _morphC.addScaledVector( _tempC.sub( _vC ), influence );
+ hasMorphAttributes = true;
}
- _vA.add( _morphA );
- _vB.add( _morphB );
- _vC.add( _morphC );
-
}
- var intersection = checkIntersection( object, material, raycaster, ray, _vA, _vB, _vC, _intersectionPoint );
-
- if ( intersection ) {
+ if ( hasMorphAttributes ) {
- if ( uv ) {
+ data.data.morphAttributes = morphAttributes;
+ data.data.morphTargetsRelative = this.morphTargetsRelative;
- _uvA.fromBufferAttribute( uv, a );
- _uvB.fromBufferAttribute( uv, b );
- _uvC.fromBufferAttribute( uv, c );
-
- intersection.uv = Triangle.getUV( _intersectionPoint, _vA, _vB, _vC, _uvA, _uvB, _uvC, new Vector2() );
+ }
- }
+ const groups = this.groups;
- if ( uv2 ) {
+ if ( groups.length > 0 ) {
- _uvA.fromBufferAttribute( uv2, a );
- _uvB.fromBufferAttribute( uv2, b );
- _uvC.fromBufferAttribute( uv2, c );
+ data.data.groups = JSON.parse( JSON.stringify( groups ) );
- intersection.uv2 = Triangle.getUV( _intersectionPoint, _vA, _vB, _vC, _uvA, _uvB, _uvC, new Vector2() );
+ }
- }
+ const boundingSphere = this.boundingSphere;
- var face = new Face3( a, b, c );
- Triangle.getNormal( _vA, _vB, _vC, face.normal );
+ if ( boundingSphere !== null ) {
- intersection.face = face;
+ data.data.boundingSphere = {
+ center: boundingSphere.center.toArray(),
+ radius: boundingSphere.radius
+ };
}
- return intersection;
+ return data;
}
- /**
- * @author mrdoob / http://mrdoob.com/
- * @author kile / http://kile.stravaganza.org/
- * @author alteredq / http://alteredqualia.com/
- * @author mikael emtinger / http://gomo.se/
- * @author zz85 / http://www.lab4games.net/zz85/blog
- * @author bhouston / http://clara.io
- */
-
- var _geometryId = 0; // Geometry uses even numbers as Id
- var _m1$3 = new Matrix4();
- var _obj$1 = new Object3D();
- var _offset$1 = new Vector3();
+ clone() {
- function Geometry() {
+ return new this.constructor().copy( this );
- Object.defineProperty( this, 'id', { value: _geometryId += 2 } );
+ }
- this.uuid = _Math.generateUUID();
+ copy( source ) {
- this.name = '';
- this.type = 'Geometry';
+ // reset
- this.vertices = [];
- this.colors = [];
- this.faces = [];
- this.faceVertexUvs = [[]];
+ this.index = null;
+ this.attributes = {};
+ this.morphAttributes = {};
+ this.groups = [];
+ this.boundingBox = null;
+ this.boundingSphere = null;
- this.morphTargets = [];
- this.morphNormals = [];
+ // used for storing cloned, shared data
- this.skinWeights = [];
- this.skinIndices = [];
+ const data = {};
- this.lineDistances = [];
+ // name
- this.boundingBox = null;
- this.boundingSphere = null;
+ this.name = source.name;
- // update flags
+ // index
- this.elementsNeedUpdate = false;
- this.verticesNeedUpdate = false;
- this.uvsNeedUpdate = false;
- this.normalsNeedUpdate = false;
- this.colorsNeedUpdate = false;
- this.lineDistancesNeedUpdate = false;
- this.groupsNeedUpdate = false;
+ const index = source.index;
- }
+ if ( index !== null ) {
- Geometry.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
+ this.setIndex( index.clone( data ) );
- constructor: Geometry,
+ }
- isGeometry: true,
+ // attributes
- applyMatrix: function ( matrix ) {
+ const attributes = source.attributes;
- var normalMatrix = new Matrix3().getNormalMatrix( matrix );
+ for ( const name in attributes ) {
- for ( var i = 0, il = this.vertices.length; i < il; i ++ ) {
+ const attribute = attributes[ name ];
+ this.setAttribute( name, attribute.clone( data ) );
- var vertex = this.vertices[ i ];
- vertex.applyMatrix4( matrix );
+ }
- }
+ // morph attributes
- for ( var i = 0, il = this.faces.length; i < il; i ++ ) {
+ const morphAttributes = source.morphAttributes;
- var face = this.faces[ i ];
- face.normal.applyMatrix3( normalMatrix ).normalize();
+ for ( const name in morphAttributes ) {
- for ( var j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) {
+ const array = [];
+ const morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes
- face.vertexNormals[ j ].applyMatrix3( normalMatrix ).normalize();
+ for ( let i = 0, l = morphAttribute.length; i < l; i ++ ) {
- }
+ array.push( morphAttribute[ i ].clone( data ) );
}
- if ( this.boundingBox !== null ) {
+ this.morphAttributes[ name ] = array;
- this.computeBoundingBox();
+ }
- }
+ this.morphTargetsRelative = source.morphTargetsRelative;
- if ( this.boundingSphere !== null ) {
+ // groups
- this.computeBoundingSphere();
+ const groups = source.groups;
- }
+ for ( let i = 0, l = groups.length; i < l; i ++ ) {
- this.verticesNeedUpdate = true;
- this.normalsNeedUpdate = true;
+ const group = groups[ i ];
+ this.addGroup( group.start, group.count, group.materialIndex );
- return this;
+ }
- },
+ // bounding box
- rotateX: function ( angle ) {
+ const boundingBox = source.boundingBox;
- // rotate geometry around world x-axis
+ if ( boundingBox !== null ) {
- _m1$3.makeRotationX( angle );
+ this.boundingBox = boundingBox.clone();
- this.applyMatrix( _m1$3 );
+ }
- return this;
+ // bounding sphere
- },
+ const boundingSphere = source.boundingSphere;
- rotateY: function ( angle ) {
+ if ( boundingSphere !== null ) {
- // rotate geometry around world y-axis
+ this.boundingSphere = boundingSphere.clone();
- _m1$3.makeRotationY( angle );
+ }
- this.applyMatrix( _m1$3 );
+ // draw range
- return this;
+ this.drawRange.start = source.drawRange.start;
+ this.drawRange.count = source.drawRange.count;
- },
+ // user data
- rotateZ: function ( angle ) {
+ this.userData = source.userData;
- // rotate geometry around world z-axis
+ return this;
- _m1$3.makeRotationZ( angle );
+ }
- this.applyMatrix( _m1$3 );
+ dispose() {
- return this;
+ this.dispatchEvent( { type: 'dispose' } );
- },
+ }
- translate: function ( x, y, z ) {
+}
- // translate geometry
+const _inverseMatrix$3 = /*@__PURE__*/ new Matrix4();
+const _ray$3 = /*@__PURE__*/ new Ray();
+const _sphere$5 = /*@__PURE__*/ new Sphere();
+const _sphereHitAt = /*@__PURE__*/ new Vector3();
- _m1$3.makeTranslation( x, y, z );
+const _vA$1 = /*@__PURE__*/ new Vector3();
+const _vB$1 = /*@__PURE__*/ new Vector3();
+const _vC$1 = /*@__PURE__*/ new Vector3();
- this.applyMatrix( _m1$3 );
+const _tempA = /*@__PURE__*/ new Vector3();
+const _morphA = /*@__PURE__*/ new Vector3();
- return this;
+const _uvA$1 = /*@__PURE__*/ new Vector2();
+const _uvB$1 = /*@__PURE__*/ new Vector2();
+const _uvC$1 = /*@__PURE__*/ new Vector2();
- },
+const _normalA = /*@__PURE__*/ new Vector3();
+const _normalB = /*@__PURE__*/ new Vector3();
+const _normalC = /*@__PURE__*/ new Vector3();
- scale: function ( x, y, z ) {
+const _intersectionPoint = /*@__PURE__*/ new Vector3();
+const _intersectionPointWorld = /*@__PURE__*/ new Vector3();
- // scale geometry
+class Mesh extends Object3D {
- _m1$3.makeScale( x, y, z );
+ constructor( geometry = new BufferGeometry(), material = new MeshBasicMaterial() ) {
- this.applyMatrix( _m1$3 );
+ super();
- return this;
+ this.isMesh = true;
- },
+ this.type = 'Mesh';
- lookAt: function ( vector ) {
+ this.geometry = geometry;
+ this.material = material;
- _obj$1.lookAt( vector );
+ this.updateMorphTargets();
- _obj$1.updateMatrix();
+ }
- this.applyMatrix( _obj$1.matrix );
+ copy( source, recursive ) {
- return this;
+ super.copy( source, recursive );
- },
+ if ( source.morphTargetInfluences !== undefined ) {
- fromBufferGeometry: function ( geometry ) {
+ this.morphTargetInfluences = source.morphTargetInfluences.slice();
- var scope = this;
+ }
- var indices = geometry.index !== null ? geometry.index.array : undefined;
- var attributes = geometry.attributes;
+ if ( source.morphTargetDictionary !== undefined ) {
- var positions = attributes.position.array;
- var normals = attributes.normal !== undefined ? attributes.normal.array : undefined;
- var colors = attributes.color !== undefined ? attributes.color.array : undefined;
- var uvs = attributes.uv !== undefined ? attributes.uv.array : undefined;
- var uvs2 = attributes.uv2 !== undefined ? attributes.uv2.array : undefined;
+ this.morphTargetDictionary = Object.assign( {}, source.morphTargetDictionary );
- if ( uvs2 !== undefined ) this.faceVertexUvs[ 1 ] = [];
+ }
- for ( var i = 0; i < positions.length; i += 3 ) {
+ this.material = Array.isArray( source.material ) ? source.material.slice() : source.material;
+ this.geometry = source.geometry;
- scope.vertices.push( new Vector3().fromArray( positions, i ) );
+ return this;
- if ( colors !== undefined ) {
+ }
- scope.colors.push( new Color().fromArray( colors, i ) );
+ updateMorphTargets() {
- }
+ const geometry = this.geometry;
- }
+ const morphAttributes = geometry.morphAttributes;
+ const keys = Object.keys( morphAttributes );
- function addFace( a, b, c, materialIndex ) {
+ if ( keys.length > 0 ) {
- var vertexColors = ( colors === undefined ) ? [] : [
- scope.colors[ a ].clone(),
- scope.colors[ b ].clone(),
- scope.colors[ c ].clone() ];
+ const morphAttribute = morphAttributes[ keys[ 0 ] ];
- var vertexNormals = ( normals === undefined ) ? [] : [
- new Vector3().fromArray( normals, a * 3 ),
- new Vector3().fromArray( normals, b * 3 ),
- new Vector3().fromArray( normals, c * 3 )
- ];
+ if ( morphAttribute !== undefined ) {
- var face = new Face3( a, b, c, vertexNormals, vertexColors, materialIndex );
+ this.morphTargetInfluences = [];
+ this.morphTargetDictionary = {};
- scope.faces.push( face );
+ for ( let m = 0, ml = morphAttribute.length; m < ml; m ++ ) {
- if ( uvs !== undefined ) {
+ const name = morphAttribute[ m ].name || String( m );
- scope.faceVertexUvs[ 0 ].push( [
- new Vector2().fromArray( uvs, a * 2 ),
- new Vector2().fromArray( uvs, b * 2 ),
- new Vector2().fromArray( uvs, c * 2 )
- ] );
+ this.morphTargetInfluences.push( 0 );
+ this.morphTargetDictionary[ name ] = m;
}
- if ( uvs2 !== undefined ) {
+ }
+
+ }
- scope.faceVertexUvs[ 1 ].push( [
- new Vector2().fromArray( uvs2, a * 2 ),
- new Vector2().fromArray( uvs2, b * 2 ),
- new Vector2().fromArray( uvs2, c * 2 )
- ] );
+ }
- }
+ getVertexPosition( index, target ) {
- }
+ const geometry = this.geometry;
+ const position = geometry.attributes.position;
+ const morphPosition = geometry.morphAttributes.position;
+ const morphTargetsRelative = geometry.morphTargetsRelative;
- var groups = geometry.groups;
+ target.fromBufferAttribute( position, index );
- if ( groups.length > 0 ) {
+ const morphInfluences = this.morphTargetInfluences;
- for ( var i = 0; i < groups.length; i ++ ) {
+ if ( morphPosition && morphInfluences ) {
- var group = groups[ i ];
+ _morphA.set( 0, 0, 0 );
- var start = group.start;
- var count = group.count;
+ for ( let i = 0, il = morphPosition.length; i < il; i ++ ) {
- for ( var j = start, jl = start + count; j < jl; j += 3 ) {
+ const influence = morphInfluences[ i ];
+ const morphAttribute = morphPosition[ i ];
- if ( indices !== undefined ) {
+ if ( influence === 0 ) continue;
- addFace( indices[ j ], indices[ j + 1 ], indices[ j + 2 ], group.materialIndex );
+ _tempA.fromBufferAttribute( morphAttribute, index );
- } else {
+ if ( morphTargetsRelative ) {
- addFace( j, j + 1, j + 2, group.materialIndex );
+ _morphA.addScaledVector( _tempA, influence );
- }
+ } else {
- }
+ _morphA.addScaledVector( _tempA.sub( target ), influence );
}
- } else {
-
- if ( indices !== undefined ) {
+ }
- for ( var i = 0; i < indices.length; i += 3 ) {
+ target.add( _morphA );
- addFace( indices[ i ], indices[ i + 1 ], indices[ i + 2 ] );
+ }
- }
+ return target;
- } else {
+ }
- for ( var i = 0; i < positions.length / 3; i += 3 ) {
+ raycast( raycaster, intersects ) {
- addFace( i, i + 1, i + 2 );
+ const geometry = this.geometry;
+ const material = this.material;
+ const matrixWorld = this.matrixWorld;
- }
+ if ( material === undefined ) return;
- }
+ // test with bounding sphere in world space
- }
+ if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
- this.computeFaceNormals();
+ _sphere$5.copy( geometry.boundingSphere );
+ _sphere$5.applyMatrix4( matrixWorld );
- if ( geometry.boundingBox !== null ) {
+ // check distance from ray origin to bounding sphere
- this.boundingBox = geometry.boundingBox.clone();
+ _ray$3.copy( raycaster.ray ).recast( raycaster.near );
- }
+ if ( _sphere$5.containsPoint( _ray$3.origin ) === false ) {
- if ( geometry.boundingSphere !== null ) {
+ if ( _ray$3.intersectSphere( _sphere$5, _sphereHitAt ) === null ) return;
- this.boundingSphere = geometry.boundingSphere.clone();
+ if ( _ray$3.origin.distanceToSquared( _sphereHitAt ) > ( raycaster.far - raycaster.near ) ** 2 ) return;
- }
+ }
- return this;
+ // convert ray to local space of mesh
- },
+ _inverseMatrix$3.copy( matrixWorld ).invert();
+ _ray$3.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$3 );
- center: function () {
+ // test with bounding box in local space
- this.computeBoundingBox();
+ if ( geometry.boundingBox !== null ) {
- this.boundingBox.getCenter( _offset$1 ).negate();
+ if ( _ray$3.intersectsBox( geometry.boundingBox ) === false ) return;
- this.translate( _offset$1.x, _offset$1.y, _offset$1.z );
+ }
- return this;
+ // test for intersections with geometry
- },
+ this._computeIntersections( raycaster, intersects, _ray$3 );
- normalize: function () {
+ }
- this.computeBoundingSphere();
+ _computeIntersections( raycaster, intersects, rayLocalSpace ) {
- var center = this.boundingSphere.center;
- var radius = this.boundingSphere.radius;
+ let intersection;
- var s = radius === 0 ? 1 : 1.0 / radius;
+ const geometry = this.geometry;
+ const material = this.material;
- 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
- );
+ const index = geometry.index;
+ const position = geometry.attributes.position;
+ const uv = geometry.attributes.uv;
+ const uv1 = geometry.attributes.uv1;
+ const normal = geometry.attributes.normal;
+ const groups = geometry.groups;
+ const drawRange = geometry.drawRange;
- this.applyMatrix( matrix );
+ if ( index !== null ) {
- return this;
+ // indexed buffer geometry
- },
+ if ( Array.isArray( material ) ) {
- computeFaceNormals: function () {
+ for ( let i = 0, il = groups.length; i < il; i ++ ) {
- var cb = new Vector3(), ab = new Vector3();
+ const group = groups[ i ];
+ const groupMaterial = material[ group.materialIndex ];
- for ( var f = 0, fl = this.faces.length; f < fl; f ++ ) {
+ const start = Math.max( group.start, drawRange.start );
+ const end = Math.min( index.count, Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) ) );
- var face = this.faces[ f ];
+ for ( let j = start, jl = end; j < jl; j += 3 ) {
- var vA = this.vertices[ face.a ];
- var vB = this.vertices[ face.b ];
- var vC = this.vertices[ face.c ];
+ const a = index.getX( j );
+ const b = index.getX( j + 1 );
+ const c = index.getX( j + 2 );
- cb.subVectors( vC, vB );
- ab.subVectors( vA, vB );
- cb.cross( ab );
+ intersection = checkGeometryIntersection( this, groupMaterial, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c );
- cb.normalize();
+ if ( intersection ) {
- face.normal.copy( cb );
+ intersection.faceIndex = Math.floor( j / 3 ); // triangle number in indexed buffer semantics
+ intersection.face.materialIndex = group.materialIndex;
+ intersects.push( intersection );
- }
+ }
- },
+ }
- computeVertexNormals: function ( areaWeighted ) {
+ }
- if ( areaWeighted === undefined ) areaWeighted = true;
+ } else {
- var v, vl, f, fl, face, vertices;
+ const start = Math.max( 0, drawRange.start );
+ const end = Math.min( index.count, ( drawRange.start + drawRange.count ) );
- vertices = new Array( this.vertices.length );
+ for ( let i = start, il = end; i < il; i += 3 ) {
- for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
+ const a = index.getX( i );
+ const b = index.getX( i + 1 );
+ const c = index.getX( i + 2 );
- vertices[ v ] = new Vector3();
+ intersection = checkGeometryIntersection( this, material, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c );
- }
+ if ( intersection ) {
- if ( areaWeighted ) {
+ intersection.faceIndex = Math.floor( i / 3 ); // triangle number in indexed buffer semantics
+ intersects.push( intersection );
- // vertex normals weighted by triangle areas
- // http://www.iquilezles.org/www/articles/normals/normals.htm
+ }
- var vA, vB, vC;
- var cb = new Vector3(), ab = new Vector3();
+ }
- for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
+ }
- face = this.faces[ f ];
+ } else if ( position !== undefined ) {
- vA = this.vertices[ face.a ];
- vB = this.vertices[ face.b ];
- vC = this.vertices[ face.c ];
+ // non-indexed buffer geometry
- cb.subVectors( vC, vB );
- ab.subVectors( vA, vB );
- cb.cross( ab );
+ if ( Array.isArray( material ) ) {
- vertices[ face.a ].add( cb );
- vertices[ face.b ].add( cb );
- vertices[ face.c ].add( cb );
+ for ( let i = 0, il = groups.length; i < il; i ++ ) {
- }
+ const group = groups[ i ];
+ const groupMaterial = material[ group.materialIndex ];
- } else {
+ const start = Math.max( group.start, drawRange.start );
+ const end = Math.min( position.count, Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) ) );
- this.computeFaceNormals();
+ for ( let j = start, jl = end; j < jl; j += 3 ) {
- for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
+ const a = j;
+ const b = j + 1;
+ const c = j + 2;
- face = this.faces[ f ];
+ intersection = checkGeometryIntersection( this, groupMaterial, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c );
- vertices[ face.a ].add( face.normal );
- vertices[ face.b ].add( face.normal );
- vertices[ face.c ].add( face.normal );
+ if ( intersection ) {
- }
+ intersection.faceIndex = Math.floor( j / 3 ); // triangle number in non-indexed buffer semantics
+ intersection.face.materialIndex = group.materialIndex;
+ intersects.push( intersection );
- }
+ }
- for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
+ }
- vertices[ v ].normalize();
+ }
- }
+ } else {
- for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
+ const start = Math.max( 0, drawRange.start );
+ const end = Math.min( position.count, ( drawRange.start + drawRange.count ) );
- face = this.faces[ f ];
+ for ( let i = start, il = end; i < il; i += 3 ) {
- var vertexNormals = face.vertexNormals;
+ const a = i;
+ const b = i + 1;
+ const c = i + 2;
- if ( vertexNormals.length === 3 ) {
+ intersection = checkGeometryIntersection( this, material, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c );
- vertexNormals[ 0 ].copy( vertices[ face.a ] );
- vertexNormals[ 1 ].copy( vertices[ face.b ] );
- vertexNormals[ 2 ].copy( vertices[ face.c ] );
+ if ( intersection ) {
- } else {
+ intersection.faceIndex = Math.floor( i / 3 ); // triangle number in non-indexed buffer semantics
+ intersects.push( intersection );
- 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;
+ }
- }
+}
- },
+function checkIntersection( object, material, raycaster, ray, pA, pB, pC, point ) {
- computeFlatVertexNormals: function () {
+ let intersect;
- var f, fl, face;
+ if ( material.side === BackSide ) {
- this.computeFaceNormals();
+ intersect = ray.intersectTriangle( pC, pB, pA, true, point );
- for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
+ } else {
- face = this.faces[ f ];
+ intersect = ray.intersectTriangle( pA, pB, pC, ( material.side === FrontSide ), point );
- var vertexNormals = face.vertexNormals;
+ }
- if ( vertexNormals.length === 3 ) {
+ if ( intersect === null ) return null;
- vertexNormals[ 0 ].copy( face.normal );
- vertexNormals[ 1 ].copy( face.normal );
- vertexNormals[ 2 ].copy( face.normal );
+ _intersectionPointWorld.copy( point );
+ _intersectionPointWorld.applyMatrix4( object.matrixWorld );
- } else {
+ const distance = raycaster.ray.origin.distanceTo( _intersectionPointWorld );
- vertexNormals[ 0 ] = face.normal.clone();
- vertexNormals[ 1 ] = face.normal.clone();
- vertexNormals[ 2 ] = face.normal.clone();
+ if ( distance < raycaster.near || distance > raycaster.far ) return null;
- }
+ return {
+ distance: distance,
+ point: _intersectionPointWorld.clone(),
+ object: object
+ };
- }
+}
- if ( this.faces.length > 0 ) {
+function checkGeometryIntersection( object, material, raycaster, ray, uv, uv1, normal, a, b, c ) {
- this.normalsNeedUpdate = true;
+ object.getVertexPosition( a, _vA$1 );
+ object.getVertexPosition( b, _vB$1 );
+ object.getVertexPosition( c, _vC$1 );
- }
+ const intersection = checkIntersection( object, material, raycaster, ray, _vA$1, _vB$1, _vC$1, _intersectionPoint );
- },
+ if ( intersection ) {
- computeMorphNormals: function () {
+ if ( uv ) {
- var i, il, f, fl, face;
+ _uvA$1.fromBufferAttribute( uv, a );
+ _uvB$1.fromBufferAttribute( uv, b );
+ _uvC$1.fromBufferAttribute( uv, c );
- // save original normals
- // - create temp variables on first access
- // otherwise just copy (for faster repeated calls)
+ intersection.uv = Triangle.getInterpolation( _intersectionPoint, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1, new Vector2() );
- for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
+ }
- face = this.faces[ f ];
+ if ( uv1 ) {
- if ( ! face.__originalFaceNormal ) {
+ _uvA$1.fromBufferAttribute( uv1, a );
+ _uvB$1.fromBufferAttribute( uv1, b );
+ _uvC$1.fromBufferAttribute( uv1, c );
- face.__originalFaceNormal = face.normal.clone();
+ intersection.uv1 = Triangle.getInterpolation( _intersectionPoint, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1, new Vector2() );
+ intersection.uv2 = intersection.uv1; // @deprecated, r152
- } else {
+ }
- face.__originalFaceNormal.copy( face.normal );
+ if ( normal ) {
- }
+ _normalA.fromBufferAttribute( normal, a );
+ _normalB.fromBufferAttribute( normal, b );
+ _normalC.fromBufferAttribute( normal, c );
- if ( ! face.__originalVertexNormals ) face.__originalVertexNormals = [];
+ intersection.normal = Triangle.getInterpolation( _intersectionPoint, _vA$1, _vB$1, _vC$1, _normalA, _normalB, _normalC, new Vector3() );
- for ( i = 0, il = face.vertexNormals.length; i < il; i ++ ) {
+ if ( intersection.normal.dot( ray.direction ) > 0 ) {
- if ( ! face.__originalVertexNormals[ i ] ) {
+ intersection.normal.multiplyScalar( - 1 );
- face.__originalVertexNormals[ i ] = face.vertexNormals[ i ].clone();
+ }
- } else {
+ }
- face.__originalVertexNormals[ i ].copy( face.vertexNormals[ i ] );
+ const face = {
+ a: a,
+ b: b,
+ c: c,
+ normal: new Vector3(),
+ materialIndex: 0
+ };
- }
+ Triangle.getNormal( _vA$1, _vB$1, _vC$1, face.normal );
- }
+ intersection.face = face;
- }
+ }
- // use temp geometry to compute face and vertex normals for each morph
+ return intersection;
- var tmpGeo = new Geometry();
- tmpGeo.faces = this.faces;
+}
- for ( i = 0, il = this.morphTargets.length; i < il; i ++ ) {
+class BoxGeometry extends BufferGeometry {
- // create on first access
+ constructor( width = 1, height = 1, depth = 1, widthSegments = 1, heightSegments = 1, depthSegments = 1 ) {
- if ( ! this.morphNormals[ i ] ) {
+ super();
- this.morphNormals[ i ] = {};
- this.morphNormals[ i ].faceNormals = [];
- this.morphNormals[ i ].vertexNormals = [];
+ this.type = 'BoxGeometry';
- var dstNormalsFace = this.morphNormals[ i ].faceNormals;
- var dstNormalsVertex = this.morphNormals[ i ].vertexNormals;
+ this.parameters = {
+ width: width,
+ height: height,
+ depth: depth,
+ widthSegments: widthSegments,
+ heightSegments: heightSegments,
+ depthSegments: depthSegments
+ };
- var faceNormal, vertexNormals;
+ const scope = this;
- for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
+ // segments
- faceNormal = new Vector3();
- vertexNormals = { a: new Vector3(), b: new Vector3(), c: new Vector3() };
+ widthSegments = Math.floor( widthSegments );
+ heightSegments = Math.floor( heightSegments );
+ depthSegments = Math.floor( depthSegments );
- dstNormalsFace.push( faceNormal );
- dstNormalsVertex.push( vertexNormals );
+ // buffers
- }
+ const indices = [];
+ const vertices = [];
+ const normals = [];
+ const uvs = [];
- }
+ // helper variables
- var morphNormals = this.morphNormals[ i ];
+ let numberOfVertices = 0;
+ let groupStart = 0;
- // set vertices to morph target
+ // build each side of the box geometry
- tmpGeo.vertices = this.morphTargets[ i ].vertices;
+ buildPlane( 'z', 'y', 'x', - 1, - 1, depth, height, width, depthSegments, heightSegments, 0 ); // px
+ buildPlane( 'z', 'y', 'x', 1, - 1, depth, height, - width, depthSegments, heightSegments, 1 ); // nx
+ buildPlane( 'x', 'z', 'y', 1, 1, width, depth, height, widthSegments, depthSegments, 2 ); // py
+ buildPlane( 'x', 'z', 'y', 1, - 1, width, depth, - height, widthSegments, depthSegments, 3 ); // ny
+ buildPlane( 'x', 'y', 'z', 1, - 1, width, height, depth, widthSegments, heightSegments, 4 ); // pz
+ buildPlane( 'x', 'y', 'z', - 1, - 1, width, height, - depth, widthSegments, heightSegments, 5 ); // nz
- // compute morph normals
+ // build geometry
- tmpGeo.computeFaceNormals();
- tmpGeo.computeVertexNormals();
+ this.setIndex( indices );
+ this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
+ this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
+ this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
- // store morph normals
+ function buildPlane( u, v, w, udir, vdir, width, height, depth, gridX, gridY, materialIndex ) {
- var faceNormal, vertexNormals;
+ const segmentWidth = width / gridX;
+ const segmentHeight = height / gridY;
- for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
+ const widthHalf = width / 2;
+ const heightHalf = height / 2;
+ const depthHalf = depth / 2;
- face = this.faces[ f ];
+ const gridX1 = gridX + 1;
+ const gridY1 = gridY + 1;
- faceNormal = morphNormals.faceNormals[ f ];
- vertexNormals = morphNormals.vertexNormals[ f ];
+ let vertexCounter = 0;
+ let groupCount = 0;
- faceNormal.copy( face.normal );
+ const vector = new Vector3();
- vertexNormals.a.copy( face.vertexNormals[ 0 ] );
- vertexNormals.b.copy( face.vertexNormals[ 1 ] );
- vertexNormals.c.copy( face.vertexNormals[ 2 ] );
+ // generate vertices, normals and uvs
- }
+ for ( let iy = 0; iy < gridY1; iy ++ ) {
- }
+ const y = iy * segmentHeight - heightHalf;
- // restore original normals
+ for ( let ix = 0; ix < gridX1; ix ++ ) {
- for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
+ const x = ix * segmentWidth - widthHalf;
- face = this.faces[ f ];
+ // set values to correct vector component
- face.normal = face.__originalFaceNormal;
- face.vertexNormals = face.__originalVertexNormals;
+ vector[ u ] = x * udir;
+ vector[ v ] = y * vdir;
+ vector[ w ] = depthHalf;
- }
+ // now apply vector to vertex buffer
- },
+ vertices.push( vector.x, vector.y, vector.z );
- computeBoundingBox: function () {
+ // set values to correct vector component
- if ( this.boundingBox === null ) {
+ vector[ u ] = 0;
+ vector[ v ] = 0;
+ vector[ w ] = depth > 0 ? 1 : - 1;
- this.boundingBox = new Box3();
+ // now apply vector to normal buffer
- }
+ normals.push( vector.x, vector.y, vector.z );
- this.boundingBox.setFromPoints( this.vertices );
+ // uvs
- },
+ uvs.push( ix / gridX );
+ uvs.push( 1 - ( iy / gridY ) );
- computeBoundingSphere: function () {
+ // counters
- if ( this.boundingSphere === null ) {
+ vertexCounter += 1;
- this.boundingSphere = new Sphere();
+ }
}
- this.boundingSphere.setFromPoints( this.vertices );
+ // indices
- },
+ // 1. you need three indices to draw a single face
+ // 2. a single segment consists of two faces
+ // 3. so we need to generate six (2*3) indices per segment
- merge: function ( geometry, matrix, materialIndexOffset ) {
+ for ( let iy = 0; iy < gridY; iy ++ ) {
- if ( ! ( geometry && geometry.isGeometry ) ) {
+ for ( let ix = 0; ix < gridX; ix ++ ) {
- console.error( 'THREE.Geometry.merge(): geometry not an instance of THREE.Geometry.', geometry );
- return;
+ const a = numberOfVertices + ix + gridX1 * iy;
+ const b = numberOfVertices + ix + gridX1 * ( iy + 1 );
+ const c = numberOfVertices + ( ix + 1 ) + gridX1 * ( iy + 1 );
+ const d = numberOfVertices + ( ix + 1 ) + gridX1 * iy;
- }
+ // faces
- var normalMatrix,
- vertexOffset = this.vertices.length,
- vertices1 = this.vertices,
- vertices2 = geometry.vertices,
- faces1 = this.faces,
- faces2 = geometry.faces,
- colors1 = this.colors,
- colors2 = geometry.colors;
+ indices.push( a, b, d );
+ indices.push( b, c, d );
- if ( materialIndexOffset === undefined ) materialIndexOffset = 0;
+ // increase counter
- if ( matrix !== undefined ) {
+ groupCount += 6;
- normalMatrix = new Matrix3().getNormalMatrix( matrix );
+ }
}
- // vertices
+ // add a group to the geometry. this will ensure multi material support
+
+ scope.addGroup( groupStart, groupCount, materialIndex );
- for ( var i = 0, il = vertices2.length; i < il; i ++ ) {
+ // calculate new start value for groups
- var vertex = vertices2[ i ];
+ groupStart += groupCount;
- var vertexCopy = vertex.clone();
+ // update total number of vertices
- if ( matrix !== undefined ) vertexCopy.applyMatrix4( matrix );
+ numberOfVertices += vertexCounter;
- vertices1.push( vertexCopy );
+ }
- }
+ }
- // colors
+ copy( source ) {
- for ( var i = 0, il = colors2.length; i < il; i ++ ) {
+ super.copy( source );
- colors1.push( colors2[ i ].clone() );
+ this.parameters = Object.assign( {}, source.parameters );
- }
+ return this;
- // faces
+ }
- for ( i = 0, il = faces2.length; i < il; i ++ ) {
+ static fromJSON( data ) {
- var face = faces2[ i ], faceCopy, normal, color,
- faceVertexNormals = face.vertexNormals,
- faceVertexColors = face.vertexColors;
+ return new BoxGeometry( data.width, data.height, data.depth, data.widthSegments, data.heightSegments, data.depthSegments );
- 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();
+/**
+ * Uniform Utilities
+ */
- }
+function cloneUniforms( src ) {
- for ( var j = 0, jl = faceVertexNormals.length; j < jl; j ++ ) {
+ const dst = {};
- normal = faceVertexNormals[ j ].clone();
+ for ( const u in src ) {
- if ( normalMatrix !== undefined ) {
+ dst[ u ] = {};
- normal.applyMatrix3( normalMatrix ).normalize();
+ for ( const p in src[ u ] ) {
- }
+ const property = src[ u ][ p ];
- faceCopy.vertexNormals.push( normal );
+ if ( property && ( property.isColor ||
+ property.isMatrix3 || property.isMatrix4 ||
+ property.isVector2 || property.isVector3 || property.isVector4 ||
+ property.isTexture || property.isQuaternion ) ) {
- }
+ if ( property.isRenderTargetTexture ) {
- faceCopy.color.copy( face.color );
+ console.warn( 'UniformsUtils: Textures of render targets cannot be cloned via cloneUniforms() or mergeUniforms().' );
+ dst[ u ][ p ] = null;
- for ( var j = 0, jl = faceVertexColors.length; j < jl; j ++ ) {
+ } else {
- color = faceVertexColors[ j ];
- faceCopy.vertexColors.push( color.clone() );
+ dst[ u ][ p ] = property.clone();
}
- faceCopy.materialIndex = face.materialIndex + materialIndexOffset;
+ } else if ( Array.isArray( property ) ) {
- faces1.push( faceCopy );
+ dst[ u ][ p ] = property.slice();
- }
+ } else {
- // uvs
+ dst[ u ][ p ] = property;
- for ( var i = 0, il = geometry.faceVertexUvs.length; i < il; i ++ ) {
+ }
- var faceVertexUvs2 = geometry.faceVertexUvs[ i ];
+ }
- if ( this.faceVertexUvs[ i ] === undefined ) this.faceVertexUvs[ i ] = [];
+ }
- for ( var j = 0, jl = faceVertexUvs2.length; j < jl; j ++ ) {
+ return dst;
- var uvs2 = faceVertexUvs2[ j ], uvsCopy = [];
+}
- for ( var k = 0, kl = uvs2.length; k < kl; k ++ ) {
+function mergeUniforms( uniforms ) {
- uvsCopy.push( uvs2[ k ].clone() );
+ const merged = {};
- }
+ for ( let u = 0; u < uniforms.length; u ++ ) {
- this.faceVertexUvs[ i ].push( uvsCopy );
+ const tmp = cloneUniforms( uniforms[ u ] );
- }
+ for ( const p in tmp ) {
- }
+ merged[ p ] = tmp[ p ];
- },
+ }
- mergeMesh: function ( mesh ) {
+ }
- if ( ! ( mesh && mesh.isMesh ) ) {
+ return merged;
- console.error( 'THREE.Geometry.mergeMesh(): mesh not an instance of THREE.Mesh.', mesh );
- return;
+}
- }
+function cloneUniformsGroups( src ) {
- if ( mesh.matrixAutoUpdate ) mesh.updateMatrix();
+ const dst = [];
- this.merge( mesh.geometry, mesh.matrix );
+ for ( let u = 0; u < src.length; u ++ ) {
- },
+ dst.push( src[ u ].clone() );
- /*
- * Checks for duplicate vertices with hashmap.
- * Duplicated vertices are removed
- * and faces' vertices are updated.
- */
+ }
- mergeVertices: function () {
+ return dst;
- var verticesMap = {}; // Hashmap for looking up vertices by position coordinates (and making sure they are unique)
- var unique = [], changes = [];
+}
- var v, key;
- var precisionPoints = 4; // number of decimal points, e.g. 4 for epsilon of 0.0001
- var precision = Math.pow( 10, precisionPoints );
- var i, il, face;
- var indices, j, jl;
+function getUnlitUniformColorSpace( renderer ) {
- for ( i = 0, il = this.vertices.length; i < il; i ++ ) {
+ if ( renderer.getRenderTarget() === null ) {
- v = this.vertices[ i ];
- key = Math.round( v.x * precision ) + '_' + Math.round( v.y * precision ) + '_' + Math.round( v.z * precision );
+ // https://github.com/mrdoob/three.js/pull/23937#issuecomment-1111067398
+ return renderer.outputColorSpace;
- if ( verticesMap[ key ] === undefined ) {
+ }
- verticesMap[ key ] = i;
- unique.push( this.vertices[ i ] );
- changes[ i ] = unique.length - 1;
+ return ColorManagement.workingColorSpace;
- } else {
+}
- //console.log('Duplicate vertex found. ', i, ' could be using ', verticesMap[key]);
- changes[ i ] = changes[ verticesMap[ key ] ];
+// Legacy
- }
+const UniformsUtils = { clone: cloneUniforms, merge: mergeUniforms };
- }
+var default_vertex = "void main() {\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}";
+var default_fragment = "void main() {\n\tgl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );\n}";
- // if faces are completely degenerate after merging vertices, we
- // have to remove them from the geometry.
- var faceIndicesToRemove = [];
+class ShaderMaterial extends Material {
- for ( i = 0, il = this.faces.length; i < il; i ++ ) {
+ constructor( parameters ) {
- face = this.faces[ i ];
+ super();
- face.a = changes[ face.a ];
- face.b = changes[ face.b ];
- face.c = changes[ face.c ];
+ this.isShaderMaterial = true;
- indices = [ face.a, face.b, face.c ];
+ this.type = 'ShaderMaterial';
- // 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 ++ ) {
+ this.defines = {};
+ this.uniforms = {};
+ this.uniformsGroups = [];
- if ( indices[ n ] === indices[ ( n + 1 ) % 3 ] ) {
+ this.vertexShader = default_vertex;
+ this.fragmentShader = default_fragment;
- faceIndicesToRemove.push( i );
- break;
+ this.linewidth = 1;
- }
+ this.wireframe = false;
+ this.wireframeLinewidth = 1;
- }
+ this.fog = false; // set to use scene fog
+ this.lights = false; // set to use scene lights
+ this.clipping = false; // set to use user-defined clipping planes
- }
+ this.forceSinglePass = true;
- for ( i = faceIndicesToRemove.length - 1; i >= 0; i -- ) {
+ this.extensions = {
+ derivatives: false, // set to use derivatives
+ fragDepth: false, // set to use fragment depth values
+ drawBuffers: false, // set to use draw buffers
+ shaderTextureLOD: false // set to use shader texture LOD
+ };
- var idx = faceIndicesToRemove[ i ];
+ // When rendered geometry doesn't include these attributes but the material does,
+ // use these default values in WebGL. This avoids errors when buffer data is missing.
+ this.defaultAttributeValues = {
+ 'color': [ 1, 1, 1 ],
+ 'uv': [ 0, 0 ],
+ 'uv1': [ 0, 0 ]
+ };
- this.faces.splice( idx, 1 );
+ this.index0AttributeName = undefined;
+ this.uniformsNeedUpdate = false;
- for ( j = 0, jl = this.faceVertexUvs.length; j < jl; j ++ ) {
+ this.glslVersion = null;
- this.faceVertexUvs[ j ].splice( idx, 1 );
+ if ( parameters !== undefined ) {
- }
+ this.setValues( parameters );
- }
+ }
- // Use unique set of vertices
+ }
- var diff = this.vertices.length - unique.length;
- this.vertices = unique;
- return diff;
+ copy( source ) {
- },
+ super.copy( source );
- setFromPoints: function ( points ) {
+ this.fragmentShader = source.fragmentShader;
+ this.vertexShader = source.vertexShader;
- this.vertices = [];
+ this.uniforms = cloneUniforms( source.uniforms );
+ this.uniformsGroups = cloneUniformsGroups( source.uniformsGroups );
- for ( var i = 0, l = points.length; i < l; i ++ ) {
+ this.defines = Object.assign( {}, source.defines );
- var point = points[ i ];
- this.vertices.push( new Vector3( point.x, point.y, point.z || 0 ) );
+ this.wireframe = source.wireframe;
+ this.wireframeLinewidth = source.wireframeLinewidth;
- }
+ this.fog = source.fog;
+ this.lights = source.lights;
+ this.clipping = source.clipping;
- return this;
+ this.extensions = Object.assign( {}, source.extensions );
- },
+ this.glslVersion = source.glslVersion;
- sortFacesByMaterialIndex: function () {
+ return this;
- var faces = this.faces;
- var length = faces.length;
+ }
- // tag faces
+ toJSON( meta ) {
- for ( var i = 0; i < length; i ++ ) {
+ const data = super.toJSON( meta );
- faces[ i ]._id = i;
+ data.glslVersion = this.glslVersion;
+ data.uniforms = {};
- }
+ for ( const name in this.uniforms ) {
- // sort faces
+ const uniform = this.uniforms[ name ];
+ const value = uniform.value;
- function materialIndexSort( a, b ) {
+ if ( value && value.isTexture ) {
- return a.materialIndex - b.materialIndex;
+ data.uniforms[ name ] = {
+ type: 't',
+ value: value.toJSON( meta ).uuid
+ };
- }
+ } else if ( value && value.isColor ) {
- faces.sort( materialIndexSort );
+ data.uniforms[ name ] = {
+ type: 'c',
+ value: value.getHex()
+ };
- // sort uvs
+ } else if ( value && value.isVector2 ) {
- var uvs1 = this.faceVertexUvs[ 0 ];
- var uvs2 = this.faceVertexUvs[ 1 ];
+ data.uniforms[ name ] = {
+ type: 'v2',
+ value: value.toArray()
+ };
- var newUvs1, newUvs2;
+ } else if ( value && value.isVector3 ) {
- if ( uvs1 && uvs1.length === length ) newUvs1 = [];
- if ( uvs2 && uvs2.length === length ) newUvs2 = [];
+ data.uniforms[ name ] = {
+ type: 'v3',
+ value: value.toArray()
+ };
- for ( var i = 0; i < length; i ++ ) {
+ } else if ( value && value.isVector4 ) {
- var id = faces[ i ]._id;
+ data.uniforms[ name ] = {
+ type: 'v4',
+ value: value.toArray()
+ };
- if ( newUvs1 ) newUvs1.push( uvs1[ id ] );
- if ( newUvs2 ) newUvs2.push( uvs2[ id ] );
+ } else if ( value && value.isMatrix3 ) {
- }
+ data.uniforms[ name ] = {
+ type: 'm3',
+ value: value.toArray()
+ };
- if ( newUvs1 ) this.faceVertexUvs[ 0 ] = newUvs1;
- if ( newUvs2 ) this.faceVertexUvs[ 1 ] = newUvs2;
+ } else if ( value && value.isMatrix4 ) {
- },
+ data.uniforms[ name ] = {
+ type: 'm4',
+ value: value.toArray()
+ };
- toJSON: function () {
+ } else {
- var data = {
- metadata: {
- version: 4.5,
- type: 'Geometry',
- generator: 'Geometry.toJSON'
- }
- };
+ data.uniforms[ name ] = {
+ value: value
+ };
- // standard Geometry serialization
+ // note: the array variants v2v, v3v, v4v, m4v and tv are not supported so far
- data.uuid = this.uuid;
- data.type = this.type;
- if ( this.name !== '' ) data.name = this.name;
+ }
- if ( this.parameters !== undefined ) {
+ }
- var parameters = this.parameters;
+ if ( Object.keys( this.defines ).length > 0 ) data.defines = this.defines;
- for ( var key in parameters ) {
+ data.vertexShader = this.vertexShader;
+ data.fragmentShader = this.fragmentShader;
- if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ];
+ data.lights = this.lights;
+ data.clipping = this.clipping;
- }
+ const extensions = {};
- return data;
+ for ( const key in this.extensions ) {
- }
+ if ( this.extensions[ key ] === true ) extensions[ key ] = true;
- var vertices = [];
+ }
- for ( var i = 0; i < this.vertices.length; i ++ ) {
+ if ( Object.keys( extensions ).length > 0 ) data.extensions = extensions;
- var vertex = this.vertices[ i ];
- vertices.push( vertex.x, vertex.y, vertex.z );
+ return data;
- }
+ }
- var faces = [];
- var normals = [];
- var normalsHash = {};
- var colors = [];
- var colorsHash = {};
- var uvs = [];
- var uvsHash = {};
+}
- for ( var i = 0; i < this.faces.length; i ++ ) {
+class Camera extends Object3D {
- var face = this.faces[ i ];
+ constructor() {
- var hasMaterial = true;
- var hasFaceUv = false; // deprecated
- var hasFaceVertexUv = this.faceVertexUvs[ 0 ][ i ] !== 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;
+ super();
- var faceType = 0;
+ this.isCamera = true;
- 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 );
+ this.type = 'Camera';
- faces.push( faceType );
- faces.push( face.a, face.b, face.c );
- faces.push( face.materialIndex );
+ this.matrixWorldInverse = new Matrix4();
- if ( hasFaceVertexUv ) {
+ this.projectionMatrix = new Matrix4();
+ this.projectionMatrixInverse = new Matrix4();
- var faceVertexUvs = this.faceVertexUvs[ 0 ][ i ];
+ this.coordinateSystem = WebGLCoordinateSystem;
- faces.push(
- getUvIndex( faceVertexUvs[ 0 ] ),
- getUvIndex( faceVertexUvs[ 1 ] ),
- getUvIndex( faceVertexUvs[ 2 ] )
- );
+ }
- }
+ copy( source, recursive ) {
- if ( hasFaceNormal ) {
+ super.copy( source, recursive );
- faces.push( getNormalIndex( face.normal ) );
+ this.matrixWorldInverse.copy( source.matrixWorldInverse );
- }
+ this.projectionMatrix.copy( source.projectionMatrix );
+ this.projectionMatrixInverse.copy( source.projectionMatrixInverse );
- if ( hasFaceVertexNormal ) {
+ this.coordinateSystem = source.coordinateSystem;
- var vertexNormals = face.vertexNormals;
+ return this;
- faces.push(
- getNormalIndex( vertexNormals[ 0 ] ),
- getNormalIndex( vertexNormals[ 1 ] ),
- getNormalIndex( vertexNormals[ 2 ] )
- );
+ }
- }
+ getWorldDirection( target ) {
- if ( hasFaceColor ) {
+ return super.getWorldDirection( target ).negate();
- faces.push( getColorIndex( face.color ) );
+ }
- }
+ updateMatrixWorld( force ) {
- if ( hasFaceVertexColor ) {
+ super.updateMatrixWorld( force );
- var vertexColors = face.vertexColors;
+ this.matrixWorldInverse.copy( this.matrixWorld ).invert();
- faces.push(
- getColorIndex( vertexColors[ 0 ] ),
- getColorIndex( vertexColors[ 1 ] ),
- getColorIndex( vertexColors[ 2 ] )
- );
+ }
- }
+ updateWorldMatrix( updateParents, updateChildren ) {
- }
+ super.updateWorldMatrix( updateParents, updateChildren );
- function setBit( value, position, enabled ) {
+ this.matrixWorldInverse.copy( this.matrixWorld ).invert();
- return enabled ? value | ( 1 << position ) : value & ( ~ ( 1 << position ) );
+ }
- }
+ clone() {
- function getNormalIndex( normal ) {
+ return new this.constructor().copy( this );
- var hash = normal.x.toString() + normal.y.toString() + normal.z.toString();
+ }
- if ( normalsHash[ hash ] !== undefined ) {
+}
- return normalsHash[ hash ];
+class PerspectiveCamera extends Camera {
- }
+ constructor( fov = 50, aspect = 1, near = 0.1, far = 2000 ) {
- normalsHash[ hash ] = normals.length / 3;
- normals.push( normal.x, normal.y, normal.z );
+ super();
- return normalsHash[ hash ];
+ this.isPerspectiveCamera = true;
- }
+ this.type = 'PerspectiveCamera';
- function getColorIndex( color ) {
+ this.fov = fov;
+ this.zoom = 1;
- var hash = color.r.toString() + color.g.toString() + color.b.toString();
+ this.near = near;
+ this.far = far;
+ this.focus = 10;
- if ( colorsHash[ hash ] !== undefined ) {
+ this.aspect = aspect;
+ this.view = null;
- return colorsHash[ hash ];
+ this.filmGauge = 35; // width of the film (default in millimeters)
+ this.filmOffset = 0; // horizontal film offset (same unit as gauge)
- }
+ this.updateProjectionMatrix();
- colorsHash[ hash ] = colors.length;
- colors.push( color.getHex() );
+ }
- return colorsHash[ hash ];
+ copy( source, recursive ) {
- }
+ super.copy( source, recursive );
- function getUvIndex( uv ) {
+ this.fov = source.fov;
+ this.zoom = source.zoom;
- var hash = uv.x.toString() + uv.y.toString();
+ this.near = source.near;
+ this.far = source.far;
+ this.focus = source.focus;
- if ( uvsHash[ hash ] !== undefined ) {
+ this.aspect = source.aspect;
+ this.view = source.view === null ? null : Object.assign( {}, source.view );
- return uvsHash[ hash ];
+ this.filmGauge = source.filmGauge;
+ this.filmOffset = source.filmOffset;
- }
+ return this;
- uvsHash[ hash ] = uvs.length / 2;
- uvs.push( uv.x, uv.y );
+ }
- return uvsHash[ hash ];
+ /**
+ * Sets the FOV by focal length in respect to the current .filmGauge.
+ *
+ * The default film gauge is 35, so that the focal length can be specified for
+ * a 35mm (full frame) camera.
+ *
+ * Values for focal length and film gauge must have the same unit.
+ */
+ setFocalLength( focalLength ) {
- }
+ /** see {@link http://www.bobatkins.com/photography/technical/field_of_view.html} */
+ const vExtentSlope = 0.5 * this.getFilmHeight() / focalLength;
- data.data = {};
+ this.fov = RAD2DEG * 2 * Math.atan( vExtentSlope );
+ this.updateProjectionMatrix();
- 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;
+ /**
+ * Calculates the focal length from the current .fov and .filmGauge.
+ */
+ getFocalLength() {
- },
+ const vExtentSlope = Math.tan( DEG2RAD * 0.5 * this.fov );
- clone: function () {
+ return 0.5 * this.getFilmHeight() / vExtentSlope;
- /*
- // Handle primitives
+ }
- var parameters = this.parameters;
+ getEffectiveFOV() {
- if ( parameters !== undefined ) {
+ return RAD2DEG * 2 * Math.atan(
+ Math.tan( DEG2RAD * 0.5 * this.fov ) / this.zoom );
- var values = [];
+ }
- for ( var key in parameters ) {
+ getFilmWidth() {
- values.push( parameters[ key ] );
+ // film not completely covered in portrait format (aspect < 1)
+ return this.filmGauge * Math.min( this.aspect, 1 );
- }
+ }
- var geometry = Object.create( this.constructor.prototype );
- this.constructor.apply( geometry, values );
- return geometry;
+ getFilmHeight() {
- }
+ // film not completely covered in landscape format (aspect > 1)
+ return this.filmGauge / Math.max( this.aspect, 1 );
- return new this.constructor().copy( this );
- */
+ }
- return new Geometry().copy( this );
+ /**
+ * Sets an offset in a larger frustum. This is useful for multi-window or
+ * multi-monitor/multi-machine setups.
+ *
+ * For example, if you have 3x2 monitors and each monitor is 1920x1080 and
+ * the monitors are in grid like this
+ *
+ * +---+---+---+
+ * | A | B | C |
+ * +---+---+---+
+ * | D | E | F |
+ * +---+---+---+
+ *
+ * then for each monitor you would call it like this
+ *
+ * const w = 1920;
+ * const h = 1080;
+ * const fullWidth = w * 3;
+ * const fullHeight = h * 2;
+ *
+ * --A--
+ * camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 0, w, h );
+ * --B--
+ * camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 0, w, h );
+ * --C--
+ * camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 0, w, h );
+ * --D--
+ * camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 1, w, h );
+ * --E--
+ * camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 1, w, h );
+ * --F--
+ * camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 1, w, h );
+ *
+ * Note there is no reason monitors have to be the same size or in a grid.
+ */
+ setViewOffset( fullWidth, fullHeight, x, y, width, height ) {
- },
+ this.aspect = fullWidth / fullHeight;
- copy: function ( source ) {
+ if ( this.view === null ) {
- var i, il, j, jl, k, kl;
+ this.view = {
+ enabled: true,
+ fullWidth: 1,
+ fullHeight: 1,
+ offsetX: 0,
+ offsetY: 0,
+ width: 1,
+ height: 1
+ };
- // 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;
+ this.view.enabled = true;
+ this.view.fullWidth = fullWidth;
+ this.view.fullHeight = fullHeight;
+ this.view.offsetX = x;
+ this.view.offsetY = y;
+ this.view.width = width;
+ this.view.height = height;
- // name
+ this.updateProjectionMatrix();
- this.name = source.name;
+ }
- // vertices
+ clearViewOffset() {
- var vertices = source.vertices;
+ if ( this.view !== null ) {
- for ( i = 0, il = vertices.length; i < il; i ++ ) {
+ this.view.enabled = false;
- this.vertices.push( vertices[ i ].clone() );
+ }
- }
+ this.updateProjectionMatrix();
- // colors
+ }
- var colors = source.colors;
+ updateProjectionMatrix() {
- for ( i = 0, il = colors.length; i < il; i ++ ) {
+ const near = this.near;
+ let top = near * Math.tan( DEG2RAD * 0.5 * this.fov ) / this.zoom;
+ let height = 2 * top;
+ let width = this.aspect * height;
+ let left = - 0.5 * width;
+ const view = this.view;
- this.colors.push( colors[ i ].clone() );
+ if ( this.view !== null && this.view.enabled ) {
- }
+ const fullWidth = view.fullWidth,
+ fullHeight = view.fullHeight;
- // faces
+ left += view.offsetX * width / fullWidth;
+ top -= view.offsetY * height / fullHeight;
+ width *= view.width / fullWidth;
+ height *= view.height / fullHeight;
- var faces = source.faces;
+ }
- for ( i = 0, il = faces.length; i < il; i ++ ) {
+ const skew = this.filmOffset;
+ if ( skew !== 0 ) left += near * skew / this.getFilmWidth();
- this.faces.push( faces[ i ].clone() );
+ this.projectionMatrix.makePerspective( left, left + width, top, top - height, near, this.far, this.coordinateSystem );
- }
+ this.projectionMatrixInverse.copy( this.projectionMatrix ).invert();
- // face vertex uvs
+ }
- for ( i = 0, il = source.faceVertexUvs.length; i < il; i ++ ) {
+ toJSON( meta ) {
- var faceVertexUvs = source.faceVertexUvs[ i ];
+ const data = super.toJSON( meta );
- if ( this.faceVertexUvs[ i ] === undefined ) {
+ data.object.fov = this.fov;
+ data.object.zoom = this.zoom;
- this.faceVertexUvs[ i ] = [];
+ data.object.near = this.near;
+ data.object.far = this.far;
+ data.object.focus = this.focus;
- }
+ data.object.aspect = this.aspect;
- for ( j = 0, jl = faceVertexUvs.length; j < jl; j ++ ) {
+ if ( this.view !== null ) data.object.view = Object.assign( {}, this.view );
- var uvs = faceVertexUvs[ j ], uvsCopy = [];
+ data.object.filmGauge = this.filmGauge;
+ data.object.filmOffset = this.filmOffset;
- for ( k = 0, kl = uvs.length; k < kl; k ++ ) {
+ return data;
- var uv = uvs[ k ];
+ }
- uvsCopy.push( uv.clone() );
+}
- }
+const fov = - 90; // negative fov is not an error
+const aspect = 1;
- this.faceVertexUvs[ i ].push( uvsCopy );
+class CubeCamera extends Object3D {
- }
+ constructor( near, far, renderTarget ) {
- }
+ super();
- // morph targets
+ this.type = 'CubeCamera';
- var morphTargets = source.morphTargets;
+ this.renderTarget = renderTarget;
+ this.coordinateSystem = null;
+ this.activeMipmapLevel = 0;
- for ( i = 0, il = morphTargets.length; i < il; i ++ ) {
+ const cameraPX = new PerspectiveCamera( fov, aspect, near, far );
+ cameraPX.layers = this.layers;
+ this.add( cameraPX );
- var morphTarget = {};
- morphTarget.name = morphTargets[ i ].name;
+ const cameraNX = new PerspectiveCamera( fov, aspect, near, far );
+ cameraNX.layers = this.layers;
+ this.add( cameraNX );
- // vertices
+ const cameraPY = new PerspectiveCamera( fov, aspect, near, far );
+ cameraPY.layers = this.layers;
+ this.add( cameraPY );
- if ( morphTargets[ i ].vertices !== undefined ) {
+ const cameraNY = new PerspectiveCamera( fov, aspect, near, far );
+ cameraNY.layers = this.layers;
+ this.add( cameraNY );
- morphTarget.vertices = [];
+ const cameraPZ = new PerspectiveCamera( fov, aspect, near, far );
+ cameraPZ.layers = this.layers;
+ this.add( cameraPZ );
- for ( j = 0, jl = morphTargets[ i ].vertices.length; j < jl; j ++ ) {
+ const cameraNZ = new PerspectiveCamera( fov, aspect, near, far );
+ cameraNZ.layers = this.layers;
+ this.add( cameraNZ );
- morphTarget.vertices.push( morphTargets[ i ].vertices[ j ].clone() );
+ }
- }
+ updateCoordinateSystem() {
- }
+ const coordinateSystem = this.coordinateSystem;
- // normals
+ const cameras = this.children.concat();
- if ( morphTargets[ i ].normals !== undefined ) {
+ const [ cameraPX, cameraNX, cameraPY, cameraNY, cameraPZ, cameraNZ ] = cameras;
- morphTarget.normals = [];
+ for ( const camera of cameras ) this.remove( camera );
- for ( j = 0, jl = morphTargets[ i ].normals.length; j < jl; j ++ ) {
+ if ( coordinateSystem === WebGLCoordinateSystem ) {
- morphTarget.normals.push( morphTargets[ i ].normals[ j ].clone() );
+ cameraPX.up.set( 0, 1, 0 );
+ cameraPX.lookAt( 1, 0, 0 );
- }
+ cameraNX.up.set( 0, 1, 0 );
+ cameraNX.lookAt( - 1, 0, 0 );
- }
+ cameraPY.up.set( 0, 0, - 1 );
+ cameraPY.lookAt( 0, 1, 0 );
- this.morphTargets.push( morphTarget );
+ cameraNY.up.set( 0, 0, 1 );
+ cameraNY.lookAt( 0, - 1, 0 );
- }
+ cameraPZ.up.set( 0, 1, 0 );
+ cameraPZ.lookAt( 0, 0, 1 );
- // morph normals
+ cameraNZ.up.set( 0, 1, 0 );
+ cameraNZ.lookAt( 0, 0, - 1 );
- var morphNormals = source.morphNormals;
+ } else if ( coordinateSystem === WebGPUCoordinateSystem ) {
- for ( i = 0, il = morphNormals.length; i < il; i ++ ) {
+ cameraPX.up.set( 0, - 1, 0 );
+ cameraPX.lookAt( - 1, 0, 0 );
- var morphNormal = {};
+ cameraNX.up.set( 0, - 1, 0 );
+ cameraNX.lookAt( 1, 0, 0 );
- // vertex normals
+ cameraPY.up.set( 0, 0, 1 );
+ cameraPY.lookAt( 0, 1, 0 );
- if ( morphNormals[ i ].vertexNormals !== undefined ) {
+ cameraNY.up.set( 0, 0, - 1 );
+ cameraNY.lookAt( 0, - 1, 0 );
- morphNormal.vertexNormals = [];
+ cameraPZ.up.set( 0, - 1, 0 );
+ cameraPZ.lookAt( 0, 0, 1 );
- for ( j = 0, jl = morphNormals[ i ].vertexNormals.length; j < jl; j ++ ) {
+ cameraNZ.up.set( 0, - 1, 0 );
+ cameraNZ.lookAt( 0, 0, - 1 );
- var srcVertexNormal = morphNormals[ i ].vertexNormals[ j ];
- var destVertexNormal = {};
+ } else {
- destVertexNormal.a = srcVertexNormal.a.clone();
- destVertexNormal.b = srcVertexNormal.b.clone();
- destVertexNormal.c = srcVertexNormal.c.clone();
+ throw new Error( 'THREE.CubeCamera.updateCoordinateSystem(): Invalid coordinate system: ' + coordinateSystem );
- morphNormal.vertexNormals.push( destVertexNormal );
+ }
- }
+ for ( const camera of cameras ) {
- }
+ this.add( camera );
- // face normals
+ camera.updateMatrixWorld();
- if ( morphNormals[ i ].faceNormals !== undefined ) {
+ }
- morphNormal.faceNormals = [];
+ }
- for ( j = 0, jl = morphNormals[ i ].faceNormals.length; j < jl; j ++ ) {
+ update( renderer, scene ) {
- morphNormal.faceNormals.push( morphNormals[ i ].faceNormals[ j ].clone() );
+ if ( this.parent === null ) this.updateMatrixWorld();
- }
+ const { renderTarget, activeMipmapLevel } = this;
- }
+ if ( this.coordinateSystem !== renderer.coordinateSystem ) {
- this.morphNormals.push( morphNormal );
+ this.coordinateSystem = renderer.coordinateSystem;
- }
+ this.updateCoordinateSystem();
- // skin weights
+ }
- var skinWeights = source.skinWeights;
+ const [ cameraPX, cameraNX, cameraPY, cameraNY, cameraPZ, cameraNZ ] = this.children;
- for ( i = 0, il = skinWeights.length; i < il; i ++ ) {
+ const currentRenderTarget = renderer.getRenderTarget();
+ const currentActiveCubeFace = renderer.getActiveCubeFace();
+ const currentActiveMipmapLevel = renderer.getActiveMipmapLevel();
- this.skinWeights.push( skinWeights[ i ].clone() );
+ const currentXrEnabled = renderer.xr.enabled;
- }
+ renderer.xr.enabled = false;
- // skin indices
+ const generateMipmaps = renderTarget.texture.generateMipmaps;
- var skinIndices = source.skinIndices;
+ renderTarget.texture.generateMipmaps = false;
- for ( i = 0, il = skinIndices.length; i < il; i ++ ) {
+ renderer.setRenderTarget( renderTarget, 0, activeMipmapLevel );
+ renderer.render( scene, cameraPX );
- this.skinIndices.push( skinIndices[ i ].clone() );
+ renderer.setRenderTarget( renderTarget, 1, activeMipmapLevel );
+ renderer.render( scene, cameraNX );
- }
+ renderer.setRenderTarget( renderTarget, 2, activeMipmapLevel );
+ renderer.render( scene, cameraPY );
- // line distances
+ renderer.setRenderTarget( renderTarget, 3, activeMipmapLevel );
+ renderer.render( scene, cameraNY );
- var lineDistances = source.lineDistances;
+ renderer.setRenderTarget( renderTarget, 4, activeMipmapLevel );
+ renderer.render( scene, cameraPZ );
- for ( i = 0, il = lineDistances.length; i < il; i ++ ) {
+ // mipmaps are generated during the last call of render()
+ // at this point, all sides of the cube render target are defined
- this.lineDistances.push( lineDistances[ i ] );
+ renderTarget.texture.generateMipmaps = generateMipmaps;
- }
+ renderer.setRenderTarget( renderTarget, 5, activeMipmapLevel );
+ renderer.render( scene, cameraNZ );
- // bounding box
+ renderer.setRenderTarget( currentRenderTarget, currentActiveCubeFace, currentActiveMipmapLevel );
- var boundingBox = source.boundingBox;
+ renderer.xr.enabled = currentXrEnabled;
- if ( boundingBox !== null ) {
+ renderTarget.texture.needsPMREMUpdate = true;
- this.boundingBox = boundingBox.clone();
+ }
- }
+}
- // bounding sphere
+class CubeTexture extends Texture {
- var boundingSphere = source.boundingSphere;
+ constructor( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace ) {
- if ( boundingSphere !== null ) {
+ images = images !== undefined ? images : [];
+ mapping = mapping !== undefined ? mapping : CubeReflectionMapping;
- this.boundingSphere = boundingSphere.clone();
+ super( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace );
- }
+ this.isCubeTexture = true;
- // update flags
+ this.flipY = false;
- 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;
+ get images() {
- },
+ return this.image;
- dispose: function () {
+ }
- this.dispatchEvent( { type: 'dispose' } );
+ set images( value ) {
- }
+ this.image = value;
- } );
+ }
- /**
- * @author mrdoob / http://mrdoob.com/
- * @author Mugen87 / https://github.com/Mugen87
- */
+}
- // BoxGeometry
+class WebGLCubeRenderTarget extends WebGLRenderTarget {
- function BoxGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) {
+ constructor( size = 1, options = {} ) {
- Geometry.call( this );
+ super( size, size, options );
- this.type = 'BoxGeometry';
+ this.isWebGLCubeRenderTarget = true;
- this.parameters = {
- width: width,
- height: height,
- depth: depth,
- widthSegments: widthSegments,
- heightSegments: heightSegments,
- depthSegments: depthSegments
- };
+ const image = { width: size, height: size, depth: 1 };
+ const images = [ image, image, image, image, image, image ];
- this.fromBufferGeometry( new BoxBufferGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) );
- this.mergeVertices();
+ if ( options.encoding !== undefined ) {
- }
+ // @deprecated, r152
+ warnOnce( 'THREE.WebGLCubeRenderTarget: option.encoding has been replaced by option.colorSpace.' );
+ options.colorSpace = options.encoding === sRGBEncoding ? SRGBColorSpace : NoColorSpace;
- BoxGeometry.prototype = Object.create( Geometry.prototype );
- BoxGeometry.prototype.constructor = BoxGeometry;
+ }
- // BoxBufferGeometry
+ this.texture = new CubeTexture( images, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.colorSpace );
- function BoxBufferGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) {
+ // By convention -- likely based on the RenderMan spec from the 1990's -- cube maps are specified by WebGL (and three.js)
+ // in a coordinate system in which positive-x is to the right when looking up the positive-z axis -- in other words,
+ // in a left-handed coordinate system. By continuing this convention, preexisting cube maps continued to render correctly.
- BufferGeometry.call( this );
+ // three.js uses a right-handed coordinate system. So environment maps used in three.js appear to have px and nx swapped
+ // and the flag isRenderTargetTexture controls this conversion. The flip is not required when using WebGLCubeRenderTarget.texture
+ // as a cube texture (this is detected when isRenderTargetTexture is set to true for cube textures).
- this.type = 'BoxBufferGeometry';
+ this.texture.isRenderTargetTexture = true;
- this.parameters = {
- width: width,
- height: height,
- depth: depth,
- widthSegments: widthSegments,
- heightSegments: heightSegments,
- depthSegments: depthSegments
- };
+ this.texture.generateMipmaps = options.generateMipmaps !== undefined ? options.generateMipmaps : false;
+ this.texture.minFilter = options.minFilter !== undefined ? options.minFilter : LinearFilter;
- var scope = this;
+ }
- width = width || 1;
- height = height || 1;
- depth = depth || 1;
+ fromEquirectangularTexture( renderer, texture ) {
- // segments
+ this.texture.type = texture.type;
+ this.texture.colorSpace = texture.colorSpace;
- widthSegments = Math.floor( widthSegments ) || 1;
- heightSegments = Math.floor( heightSegments ) || 1;
- depthSegments = Math.floor( depthSegments ) || 1;
+ this.texture.generateMipmaps = texture.generateMipmaps;
+ this.texture.minFilter = texture.minFilter;
+ this.texture.magFilter = texture.magFilter;
- // buffers
+ const shader = {
- var indices = [];
- var vertices = [];
- var normals = [];
- var uvs = [];
+ uniforms: {
+ tEquirect: { value: null },
+ },
- // helper variables
+ vertexShader: /* glsl */`
- var numberOfVertices = 0;
- var groupStart = 0;
+ varying vec3 vWorldDirection;
- // build each side of the box geometry
+ vec3 transformDirection( in vec3 dir, in mat4 matrix ) {
- buildPlane( 'z', 'y', 'x', - 1, - 1, depth, height, width, depthSegments, heightSegments, 0 ); // px
- buildPlane( 'z', 'y', 'x', 1, - 1, depth, height, - width, depthSegments, heightSegments, 1 ); // nx
- buildPlane( 'x', 'z', 'y', 1, 1, width, depth, height, widthSegments, depthSegments, 2 ); // py
- buildPlane( 'x', 'z', 'y', 1, - 1, width, depth, - height, widthSegments, depthSegments, 3 ); // ny
- buildPlane( 'x', 'y', 'z', 1, - 1, width, height, depth, widthSegments, heightSegments, 4 ); // pz
- buildPlane( 'x', 'y', 'z', - 1, - 1, width, height, - depth, widthSegments, heightSegments, 5 ); // nz
+ return normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );
- // build geometry
+ }
- this.setIndex( indices );
- this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
- this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
- this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
+ void main() {
- function buildPlane( u, v, w, udir, vdir, width, height, depth, gridX, gridY, materialIndex ) {
+ vWorldDirection = transformDirection( position, modelMatrix );
- var segmentWidth = width / gridX;
- var segmentHeight = height / gridY;
+ #include
+ #include
- var widthHalf = width / 2;
- var heightHalf = height / 2;
- var depthHalf = depth / 2;
+ }
+ `,
- var gridX1 = gridX + 1;
- var gridY1 = gridY + 1;
+ fragmentShader: /* glsl */`
- var vertexCounter = 0;
- var groupCount = 0;
+ uniform sampler2D tEquirect;
- var ix, iy;
+ varying vec3 vWorldDirection;
- var vector = new Vector3();
+ #include
- // generate vertices, normals and uvs
+ void main() {
- for ( iy = 0; iy < gridY1; iy ++ ) {
+ vec3 direction = normalize( vWorldDirection );
- var y = iy * segmentHeight - heightHalf;
+ vec2 sampleUV = equirectUv( direction );
- for ( ix = 0; ix < gridX1; ix ++ ) {
+ gl_FragColor = texture2D( tEquirect, sampleUV );
- var x = ix * segmentWidth - widthHalf;
+ }
+ `
+ };
- // set values to correct vector component
+ const geometry = new BoxGeometry( 5, 5, 5 );
- vector[ u ] = x * udir;
- vector[ v ] = y * vdir;
- vector[ w ] = depthHalf;
+ const material = new ShaderMaterial( {
- // now apply vector to vertex buffer
+ name: 'CubemapFromEquirect',
- vertices.push( vector.x, vector.y, vector.z );
+ uniforms: cloneUniforms( shader.uniforms ),
+ vertexShader: shader.vertexShader,
+ fragmentShader: shader.fragmentShader,
+ side: BackSide,
+ blending: NoBlending
- // set values to correct vector component
+ } );
- vector[ u ] = 0;
- vector[ v ] = 0;
- vector[ w ] = depth > 0 ? 1 : - 1;
+ material.uniforms.tEquirect.value = texture;
- // now apply vector to normal buffer
+ const mesh = new Mesh( geometry, material );
- normals.push( vector.x, vector.y, vector.z );
+ const currentMinFilter = texture.minFilter;
- // uvs
+ // Avoid blurred poles
+ if ( texture.minFilter === LinearMipmapLinearFilter ) texture.minFilter = LinearFilter;
- uvs.push( ix / gridX );
- uvs.push( 1 - ( iy / gridY ) );
+ const camera = new CubeCamera( 1, 10, this );
+ camera.update( renderer, mesh );
- // counters
+ texture.minFilter = currentMinFilter;
- vertexCounter += 1;
+ mesh.geometry.dispose();
+ mesh.material.dispose();
- }
+ return this;
- }
+ }
- // indices
+ clear( renderer, color, depth, stencil ) {
- // 1. you need three indices to draw a single face
- // 2. a single segment consists of two faces
- // 3. so we need to generate six (2*3) indices per segment
+ const currentRenderTarget = renderer.getRenderTarget();
- for ( iy = 0; iy < gridY; iy ++ ) {
+ for ( let i = 0; i < 6; i ++ ) {
- for ( ix = 0; ix < gridX; ix ++ ) {
+ renderer.setRenderTarget( this, i );
- var a = numberOfVertices + ix + gridX1 * iy;
- var b = numberOfVertices + ix + gridX1 * ( iy + 1 );
- var c = numberOfVertices + ( ix + 1 ) + gridX1 * ( iy + 1 );
- var d = numberOfVertices + ( ix + 1 ) + gridX1 * iy;
+ renderer.clear( color, depth, stencil );
- // faces
+ }
- indices.push( a, b, d );
- indices.push( b, c, d );
+ renderer.setRenderTarget( currentRenderTarget );
- // increase counter
+ }
- groupCount += 6;
+}
- }
+const _vector1 = /*@__PURE__*/ new Vector3();
+const _vector2 = /*@__PURE__*/ new Vector3();
+const _normalMatrix = /*@__PURE__*/ new Matrix3();
- }
+class Plane {
- // add a group to the geometry. this will ensure multi material support
+ constructor( normal = new Vector3( 1, 0, 0 ), constant = 0 ) {
- scope.addGroup( groupStart, groupCount, materialIndex );
+ this.isPlane = true;
- // calculate new start value for groups
+ // normal is assumed to be normalized
- groupStart += groupCount;
+ this.normal = normal;
+ this.constant = constant;
- // update total number of vertices
+ }
- numberOfVertices += vertexCounter;
+ set( normal, constant ) {
- }
+ this.normal.copy( normal );
+ this.constant = constant;
- }
+ return this;
- BoxBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
- BoxBufferGeometry.prototype.constructor = BoxBufferGeometry;
+ }
- /**
- * Uniform Utilities
- */
+ setComponents( x, y, z, w ) {
- function cloneUniforms( src ) {
+ this.normal.set( x, y, z );
+ this.constant = w;
- var dst = {};
+ return this;
- for ( var u in src ) {
+ }
- dst[ u ] = {};
+ setFromNormalAndCoplanarPoint( normal, point ) {
- for ( var p in src[ u ] ) {
+ this.normal.copy( normal );
+ this.constant = - point.dot( this.normal );
- var property = src[ u ][ p ];
+ return this;
- if ( property && ( property.isColor ||
- property.isMatrix3 || property.isMatrix4 ||
- property.isVector2 || property.isVector3 || property.isVector4 ||
- property.isTexture ) ) {
+ }
- dst[ u ][ p ] = property.clone();
+ setFromCoplanarPoints( a, b, c ) {
- } else if ( Array.isArray( property ) ) {
+ const normal = _vector1.subVectors( c, b ).cross( _vector2.subVectors( a, b ) ).normalize();
- dst[ u ][ p ] = property.slice();
+ // Q: should an error be thrown if normal is zero (e.g. degenerate plane)?
- } else {
+ this.setFromNormalAndCoplanarPoint( normal, a );
- dst[ u ][ p ] = property;
+ return this;
- }
+ }
- }
+ copy( plane ) {
- }
+ this.normal.copy( plane.normal );
+ this.constant = plane.constant;
- return dst;
+ return this;
}
- function mergeUniforms( uniforms ) {
+ normalize() {
- var merged = {};
+ // Note: will lead to a divide by zero if the plane is invalid.
- for ( var u = 0; u < uniforms.length; u ++ ) {
+ const inverseNormalLength = 1.0 / this.normal.length();
+ this.normal.multiplyScalar( inverseNormalLength );
+ this.constant *= inverseNormalLength;
- var tmp = cloneUniforms( uniforms[ u ] );
+ return this;
- for ( var p in tmp ) {
+ }
- merged[ p ] = tmp[ p ];
+ negate() {
- }
+ this.constant *= - 1;
+ this.normal.negate();
- }
+ return this;
+
+ }
+
+ distanceToPoint( point ) {
- return merged;
+ return this.normal.dot( point ) + this.constant;
}
- // Legacy
+ distanceToSphere( sphere ) {
- var UniformsUtils = { clone: cloneUniforms, merge: mergeUniforms };
+ return this.distanceToPoint( sphere.center ) - sphere.radius;
- var default_vertex = "void main() {\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}";
+ }
- var default_fragment = "void main() {\n\tgl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );\n}";
+ projectPoint( point, target ) {
- /**
- * @author alteredq / http://alteredqualia.com/
- *
- * parameters = {
- * defines: { "label" : "value" },
- * uniforms: { "parameter1": { value: 1.0 }, "parameter2": { value2: 2 } },
- *
- * fragmentShader: ,
- * vertexShader: ,
- *
- * wireframe: ,
- * wireframeLinewidth: ,
- *
- * lights: ,
- *
- * skinning: ,
- * morphTargets: ,
- * morphNormals:
- * }
- */
+ return target.copy( point ).addScaledVector( this.normal, - this.distanceToPoint( point ) );
- function ShaderMaterial( parameters ) {
+ }
- Material.call( this );
+ intersectLine( line, target ) {
- this.type = 'ShaderMaterial';
+ const direction = line.delta( _vector1 );
- this.defines = {};
- this.uniforms = {};
+ const denominator = this.normal.dot( direction );
- this.vertexShader = default_vertex;
- this.fragmentShader = default_fragment;
+ if ( denominator === 0 ) {
- this.linewidth = 1;
+ // line is coplanar, return origin
+ if ( this.distanceToPoint( line.start ) === 0 ) {
- this.wireframe = false;
- this.wireframeLinewidth = 1;
+ return target.copy( line.start );
- this.fog = false; // set to use scene fog
- this.lights = false; // set to use scene lights
- this.clipping = false; // set to use user-defined clipping planes
+ }
- this.skinning = false; // set to use skinning attribute streams
- this.morphTargets = false; // set to use morph targets
- this.morphNormals = false; // set to use morph normals
+ // Unsure if this is the correct method to handle this case.
+ return null;
- this.extensions = {
- derivatives: false, // set to use derivatives
- fragDepth: false, // set to use fragment depth values
- drawBuffers: false, // set to use draw buffers
- shaderTextureLOD: false // set to use shader texture LOD
- };
+ }
- // When rendered geometry doesn't include these attributes but the material does,
- // use these default values in WebGL. This avoids errors when buffer data is missing.
- this.defaultAttributeValues = {
- 'color': [ 1, 1, 1 ],
- 'uv': [ 0, 0 ],
- 'uv2': [ 0, 0 ]
- };
+ const t = - ( line.start.dot( this.normal ) + this.constant ) / denominator;
- this.index0AttributeName = undefined;
- this.uniformsNeedUpdate = false;
+ if ( t < 0 || t > 1 ) {
- if ( parameters !== undefined ) {
+ return null;
+
+ }
- if ( parameters.attributes !== undefined ) {
+ return target.copy( line.start ).addScaledVector( direction, t );
- console.error( 'THREE.ShaderMaterial: attributes should now be defined in THREE.BufferGeometry instead.' );
+ }
- }
+ intersectsLine( line ) {
- this.setValues( parameters );
+ // Note: this tests if a line intersects the plane, not whether it (or its end-points) are coplanar with it.
- }
+ const startSign = this.distanceToPoint( line.start );
+ const endSign = this.distanceToPoint( line.end );
+
+ return ( startSign < 0 && endSign > 0 ) || ( endSign < 0 && startSign > 0 );
}
- ShaderMaterial.prototype = Object.create( Material.prototype );
- ShaderMaterial.prototype.constructor = ShaderMaterial;
+ intersectsBox( box ) {
- ShaderMaterial.prototype.isShaderMaterial = true;
+ return box.intersectsPlane( this );
- ShaderMaterial.prototype.copy = function ( source ) {
+ }
- Material.prototype.copy.call( this, source );
+ intersectsSphere( sphere ) {
- this.fragmentShader = source.fragmentShader;
- this.vertexShader = source.vertexShader;
+ return sphere.intersectsPlane( this );
- this.uniforms = cloneUniforms( source.uniforms );
+ }
- this.defines = Object.assign( {}, source.defines );
+ coplanarPoint( target ) {
- this.wireframe = source.wireframe;
- this.wireframeLinewidth = source.wireframeLinewidth;
+ return target.copy( this.normal ).multiplyScalar( - this.constant );
- this.lights = source.lights;
- this.clipping = source.clipping;
+ }
+
+ applyMatrix4( matrix, optionalNormalMatrix ) {
- this.skinning = source.skinning;
+ const normalMatrix = optionalNormalMatrix || _normalMatrix.getNormalMatrix( matrix );
- this.morphTargets = source.morphTargets;
- this.morphNormals = source.morphNormals;
+ const referencePoint = this.coplanarPoint( _vector1 ).applyMatrix4( matrix );
- this.extensions = source.extensions;
+ const normal = this.normal.applyMatrix3( normalMatrix ).normalize();
+
+ this.constant = - referencePoint.dot( normal );
return this;
- };
+ }
- ShaderMaterial.prototype.toJSON = function ( meta ) {
+ translate( offset ) {
- var data = Material.prototype.toJSON.call( this, meta );
+ this.constant -= offset.dot( this.normal );
- data.uniforms = {};
+ return this;
- for ( var name in this.uniforms ) {
+ }
- var uniform = this.uniforms[ name ];
- var value = uniform.value;
+ equals( plane ) {
- if ( value && value.isTexture ) {
+ return plane.normal.equals( this.normal ) && ( plane.constant === this.constant );
- data.uniforms[ name ] = {
- type: 't',
- value: value.toJSON( meta ).uuid
- };
+ }
- } else if ( value && value.isColor ) {
+ clone() {
- data.uniforms[ name ] = {
- type: 'c',
- value: value.getHex()
- };
+ return new this.constructor().copy( this );
- } else if ( value && value.isVector2 ) {
+ }
- data.uniforms[ name ] = {
- type: 'v2',
- value: value.toArray()
- };
+}
- } else if ( value && value.isVector3 ) {
+const _sphere$4 = /*@__PURE__*/ new Sphere();
+const _vector$6 = /*@__PURE__*/ new Vector3();
- data.uniforms[ name ] = {
- type: 'v3',
- value: value.toArray()
- };
+class Frustum {
- } else if ( value && value.isVector4 ) {
+ constructor( p0 = new Plane(), p1 = new Plane(), p2 = new Plane(), p3 = new Plane(), p4 = new Plane(), p5 = new Plane() ) {
- data.uniforms[ name ] = {
- type: 'v4',
- value: value.toArray()
- };
+ this.planes = [ p0, p1, p2, p3, p4, p5 ];
- } else if ( value && value.isMatrix3 ) {
+ }
- data.uniforms[ name ] = {
- type: 'm3',
- value: value.toArray()
- };
+ set( p0, p1, p2, p3, p4, p5 ) {
- } else if ( value && value.isMatrix4 ) {
+ const planes = this.planes;
- data.uniforms[ name ] = {
- type: 'm4',
- value: value.toArray()
- };
+ planes[ 0 ].copy( p0 );
+ planes[ 1 ].copy( p1 );
+ planes[ 2 ].copy( p2 );
+ planes[ 3 ].copy( p3 );
+ planes[ 4 ].copy( p4 );
+ planes[ 5 ].copy( p5 );
- } else {
+ return this;
- data.uniforms[ name ] = {
- value: value
- };
+ }
- // note: the array variants v2v, v3v, v4v, m4v and tv are not supported so far
+ copy( frustum ) {
- }
+ const planes = this.planes;
+
+ for ( let i = 0; i < 6; i ++ ) {
+
+ planes[ i ].copy( frustum.planes[ i ] );
}
- if ( Object.keys( this.defines ).length > 0 ) data.defines = this.defines;
+ return this;
- data.vertexShader = this.vertexShader;
- data.fragmentShader = this.fragmentShader;
+ }
- var extensions = {};
+ setFromProjectionMatrix( m, coordinateSystem = WebGLCoordinateSystem ) {
- for ( var key in this.extensions ) {
+ const planes = this.planes;
+ const me = m.elements;
+ const me0 = me[ 0 ], me1 = me[ 1 ], me2 = me[ 2 ], me3 = me[ 3 ];
+ const me4 = me[ 4 ], me5 = me[ 5 ], me6 = me[ 6 ], me7 = me[ 7 ];
+ const me8 = me[ 8 ], me9 = me[ 9 ], me10 = me[ 10 ], me11 = me[ 11 ];
+ const me12 = me[ 12 ], me13 = me[ 13 ], me14 = me[ 14 ], me15 = me[ 15 ];
- if ( this.extensions[ key ] === true ) extensions[ key ] = true;
+ planes[ 0 ].setComponents( me3 - me0, me7 - me4, me11 - me8, me15 - me12 ).normalize();
+ planes[ 1 ].setComponents( me3 + me0, me7 + me4, me11 + me8, me15 + me12 ).normalize();
+ planes[ 2 ].setComponents( me3 + me1, me7 + me5, me11 + me9, me15 + me13 ).normalize();
+ planes[ 3 ].setComponents( me3 - me1, me7 - me5, me11 - me9, me15 - me13 ).normalize();
+ planes[ 4 ].setComponents( me3 - me2, me7 - me6, me11 - me10, me15 - me14 ).normalize();
+
+ if ( coordinateSystem === WebGLCoordinateSystem ) {
+
+ planes[ 5 ].setComponents( me3 + me2, me7 + me6, me11 + me10, me15 + me14 ).normalize();
+
+ } else if ( coordinateSystem === WebGPUCoordinateSystem ) {
+
+ planes[ 5 ].setComponents( me2, me6, me10, me14 ).normalize();
+
+ } else {
+
+ throw new Error( 'THREE.Frustum.setFromProjectionMatrix(): Invalid coordinate system: ' + coordinateSystem );
}
- if ( Object.keys( extensions ).length > 0 ) data.extensions = extensions;
+ return this;
- return data;
+ }
- };
+ intersectsObject( object ) {
- /**
- * @author mrdoob / http://mrdoob.com/
- * @author mikael emtinger / http://gomo.se/
- * @author WestLangley / http://github.com/WestLangley
- */
+ if ( object.boundingSphere !== undefined ) {
- function Camera() {
+ if ( object.boundingSphere === null ) object.computeBoundingSphere();
- Object3D.call( this );
+ _sphere$4.copy( object.boundingSphere ).applyMatrix4( object.matrixWorld );
- this.type = 'Camera';
+ } else {
- this.matrixWorldInverse = new Matrix4();
+ const geometry = object.geometry;
- this.projectionMatrix = new Matrix4();
- this.projectionMatrixInverse = new Matrix4();
+ if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
- }
+ _sphere$4.copy( geometry.boundingSphere ).applyMatrix4( object.matrixWorld );
+
+ }
- Camera.prototype = Object.assign( Object.create( Object3D.prototype ), {
+ return this.intersectsSphere( _sphere$4 );
- constructor: Camera,
+ }
- isCamera: true,
+ intersectsSprite( sprite ) {
- copy: function ( source, recursive ) {
+ _sphere$4.center.set( 0, 0, 0 );
+ _sphere$4.radius = 0.7071067811865476;
+ _sphere$4.applyMatrix4( sprite.matrixWorld );
- Object3D.prototype.copy.call( this, source, recursive );
+ return this.intersectsSphere( _sphere$4 );
- this.matrixWorldInverse.copy( source.matrixWorldInverse );
+ }
- this.projectionMatrix.copy( source.projectionMatrix );
- this.projectionMatrixInverse.copy( source.projectionMatrixInverse );
+ intersectsSphere( sphere ) {
- return this;
+ const planes = this.planes;
+ const center = sphere.center;
+ const negRadius = - sphere.radius;
- },
+ for ( let i = 0; i < 6; i ++ ) {
- getWorldDirection: function ( target ) {
+ const distance = planes[ i ].distanceToPoint( center );
- if ( target === undefined ) {
+ if ( distance < negRadius ) {
- console.warn( 'THREE.Camera: .getWorldDirection() target is now required' );
- target = new Vector3();
+ return false;
}
- this.updateMatrixWorld( true );
+ }
+
+ return true;
- var e = this.matrixWorld.elements;
+ }
- return target.set( - e[ 8 ], - e[ 9 ], - e[ 10 ] ).normalize();
+ intersectsBox( box ) {
- },
+ const planes = this.planes;
- updateMatrixWorld: function ( force ) {
+ for ( let i = 0; i < 6; i ++ ) {
- Object3D.prototype.updateMatrixWorld.call( this, force );
+ const plane = planes[ i ];
- this.matrixWorldInverse.getInverse( this.matrixWorld );
+ // corner at max distance
- },
+ _vector$6.x = plane.normal.x > 0 ? box.max.x : box.min.x;
+ _vector$6.y = plane.normal.y > 0 ? box.max.y : box.min.y;
+ _vector$6.z = plane.normal.z > 0 ? box.max.z : box.min.z;
+
+ if ( plane.distanceToPoint( _vector$6 ) < 0 ) {
- clone: function () {
+ return false;
- return new this.constructor().copy( this );
+ }
}
- } );
+ return true;
- /**
- * @author mrdoob / http://mrdoob.com/
- * @author greggman / http://games.greggman.com/
- * @author zz85 / http://www.lab4games.net/zz85/blog
- * @author tschw
- */
+ }
- function PerspectiveCamera( fov, aspect, near, far ) {
+ containsPoint( point ) {
- Camera.call( this );
+ const planes = this.planes;
- this.type = 'PerspectiveCamera';
+ for ( let i = 0; i < 6; i ++ ) {
- this.fov = fov !== undefined ? fov : 50;
- this.zoom = 1;
+ if ( planes[ i ].distanceToPoint( point ) < 0 ) {
- this.near = near !== undefined ? near : 0.1;
- this.far = far !== undefined ? far : 2000;
- this.focus = 10;
+ return false;
- this.aspect = aspect !== undefined ? aspect : 1;
- this.view = null;
+ }
- this.filmGauge = 35; // width of the film (default in millimeters)
- this.filmOffset = 0; // horizontal film offset (same unit as gauge)
+ }
- this.updateProjectionMatrix();
+ return true;
}
- PerspectiveCamera.prototype = Object.assign( Object.create( Camera.prototype ), {
+ clone() {
+
+ return new this.constructor().copy( this );
- constructor: PerspectiveCamera,
+ }
- isPerspectiveCamera: true,
+}
- copy: function ( source, recursive ) {
+function WebGLAnimation() {
- Camera.prototype.copy.call( this, source, recursive );
+ let context = null;
+ let isAnimating = false;
+ let animationLoop = null;
+ let requestId = null;
- this.fov = source.fov;
- this.zoom = source.zoom;
+ function onAnimationFrame( time, frame ) {
- this.near = source.near;
- this.far = source.far;
- this.focus = source.focus;
+ animationLoop( time, frame );
- this.aspect = source.aspect;
- this.view = source.view === null ? null : Object.assign( {}, source.view );
+ requestId = context.requestAnimationFrame( onAnimationFrame );
- this.filmGauge = source.filmGauge;
- this.filmOffset = source.filmOffset;
+ }
- return this;
+ return {
- },
+ start: function () {
- /**
- * Sets the FOV by focal length in respect to the current .filmGauge.
- *
- * The default film gauge is 35, so that the focal length can be specified for
- * a 35mm (full frame) camera.
- *
- * Values for focal length and film gauge must have the same unit.
- */
- setFocalLength: function ( focalLength ) {
+ if ( isAnimating === true ) return;
+ if ( animationLoop === null ) return;
- // see http://www.bobatkins.com/photography/technical/field_of_view.html
- var vExtentSlope = 0.5 * this.getFilmHeight() / focalLength;
+ requestId = context.requestAnimationFrame( onAnimationFrame );
- this.fov = _Math.RAD2DEG * 2 * Math.atan( vExtentSlope );
- this.updateProjectionMatrix();
+ isAnimating = true;
},
- /**
- * Calculates the focal length from the current .fov and .filmGauge.
- */
- getFocalLength: function () {
+ stop: function () {
- var vExtentSlope = Math.tan( _Math.DEG2RAD * 0.5 * this.fov );
+ context.cancelAnimationFrame( requestId );
- return 0.5 * this.getFilmHeight() / vExtentSlope;
+ isAnimating = false;
},
- getEffectiveFOV: function () {
+ setAnimationLoop: function ( callback ) {
- return _Math.RAD2DEG * 2 * Math.atan(
- Math.tan( _Math.DEG2RAD * 0.5 * this.fov ) / this.zoom );
+ animationLoop = callback;
},
- getFilmWidth: function () {
+ setContext: function ( value ) {
- // film not completely covered in portrait format (aspect < 1)
- return this.filmGauge * Math.min( this.aspect, 1 );
+ context = value;
- },
+ }
- getFilmHeight: function () {
+ };
- // film not completely covered in landscape format (aspect > 1)
- return this.filmGauge / Math.max( this.aspect, 1 );
+}
- },
+function WebGLAttributes( gl, capabilities ) {
- /**
- * Sets an offset in a larger frustum. This is useful for multi-window or
- * multi-monitor/multi-machine setups.
- *
- * For example, if you have 3x2 monitors and each monitor is 1920x1080 and
- * the monitors are in grid like this
- *
- * +---+---+---+
- * | A | B | C |
- * +---+---+---+
- * | D | E | F |
- * +---+---+---+
- *
- * then for each monitor you would call it like this
- *
- * var w = 1920;
- * var h = 1080;
- * var fullWidth = w * 3;
- * var fullHeight = h * 2;
- *
- * --A--
- * camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 0, w, h );
- * --B--
- * camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 0, w, h );
- * --C--
- * camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 0, w, h );
- * --D--
- * camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 1, w, h );
- * --E--
- * camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 1, w, h );
- * --F--
- * camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 1, w, h );
- *
- * Note there is no reason monitors have to be the same size or in a grid.
- */
- setViewOffset: function ( fullWidth, fullHeight, x, y, width, height ) {
+ const isWebGL2 = capabilities.isWebGL2;
- this.aspect = fullWidth / fullHeight;
+ const buffers = new WeakMap();
- if ( this.view === null ) {
+ function createBuffer( attribute, bufferType ) {
- this.view = {
- enabled: true,
- fullWidth: 1,
- fullHeight: 1,
- offsetX: 0,
- offsetY: 0,
- width: 1,
- height: 1
- };
+ const array = attribute.array;
+ const usage = attribute.usage;
- }
+ const buffer = gl.createBuffer();
- this.view.enabled = true;
- this.view.fullWidth = fullWidth;
- this.view.fullHeight = fullHeight;
- this.view.offsetX = x;
- this.view.offsetY = y;
- this.view.width = width;
- this.view.height = height;
+ gl.bindBuffer( bufferType, buffer );
+ gl.bufferData( bufferType, array, usage );
- this.updateProjectionMatrix();
+ attribute.onUploadCallback();
- },
+ let type;
- clearViewOffset: function () {
+ if ( array instanceof Float32Array ) {
- if ( this.view !== null ) {
+ type = gl.FLOAT;
- this.view.enabled = false;
+ } else if ( array instanceof Uint16Array ) {
- }
+ if ( attribute.isFloat16BufferAttribute ) {
- this.updateProjectionMatrix();
+ if ( isWebGL2 ) {
- },
+ type = gl.HALF_FLOAT;
- updateProjectionMatrix: function () {
+ } else {
- var near = this.near,
- top = near * Math.tan( _Math.DEG2RAD * 0.5 * this.fov ) / this.zoom,
- height = 2 * top,
- width = this.aspect * height,
- left = - 0.5 * width,
- view = this.view;
+ throw new Error( 'THREE.WebGLAttributes: Usage of Float16BufferAttribute requires WebGL2.' );
- if ( this.view !== null && this.view.enabled ) {
+ }
- var fullWidth = view.fullWidth,
- fullHeight = view.fullHeight;
+ } else {
- left += view.offsetX * width / fullWidth;
- top -= view.offsetY * height / fullHeight;
- width *= view.width / fullWidth;
- height *= view.height / fullHeight;
+ type = gl.UNSIGNED_SHORT;
}
- var skew = this.filmOffset;
- if ( skew !== 0 ) left += near * skew / this.getFilmWidth();
+ } else if ( array instanceof Int16Array ) {
- this.projectionMatrix.makePerspective( left, left + width, top, top - height, near, this.far );
+ type = gl.SHORT;
- this.projectionMatrixInverse.getInverse( this.projectionMatrix );
+ } else if ( array instanceof Uint32Array ) {
- },
+ type = gl.UNSIGNED_INT;
- toJSON: function ( meta ) {
+ } else if ( array instanceof Int32Array ) {
- var data = Object3D.prototype.toJSON.call( this, meta );
+ type = gl.INT;
- data.object.fov = this.fov;
- data.object.zoom = this.zoom;
+ } else if ( array instanceof Int8Array ) {
- data.object.near = this.near;
- data.object.far = this.far;
- data.object.focus = this.focus;
+ type = gl.BYTE;
- data.object.aspect = this.aspect;
+ } else if ( array instanceof Uint8Array ) {
- if ( this.view !== null ) data.object.view = Object.assign( {}, this.view );
+ type = gl.UNSIGNED_BYTE;
- data.object.filmGauge = this.filmGauge;
- data.object.filmOffset = this.filmOffset;
+ } else if ( array instanceof Uint8ClampedArray ) {
- return data;
+ type = gl.UNSIGNED_BYTE;
- }
+ } else {
- } );
+ throw new Error( 'THREE.WebGLAttributes: Unsupported buffer data format: ' + array );
- /**
- * Camera for rendering cube maps
- * - renders scene into axis-aligned cube
- *
- * @author alteredq / http://alteredqualia.com/
- */
+ }
- var fov = 90, aspect = 1;
+ return {
+ buffer: buffer,
+ type: type,
+ bytesPerElement: array.BYTES_PER_ELEMENT,
+ version: attribute.version
+ };
- function CubeCamera( near, far, cubeResolution, options ) {
+ }
- Object3D.call( this );
+ function updateBuffer( buffer, attribute, bufferType ) {
- this.type = 'CubeCamera';
+ const array = attribute.array;
+ const updateRange = attribute.updateRange;
- var cameraPX = new PerspectiveCamera( fov, aspect, near, far );
- cameraPX.up.set( 0, - 1, 0 );
- cameraPX.lookAt( new Vector3( 1, 0, 0 ) );
- this.add( cameraPX );
+ gl.bindBuffer( bufferType, buffer );
- var cameraNX = new PerspectiveCamera( fov, aspect, near, far );
- cameraNX.up.set( 0, - 1, 0 );
- cameraNX.lookAt( new Vector3( - 1, 0, 0 ) );
- this.add( cameraNX );
+ if ( updateRange.count === - 1 ) {
- var cameraPY = new PerspectiveCamera( fov, aspect, near, far );
- cameraPY.up.set( 0, 0, 1 );
- cameraPY.lookAt( new Vector3( 0, 1, 0 ) );
- this.add( cameraPY );
+ // Not using update ranges
- var cameraNY = new PerspectiveCamera( fov, aspect, near, far );
- cameraNY.up.set( 0, 0, - 1 );
- cameraNY.lookAt( new Vector3( 0, - 1, 0 ) );
- this.add( cameraNY );
+ gl.bufferSubData( bufferType, 0, array );
- var cameraPZ = new PerspectiveCamera( fov, aspect, near, far );
- cameraPZ.up.set( 0, - 1, 0 );
- cameraPZ.lookAt( new Vector3( 0, 0, 1 ) );
- this.add( cameraPZ );
+ } else {
- var cameraNZ = new PerspectiveCamera( fov, aspect, near, far );
- cameraNZ.up.set( 0, - 1, 0 );
- cameraNZ.lookAt( new Vector3( 0, 0, - 1 ) );
- this.add( cameraNZ );
+ if ( isWebGL2 ) {
- options = options || { format: RGBFormat, magFilter: LinearFilter, minFilter: LinearFilter };
+ gl.bufferSubData( bufferType, updateRange.offset * array.BYTES_PER_ELEMENT,
+ array, updateRange.offset, updateRange.count );
- this.renderTarget = new WebGLRenderTargetCube( cubeResolution, cubeResolution, options );
- this.renderTarget.texture.name = "CubeCamera";
+ } else {
- this.update = function ( renderer, scene ) {
+ gl.bufferSubData( bufferType, updateRange.offset * array.BYTES_PER_ELEMENT,
+ array.subarray( updateRange.offset, updateRange.offset + updateRange.count ) );
- if ( this.parent === null ) this.updateMatrixWorld();
+ }
- var currentRenderTarget = renderer.getRenderTarget();
+ updateRange.count = - 1; // reset range
- var renderTarget = this.renderTarget;
- var generateMipmaps = renderTarget.texture.generateMipmaps;
+ }
- renderTarget.texture.generateMipmaps = false;
+ attribute.onUploadCallback();
- renderer.setRenderTarget( renderTarget, 0 );
- renderer.render( scene, cameraPX );
+ }
- renderer.setRenderTarget( renderTarget, 1 );
- renderer.render( scene, cameraNX );
+ //
- renderer.setRenderTarget( renderTarget, 2 );
- renderer.render( scene, cameraPY );
+ function get( attribute ) {
- renderer.setRenderTarget( renderTarget, 3 );
- renderer.render( scene, cameraNY );
+ if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;
- renderer.setRenderTarget( renderTarget, 4 );
- renderer.render( scene, cameraPZ );
+ return buffers.get( attribute );
- renderTarget.texture.generateMipmaps = generateMipmaps;
+ }
- renderer.setRenderTarget( renderTarget, 5 );
- renderer.render( scene, cameraNZ );
+ function remove( attribute ) {
- renderer.setRenderTarget( currentRenderTarget );
+ if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;
- };
+ const data = buffers.get( attribute );
- this.clear = function ( renderer, color, depth, stencil ) {
+ if ( data ) {
- var currentRenderTarget = renderer.getRenderTarget();
+ gl.deleteBuffer( data.buffer );
- var renderTarget = this.renderTarget;
+ buffers.delete( attribute );
- for ( var i = 0; i < 6; i ++ ) {
+ }
- renderer.setRenderTarget( renderTarget, i );
+ }
- renderer.clear( color, depth, stencil );
+ function update( attribute, bufferType ) {
- }
+ if ( attribute.isGLBufferAttribute ) {
- renderer.setRenderTarget( currentRenderTarget );
+ const cached = buffers.get( attribute );
- };
+ if ( ! cached || cached.version < attribute.version ) {
- }
+ buffers.set( attribute, {
+ buffer: attribute.buffer,
+ type: attribute.type,
+ bytesPerElement: attribute.elementSize,
+ version: attribute.version
+ } );
- CubeCamera.prototype = Object.create( Object3D.prototype );
- CubeCamera.prototype.constructor = CubeCamera;
+ }
- /**
- * @author alteredq / http://alteredqualia.com
- * @author WestLangley / http://github.com/WestLangley
- */
+ return;
- function WebGLRenderTargetCube( width, height, options ) {
+ }
- WebGLRenderTarget.call( this, width, height, options );
+ if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;
- }
+ const data = buffers.get( attribute );
- WebGLRenderTargetCube.prototype = Object.create( WebGLRenderTarget.prototype );
- WebGLRenderTargetCube.prototype.constructor = WebGLRenderTargetCube;
+ if ( data === undefined ) {
- WebGLRenderTargetCube.prototype.isWebGLRenderTargetCube = true;
+ buffers.set( attribute, createBuffer( attribute, bufferType ) );
- WebGLRenderTargetCube.prototype.fromEquirectangularTexture = function ( renderer, texture ) {
+ } else if ( data.version < attribute.version ) {
- this.texture.type = texture.type;
- this.texture.format = texture.format;
- this.texture.encoding = texture.encoding;
+ updateBuffer( data.buffer, attribute, bufferType );
- var scene = new Scene();
+ data.version = attribute.version;
- var shader = {
+ }
- uniforms: {
- tEquirect: { value: null },
- },
+ }
- vertexShader: [
+ return {
- "varying vec3 vWorldDirection;",
+ get: get,
+ remove: remove,
+ update: update
- "vec3 transformDirection( in vec3 dir, in mat4 matrix ) {",
+ };
- " return normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );",
+}
- "}",
+class PlaneGeometry extends BufferGeometry {
- "void main() {",
+ constructor( width = 1, height = 1, widthSegments = 1, heightSegments = 1 ) {
- " vWorldDirection = transformDirection( position, modelMatrix );",
+ super();
- " #include ",
- " #include ",
+ this.type = 'PlaneGeometry';
- "}"
+ this.parameters = {
+ width: width,
+ height: height,
+ widthSegments: widthSegments,
+ heightSegments: heightSegments
+ };
- ].join( '\n' ),
+ const width_half = width / 2;
+ const height_half = height / 2;
- fragmentShader: [
+ const gridX = Math.floor( widthSegments );
+ const gridY = Math.floor( heightSegments );
- "uniform sampler2D tEquirect;",
+ const gridX1 = gridX + 1;
+ const gridY1 = gridY + 1;
- "varying vec3 vWorldDirection;",
+ const segment_width = width / gridX;
+ const segment_height = height / gridY;
- "#define RECIPROCAL_PI 0.31830988618",
- "#define RECIPROCAL_PI2 0.15915494",
+ //
- "void main() {",
+ const indices = [];
+ const vertices = [];
+ const normals = [];
+ const uvs = [];
- " vec3 direction = normalize( vWorldDirection );",
+ for ( let iy = 0; iy < gridY1; iy ++ ) {
- " vec2 sampleUV;",
+ const y = iy * segment_height - height_half;
- " sampleUV.y = asin( clamp( direction.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;",
+ for ( let ix = 0; ix < gridX1; ix ++ ) {
- " sampleUV.x = atan( direction.z, direction.x ) * RECIPROCAL_PI2 + 0.5;",
+ const x = ix * segment_width - width_half;
- " gl_FragColor = texture2D( tEquirect, sampleUV );",
+ vertices.push( x, - y, 0 );
- "}"
+ normals.push( 0, 0, 1 );
- ].join( '\n' ),
- };
+ uvs.push( ix / gridX );
+ uvs.push( 1 - ( iy / gridY ) );
- var material = new ShaderMaterial( {
+ }
- type: 'CubemapFromEquirect',
+ }
- uniforms: cloneUniforms( shader.uniforms ),
- vertexShader: shader.vertexShader,
- fragmentShader: shader.fragmentShader,
- side: BackSide,
- blending: NoBlending
+ for ( let iy = 0; iy < gridY; iy ++ ) {
- } );
+ for ( let ix = 0; ix < gridX; ix ++ ) {
- material.uniforms.tEquirect.value = texture;
+ const a = ix + gridX1 * iy;
+ const b = ix + gridX1 * ( iy + 1 );
+ const c = ( ix + 1 ) + gridX1 * ( iy + 1 );
+ const d = ( ix + 1 ) + gridX1 * iy;
- var mesh = new Mesh( new BoxBufferGeometry( 5, 5, 5 ), material );
+ indices.push( a, b, d );
+ indices.push( b, c, d );
- scene.add( mesh );
+ }
- var camera = new CubeCamera( 1, 10, 1 );
+ }
- camera.renderTarget = this;
- camera.renderTarget.texture.name = 'CubeCameraTexture';
+ this.setIndex( indices );
+ this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
+ this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
+ this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
- camera.update( renderer, scene );
+ }
- mesh.geometry.dispose();
- mesh.material.dispose();
+ copy( source ) {
+
+ super.copy( source );
+
+ this.parameters = Object.assign( {}, source.parameters );
return this;
- };
+ }
- /**
- * @author alteredq / http://alteredqualia.com/
- */
+ static fromJSON( data ) {
- function DataTexture( data, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding ) {
+ return new PlaneGeometry( data.width, data.height, data.widthSegments, data.heightSegments );
- Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding );
+ }
- this.image = { data: data, width: width, height: height };
+}
- this.magFilter = magFilter !== undefined ? magFilter : NearestFilter;
- this.minFilter = minFilter !== undefined ? minFilter : NearestFilter;
+var alphahash_fragment = "#ifdef USE_ALPHAHASH\n\tif ( diffuseColor.a < getAlphaHashThreshold( vPosition ) ) discard;\n#endif";
- this.generateMipmaps = false;
- this.flipY = false;
- this.unpackAlignment = 1;
+var alphahash_pars_fragment = "#ifdef USE_ALPHAHASH\n\tconst float ALPHA_HASH_SCALE = 0.05;\n\tfloat hash2D( vec2 value ) {\n\t\treturn fract( 1.0e4 * sin( 17.0 * value.x + 0.1 * value.y ) * ( 0.1 + abs( sin( 13.0 * value.y + value.x ) ) ) );\n\t}\n\tfloat hash3D( vec3 value ) {\n\t\treturn hash2D( vec2( hash2D( value.xy ), value.z ) );\n\t}\n\tfloat getAlphaHashThreshold( vec3 position ) {\n\t\tfloat maxDeriv = max(\n\t\t\tlength( dFdx( position.xyz ) ),\n\t\t\tlength( dFdy( position.xyz ) )\n\t\t);\n\t\tfloat pixScale = 1.0 / ( ALPHA_HASH_SCALE * maxDeriv );\n\t\tvec2 pixScales = vec2(\n\t\t\texp2( floor( log2( pixScale ) ) ),\n\t\t\texp2( ceil( log2( pixScale ) ) )\n\t\t);\n\t\tvec2 alpha = vec2(\n\t\t\thash3D( floor( pixScales.x * position.xyz ) ),\n\t\t\thash3D( floor( pixScales.y * position.xyz ) )\n\t\t);\n\t\tfloat lerpFactor = fract( log2( pixScale ) );\n\t\tfloat x = ( 1.0 - lerpFactor ) * alpha.x + lerpFactor * alpha.y;\n\t\tfloat a = min( lerpFactor, 1.0 - lerpFactor );\n\t\tvec3 cases = vec3(\n\t\t\tx * x / ( 2.0 * a * ( 1.0 - a ) ),\n\t\t\t( x - 0.5 * a ) / ( 1.0 - a ),\n\t\t\t1.0 - ( ( 1.0 - x ) * ( 1.0 - x ) / ( 2.0 * a * ( 1.0 - a ) ) )\n\t\t);\n\t\tfloat threshold = ( x < ( 1.0 - a ) )\n\t\t\t? ( ( x < a ) ? cases.x : cases.y )\n\t\t\t: cases.z;\n\t\treturn clamp( threshold , 1.0e-6, 1.0 );\n\t}\n#endif";
- }
+var alphamap_fragment = "#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, vAlphaMapUv ).g;\n#endif";
- DataTexture.prototype = Object.create( Texture.prototype );
- DataTexture.prototype.constructor = DataTexture;
+var alphamap_pars_fragment = "#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif";
- DataTexture.prototype.isDataTexture = true;
+var alphatest_fragment = "#ifdef USE_ALPHATEST\n\tif ( diffuseColor.a < alphaTest ) discard;\n#endif";
- /**
- * @author bhouston / http://clara.io
- */
+var alphatest_pars_fragment = "#ifdef USE_ALPHATEST\n\tuniform float alphaTest;\n#endif";
- var _vector1 = new Vector3();
- var _vector2 = new Vector3();
- var _normalMatrix = new Matrix3();
+var aomap_fragment = "#ifdef USE_AOMAP\n\tfloat ambientOcclusion = ( texture2D( aoMap, vAoMapUv ).r - 1.0 ) * aoMapIntensity + 1.0;\n\treflectedLight.indirectDiffuse *= ambientOcclusion;\n\t#if defined( USE_ENVMAP ) && defined( STANDARD )\n\t\tfloat dotNV = saturate( dot( geometryNormal, geometryViewDir ) );\n\t\treflectedLight.indirectSpecular *= computeSpecularOcclusion( dotNV, ambientOcclusion, material.roughness );\n\t#endif\n#endif";
- function Plane( normal, constant ) {
+var aomap_pars_fragment = "#ifdef USE_AOMAP\n\tuniform sampler2D aoMap;\n\tuniform float aoMapIntensity;\n#endif";
- // normal is assumed to be normalized
+var begin_vertex = "vec3 transformed = vec3( position );\n#ifdef USE_ALPHAHASH\n\tvPosition = vec3( position );\n#endif";
- this.normal = ( normal !== undefined ) ? normal : new Vector3( 1, 0, 0 );
- this.constant = ( constant !== undefined ) ? constant : 0;
+var beginnormal_vertex = "vec3 objectNormal = vec3( normal );\n#ifdef USE_TANGENT\n\tvec3 objectTangent = vec3( tangent.xyz );\n#endif";
- }
+var bsdfs = "float G_BlinnPhong_Implicit( ) {\n\treturn 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n\treturn RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n}\nvec3 BRDF_BlinnPhong( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in vec3 specularColor, const in float shininess ) {\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, 1.0, dotVH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n} // validated";
- Object.assign( Plane.prototype, {
+var iridescence_fragment = "#ifdef USE_IRIDESCENCE\n\tconst mat3 XYZ_TO_REC709 = mat3(\n\t\t 3.2404542, -0.9692660, 0.0556434,\n\t\t-1.5371385, 1.8760108, -0.2040259,\n\t\t-0.4985314, 0.0415560, 1.0572252\n\t);\n\tvec3 Fresnel0ToIor( vec3 fresnel0 ) {\n\t\tvec3 sqrtF0 = sqrt( fresnel0 );\n\t\treturn ( vec3( 1.0 ) + sqrtF0 ) / ( vec3( 1.0 ) - sqrtF0 );\n\t}\n\tvec3 IorToFresnel0( vec3 transmittedIor, float incidentIor ) {\n\t\treturn pow2( ( transmittedIor - vec3( incidentIor ) ) / ( transmittedIor + vec3( incidentIor ) ) );\n\t}\n\tfloat IorToFresnel0( float transmittedIor, float incidentIor ) {\n\t\treturn pow2( ( transmittedIor - incidentIor ) / ( transmittedIor + incidentIor ));\n\t}\n\tvec3 evalSensitivity( float OPD, vec3 shift ) {\n\t\tfloat phase = 2.0 * PI * OPD * 1.0e-9;\n\t\tvec3 val = vec3( 5.4856e-13, 4.4201e-13, 5.2481e-13 );\n\t\tvec3 pos = vec3( 1.6810e+06, 1.7953e+06, 2.2084e+06 );\n\t\tvec3 var = vec3( 4.3278e+09, 9.3046e+09, 6.6121e+09 );\n\t\tvec3 xyz = val * sqrt( 2.0 * PI * var ) * cos( pos * phase + shift ) * exp( - pow2( phase ) * var );\n\t\txyz.x += 9.7470e-14 * sqrt( 2.0 * PI * 4.5282e+09 ) * cos( 2.2399e+06 * phase + shift[ 0 ] ) * exp( - 4.5282e+09 * pow2( phase ) );\n\t\txyz /= 1.0685e-7;\n\t\tvec3 rgb = XYZ_TO_REC709 * xyz;\n\t\treturn rgb;\n\t}\n\tvec3 evalIridescence( float outsideIOR, float eta2, float cosTheta1, float thinFilmThickness, vec3 baseF0 ) {\n\t\tvec3 I;\n\t\tfloat iridescenceIOR = mix( outsideIOR, eta2, smoothstep( 0.0, 0.03, thinFilmThickness ) );\n\t\tfloat sinTheta2Sq = pow2( outsideIOR / iridescenceIOR ) * ( 1.0 - pow2( cosTheta1 ) );\n\t\tfloat cosTheta2Sq = 1.0 - sinTheta2Sq;\n\t\tif ( cosTheta2Sq < 0.0 ) {\n\t\t\treturn vec3( 1.0 );\n\t\t}\n\t\tfloat cosTheta2 = sqrt( cosTheta2Sq );\n\t\tfloat R0 = IorToFresnel0( iridescenceIOR, outsideIOR );\n\t\tfloat R12 = F_Schlick( R0, 1.0, cosTheta1 );\n\t\tfloat T121 = 1.0 - R12;\n\t\tfloat phi12 = 0.0;\n\t\tif ( iridescenceIOR < outsideIOR ) phi12 = PI;\n\t\tfloat phi21 = PI - phi12;\n\t\tvec3 baseIOR = Fresnel0ToIor( clamp( baseF0, 0.0, 0.9999 ) );\t\tvec3 R1 = IorToFresnel0( baseIOR, iridescenceIOR );\n\t\tvec3 R23 = F_Schlick( R1, 1.0, cosTheta2 );\n\t\tvec3 phi23 = vec3( 0.0 );\n\t\tif ( baseIOR[ 0 ] < iridescenceIOR ) phi23[ 0 ] = PI;\n\t\tif ( baseIOR[ 1 ] < iridescenceIOR ) phi23[ 1 ] = PI;\n\t\tif ( baseIOR[ 2 ] < iridescenceIOR ) phi23[ 2 ] = PI;\n\t\tfloat OPD = 2.0 * iridescenceIOR * thinFilmThickness * cosTheta2;\n\t\tvec3 phi = vec3( phi21 ) + phi23;\n\t\tvec3 R123 = clamp( R12 * R23, 1e-5, 0.9999 );\n\t\tvec3 r123 = sqrt( R123 );\n\t\tvec3 Rs = pow2( T121 ) * R23 / ( vec3( 1.0 ) - R123 );\n\t\tvec3 C0 = R12 + Rs;\n\t\tI = C0;\n\t\tvec3 Cm = Rs - T121;\n\t\tfor ( int m = 1; m <= 2; ++ m ) {\n\t\t\tCm *= r123;\n\t\t\tvec3 Sm = 2.0 * evalSensitivity( float( m ) * OPD, float( m ) * phi );\n\t\t\tI += Cm * Sm;\n\t\t}\n\t\treturn max( I, vec3( 0.0 ) );\n\t}\n#endif";
- isPlane: true,
+var bumpmap_pars_fragment = "#ifdef USE_BUMPMAP\n\tuniform sampler2D bumpMap;\n\tuniform float bumpScale;\n\tvec2 dHdxy_fwd() {\n\t\tvec2 dSTdx = dFdx( vBumpMapUv );\n\t\tvec2 dSTdy = dFdy( vBumpMapUv );\n\t\tfloat Hll = bumpScale * texture2D( bumpMap, vBumpMapUv ).x;\n\t\tfloat dBx = bumpScale * texture2D( bumpMap, vBumpMapUv + dSTdx ).x - Hll;\n\t\tfloat dBy = bumpScale * texture2D( bumpMap, vBumpMapUv + dSTdy ).x - Hll;\n\t\treturn vec2( dBx, dBy );\n\t}\n\tvec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy, float faceDirection ) {\n\t\tvec3 vSigmaX = dFdx( surf_pos.xyz );\n\t\tvec3 vSigmaY = dFdy( surf_pos.xyz );\n\t\tvec3 vN = surf_norm;\n\t\tvec3 R1 = cross( vSigmaY, vN );\n\t\tvec3 R2 = cross( vN, vSigmaX );\n\t\tfloat fDet = dot( vSigmaX, R1 ) * faceDirection;\n\t\tvec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n\t\treturn normalize( abs( fDet ) * surf_norm - vGrad );\n\t}\n#endif";
- set: function ( normal, constant ) {
+var clipping_planes_fragment = "#if NUM_CLIPPING_PLANES > 0\n\tvec4 plane;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n\t\tplane = clippingPlanes[ i ];\n\t\tif ( dot( vClipPosition, plane.xyz ) > plane.w ) discard;\n\t}\n\t#pragma unroll_loop_end\n\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\tbool clipped = true;\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n\t\t\tplane = clippingPlanes[ i ];\n\t\t\tclipped = ( dot( vClipPosition, plane.xyz ) > plane.w ) && clipped;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t\tif ( clipped ) discard;\n\t#endif\n#endif";
- this.normal.copy( normal );
- this.constant = constant;
+var clipping_planes_pars_fragment = "#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif";
- return this;
+var clipping_planes_pars_vertex = "#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n#endif";
- },
+var clipping_planes_vertex = "#if NUM_CLIPPING_PLANES > 0\n\tvClipPosition = - mvPosition.xyz;\n#endif";
- setComponents: function ( x, y, z, w ) {
+var color_fragment = "#if defined( USE_COLOR_ALPHA )\n\tdiffuseColor *= vColor;\n#elif defined( USE_COLOR )\n\tdiffuseColor.rgb *= vColor;\n#endif";
- this.normal.set( x, y, z );
- this.constant = w;
+var color_pars_fragment = "#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR )\n\tvarying vec3 vColor;\n#endif";
- return this;
+var color_pars_vertex = "#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )\n\tvarying vec3 vColor;\n#endif";
- },
+var color_vertex = "#if defined( USE_COLOR_ALPHA )\n\tvColor = vec4( 1.0 );\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )\n\tvColor = vec3( 1.0 );\n#endif\n#ifdef USE_COLOR\n\tvColor *= color;\n#endif\n#ifdef USE_INSTANCING_COLOR\n\tvColor.xyz *= instanceColor.xyz;\n#endif";
- setFromNormalAndCoplanarPoint: function ( normal, point ) {
+var common = "#define PI 3.141592653589793\n#define PI2 6.283185307179586\n#define PI_HALF 1.5707963267948966\n#define RECIPROCAL_PI 0.3183098861837907\n#define RECIPROCAL_PI2 0.15915494309189535\n#define EPSILON 1e-6\n#ifndef saturate\n#define saturate( a ) clamp( a, 0.0, 1.0 )\n#endif\n#define whiteComplement( a ) ( 1.0 - saturate( a ) )\nfloat pow2( const in float x ) { return x*x; }\nvec3 pow2( const in vec3 x ) { return x*x; }\nfloat pow3( const in float x ) { return x*x*x; }\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\nfloat max3( const in vec3 v ) { return max( max( v.x, v.y ), v.z ); }\nfloat average( const in vec3 v ) { return dot( v, vec3( 0.3333333 ) ); }\nhighp float rand( const in vec2 uv ) {\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract( sin( sn ) * c );\n}\n#ifdef HIGH_PRECISION\n\tfloat precisionSafeLength( vec3 v ) { return length( v ); }\n#else\n\tfloat precisionSafeLength( vec3 v ) {\n\t\tfloat maxComponent = max3( abs( v ) );\n\t\treturn length( v / maxComponent ) * maxComponent;\n\t}\n#endif\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\n#ifdef USE_ALPHAHASH\n\tvarying vec3 vPosition;\n#endif\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nfloat luminance( const in vec3 rgb ) {\n\tconst vec3 weights = vec3( 0.2126729, 0.7151522, 0.0721750 );\n\treturn dot( weights, rgb );\n}\nbool isPerspectiveMatrix( mat4 m ) {\n\treturn m[ 2 ][ 3 ] == - 1.0;\n}\nvec2 equirectUv( in vec3 dir ) {\n\tfloat u = atan( dir.z, dir.x ) * RECIPROCAL_PI2 + 0.5;\n\tfloat v = asin( clamp( dir.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\treturn vec2( u, v );\n}\nvec3 BRDF_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 f0, const in float f90, const in float dotVH ) {\n\tfloat fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n\treturn f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n}\nfloat F_Schlick( const in float f0, const in float f90, const in float dotVH ) {\n\tfloat fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n\treturn f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n} // validated";
- this.normal.copy( normal );
- this.constant = - point.dot( this.normal );
+var cube_uv_reflection_fragment = "#ifdef ENVMAP_TYPE_CUBE_UV\n\t#define cubeUV_minMipLevel 4.0\n\t#define cubeUV_minTileSize 16.0\n\tfloat getFace( vec3 direction ) {\n\t\tvec3 absDirection = abs( direction );\n\t\tfloat face = - 1.0;\n\t\tif ( absDirection.x > absDirection.z ) {\n\t\t\tif ( absDirection.x > absDirection.y )\n\t\t\t\tface = direction.x > 0.0 ? 0.0 : 3.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t} else {\n\t\t\tif ( absDirection.z > absDirection.y )\n\t\t\t\tface = direction.z > 0.0 ? 2.0 : 5.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t}\n\t\treturn face;\n\t}\n\tvec2 getUV( vec3 direction, float face ) {\n\t\tvec2 uv;\n\t\tif ( face == 0.0 ) {\n\t\t\tuv = vec2( direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 1.0 ) {\n\t\t\tuv = vec2( - direction.x, - direction.z ) / abs( direction.y );\n\t\t} else if ( face == 2.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.y ) / abs( direction.z );\n\t\t} else if ( face == 3.0 ) {\n\t\t\tuv = vec2( - direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 4.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.z ) / abs( direction.y );\n\t\t} else {\n\t\t\tuv = vec2( direction.x, direction.y ) / abs( direction.z );\n\t\t}\n\t\treturn 0.5 * ( uv + 1.0 );\n\t}\n\tvec3 bilinearCubeUV( sampler2D envMap, vec3 direction, float mipInt ) {\n\t\tfloat face = getFace( direction );\n\t\tfloat filterInt = max( cubeUV_minMipLevel - mipInt, 0.0 );\n\t\tmipInt = max( mipInt, cubeUV_minMipLevel );\n\t\tfloat faceSize = exp2( mipInt );\n\t\thighp vec2 uv = getUV( direction, face ) * ( faceSize - 2.0 ) + 1.0;\n\t\tif ( face > 2.0 ) {\n\t\t\tuv.y += faceSize;\n\t\t\tface -= 3.0;\n\t\t}\n\t\tuv.x += face * faceSize;\n\t\tuv.x += filterInt * 3.0 * cubeUV_minTileSize;\n\t\tuv.y += 4.0 * ( exp2( CUBEUV_MAX_MIP ) - faceSize );\n\t\tuv.x *= CUBEUV_TEXEL_WIDTH;\n\t\tuv.y *= CUBEUV_TEXEL_HEIGHT;\n\t\t#ifdef texture2DGradEXT\n\t\t\treturn texture2DGradEXT( envMap, uv, vec2( 0.0 ), vec2( 0.0 ) ).rgb;\n\t\t#else\n\t\t\treturn texture2D( envMap, uv ).rgb;\n\t\t#endif\n\t}\n\t#define cubeUV_r0 1.0\n\t#define cubeUV_v0 0.339\n\t#define cubeUV_m0 - 2.0\n\t#define cubeUV_r1 0.8\n\t#define cubeUV_v1 0.276\n\t#define cubeUV_m1 - 1.0\n\t#define cubeUV_r4 0.4\n\t#define cubeUV_v4 0.046\n\t#define cubeUV_m4 2.0\n\t#define cubeUV_r5 0.305\n\t#define cubeUV_v5 0.016\n\t#define cubeUV_m5 3.0\n\t#define cubeUV_r6 0.21\n\t#define cubeUV_v6 0.0038\n\t#define cubeUV_m6 4.0\n\tfloat roughnessToMip( float roughness ) {\n\t\tfloat mip = 0.0;\n\t\tif ( roughness >= cubeUV_r1 ) {\n\t\t\tmip = ( cubeUV_r0 - roughness ) * ( cubeUV_m1 - cubeUV_m0 ) / ( cubeUV_r0 - cubeUV_r1 ) + cubeUV_m0;\n\t\t} else if ( roughness >= cubeUV_r4 ) {\n\t\t\tmip = ( cubeUV_r1 - roughness ) * ( cubeUV_m4 - cubeUV_m1 ) / ( cubeUV_r1 - cubeUV_r4 ) + cubeUV_m1;\n\t\t} else if ( roughness >= cubeUV_r5 ) {\n\t\t\tmip = ( cubeUV_r4 - roughness ) * ( cubeUV_m5 - cubeUV_m4 ) / ( cubeUV_r4 - cubeUV_r5 ) + cubeUV_m4;\n\t\t} else if ( roughness >= cubeUV_r6 ) {\n\t\t\tmip = ( cubeUV_r5 - roughness ) * ( cubeUV_m6 - cubeUV_m5 ) / ( cubeUV_r5 - cubeUV_r6 ) + cubeUV_m5;\n\t\t} else {\n\t\t\tmip = - 2.0 * log2( 1.16 * roughness );\t\t}\n\t\treturn mip;\n\t}\n\tvec4 textureCubeUV( sampler2D envMap, vec3 sampleDir, float roughness ) {\n\t\tfloat mip = clamp( roughnessToMip( roughness ), cubeUV_m0, CUBEUV_MAX_MIP );\n\t\tfloat mipF = fract( mip );\n\t\tfloat mipInt = floor( mip );\n\t\tvec3 color0 = bilinearCubeUV( envMap, sampleDir, mipInt );\n\t\tif ( mipF == 0.0 ) {\n\t\t\treturn vec4( color0, 1.0 );\n\t\t} else {\n\t\t\tvec3 color1 = bilinearCubeUV( envMap, sampleDir, mipInt + 1.0 );\n\t\t\treturn vec4( mix( color0, color1, mipF ), 1.0 );\n\t\t}\n\t}\n#endif";
- return this;
+var defaultnormal_vertex = "vec3 transformedNormal = objectNormal;\n#ifdef USE_INSTANCING\n\tmat3 m = mat3( instanceMatrix );\n\ttransformedNormal /= vec3( dot( m[ 0 ], m[ 0 ] ), dot( m[ 1 ], m[ 1 ] ), dot( m[ 2 ], m[ 2 ] ) );\n\ttransformedNormal = m * transformedNormal;\n#endif\ntransformedNormal = normalMatrix * transformedNormal;\n#ifdef FLIP_SIDED\n\ttransformedNormal = - transformedNormal;\n#endif\n#ifdef USE_TANGENT\n\tvec3 transformedTangent = ( modelViewMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n\t#ifdef FLIP_SIDED\n\t\ttransformedTangent = - transformedTangent;\n\t#endif\n#endif";
- },
+var displacementmap_pars_vertex = "#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif";
- setFromCoplanarPoints: function ( a, b, c ) {
+var displacementmap_vertex = "#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, vDisplacementMapUv ).x * displacementScale + displacementBias );\n#endif";
- var normal = _vector1.subVectors( c, b ).cross( _vector2.subVectors( a, b ) ).normalize();
+var emissivemap_fragment = "#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vEmissiveMapUv );\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif";
- // Q: should an error be thrown if normal is zero (e.g. degenerate plane)?
+var emissivemap_pars_fragment = "#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif";
- this.setFromNormalAndCoplanarPoint( normal, a );
+var colorspace_fragment = "gl_FragColor = linearToOutputTexel( gl_FragColor );";
- return this;
+var colorspace_pars_fragment = "\nconst mat3 LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 = mat3(\n\tvec3( 0.8224621, 0.177538, 0.0 ),\n\tvec3( 0.0331941, 0.9668058, 0.0 ),\n\tvec3( 0.0170827, 0.0723974, 0.9105199 )\n);\nconst mat3 LINEAR_DISPLAY_P3_TO_LINEAR_SRGB = mat3(\n\tvec3( 1.2249401, - 0.2249404, 0.0 ),\n\tvec3( - 0.0420569, 1.0420571, 0.0 ),\n\tvec3( - 0.0196376, - 0.0786361, 1.0982735 )\n);\nvec4 LinearSRGBToLinearDisplayP3( in vec4 value ) {\n\treturn vec4( value.rgb * LINEAR_SRGB_TO_LINEAR_DISPLAY_P3, value.a );\n}\nvec4 LinearDisplayP3ToLinearSRGB( in vec4 value ) {\n\treturn vec4( value.rgb * LINEAR_DISPLAY_P3_TO_LINEAR_SRGB, value.a );\n}\nvec4 LinearTransferOETF( in vec4 value ) {\n\treturn value;\n}\nvec4 sRGBTransferOETF( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.a );\n}\nvec4 LinearToLinear( in vec4 value ) {\n\treturn value;\n}\nvec4 LinearTosRGB( in vec4 value ) {\n\treturn sRGBTransferOETF( value );\n}";
- },
+var envmap_fragment = "#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvec3 cameraToFrag;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToFrag = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToFrag = normalize( vWorldPosition - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToFrag, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToFrag, worldNormal, refractionRatio );\n\t\t#endif\n\t#else\n\t\tvec3 reflectVec = vReflect;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 envColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\t#else\n\t\tvec4 envColor = vec4( 0.0 );\n\t#endif\n\t#ifdef ENVMAP_BLENDING_MULTIPLY\n\t\toutgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_MIX )\n\t\toutgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_ADD )\n\t\toutgoingLight += envColor.xyz * specularStrength * reflectivity;\n\t#endif\n#endif";
- clone: function () {
+var envmap_common_pars_fragment = "#ifdef USE_ENVMAP\n\tuniform float envMapIntensity;\n\tuniform float flipEnvMap;\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tuniform samplerCube envMap;\n\t#else\n\t\tuniform sampler2D envMap;\n\t#endif\n\t\n#endif";
- return new this.constructor().copy( this );
+var envmap_pars_fragment = "#ifdef USE_ENVMAP\n\tuniform float reflectivity;\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( LAMBERT )\n\t\t#define ENV_WORLDPOS\n\t#endif\n\t#ifdef ENV_WORLDPOS\n\t\tvarying vec3 vWorldPosition;\n\t\tuniform float refractionRatio;\n\t#else\n\t\tvarying vec3 vReflect;\n\t#endif\n#endif";
- },
+var envmap_pars_vertex = "#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( LAMBERT )\n\t\t#define ENV_WORLDPOS\n\t#endif\n\t#ifdef ENV_WORLDPOS\n\t\t\n\t\tvarying vec3 vWorldPosition;\n\t#else\n\t\tvarying vec3 vReflect;\n\t\tuniform float refractionRatio;\n\t#endif\n#endif";
- copy: function ( plane ) {
+var envmap_vertex = "#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvWorldPosition = worldPosition.xyz;\n\t#else\n\t\tvec3 cameraToVertex;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToVertex = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToVertex = normalize( worldPosition.xyz - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvReflect = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#endif\n#endif";
- this.normal.copy( plane.normal );
- this.constant = plane.constant;
+var fog_vertex = "#ifdef USE_FOG\n\tvFogDepth = - mvPosition.z;\n#endif";
- return this;
+var fog_pars_vertex = "#ifdef USE_FOG\n\tvarying float vFogDepth;\n#endif";
- },
+var fog_fragment = "#ifdef USE_FOG\n\t#ifdef FOG_EXP2\n\t\tfloat fogFactor = 1.0 - exp( - fogDensity * fogDensity * vFogDepth * vFogDepth );\n\t#else\n\t\tfloat fogFactor = smoothstep( fogNear, fogFar, vFogDepth );\n\t#endif\n\tgl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n#endif";
- normalize: function () {
+var fog_pars_fragment = "#ifdef USE_FOG\n\tuniform vec3 fogColor;\n\tvarying float vFogDepth;\n\t#ifdef FOG_EXP2\n\t\tuniform float fogDensity;\n\t#else\n\t\tuniform float fogNear;\n\t\tuniform float fogFar;\n\t#endif\n#endif";
- // Note: will lead to a divide by zero if the plane is invalid.
+var gradientmap_pars_fragment = "#ifdef USE_GRADIENTMAP\n\tuniform sampler2D gradientMap;\n#endif\nvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\n\tfloat dotNL = dot( normal, lightDirection );\n\tvec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\n\t#ifdef USE_GRADIENTMAP\n\t\treturn vec3( texture2D( gradientMap, coord ).r );\n\t#else\n\t\tvec2 fw = fwidth( coord ) * 0.5;\n\t\treturn mix( vec3( 0.7 ), vec3( 1.0 ), smoothstep( 0.7 - fw.x, 0.7 + fw.x, coord.x ) );\n\t#endif\n}";
- var inverseNormalLength = 1.0 / this.normal.length();
- this.normal.multiplyScalar( inverseNormalLength );
- this.constant *= inverseNormalLength;
+var lightmap_fragment = "#ifdef USE_LIGHTMAP\n\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\n\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\treflectedLight.indirectDiffuse += lightMapIrradiance;\n#endif";
- return this;
+var lightmap_pars_fragment = "#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif";
- },
+var lights_lambert_fragment = "LambertMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularStrength = specularStrength;";
- negate: function () {
+var lights_lambert_pars_fragment = "varying vec3 vViewPosition;\nstruct LambertMaterial {\n\tvec3 diffuseColor;\n\tfloat specularStrength;\n};\nvoid RE_Direct_Lambert( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in LambertMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometryNormal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Lambert( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in LambertMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_Lambert\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Lambert";
- this.constant *= - 1;
- this.normal.negate();
+var lights_pars_begin = "uniform bool receiveShadow;\nuniform vec3 ambientLightColor;\n#if defined( USE_LIGHT_PROBES )\n\tuniform vec3 lightProbe[ 9 ];\n#endif\nvec3 shGetIrradianceAt( in vec3 normal, in vec3 shCoefficients[ 9 ] ) {\n\tfloat x = normal.x, y = normal.y, z = normal.z;\n\tvec3 result = shCoefficients[ 0 ] * 0.886227;\n\tresult += shCoefficients[ 1 ] * 2.0 * 0.511664 * y;\n\tresult += shCoefficients[ 2 ] * 2.0 * 0.511664 * z;\n\tresult += shCoefficients[ 3 ] * 2.0 * 0.511664 * x;\n\tresult += shCoefficients[ 4 ] * 2.0 * 0.429043 * x * y;\n\tresult += shCoefficients[ 5 ] * 2.0 * 0.429043 * y * z;\n\tresult += shCoefficients[ 6 ] * ( 0.743125 * z * z - 0.247708 );\n\tresult += shCoefficients[ 7 ] * 2.0 * 0.429043 * x * z;\n\tresult += shCoefficients[ 8 ] * 0.429043 * ( x * x - y * y );\n\treturn result;\n}\nvec3 getLightProbeIrradiance( const in vec3 lightProbe[ 9 ], const in vec3 normal ) {\n\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\tvec3 irradiance = shGetIrradianceAt( worldNormal, lightProbe );\n\treturn irradiance;\n}\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\treturn irradiance;\n}\nfloat getDistanceAttenuation( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\t#if defined ( LEGACY_LIGHTS )\n\t\tif ( cutoffDistance > 0.0 && decayExponent > 0.0 ) {\n\t\t\treturn pow( saturate( - lightDistance / cutoffDistance + 1.0 ), decayExponent );\n\t\t}\n\t\treturn 1.0;\n\t#else\n\t\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\t\tif ( cutoffDistance > 0.0 ) {\n\t\t\tdistanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t\t}\n\t\treturn distanceFalloff;\n\t#endif\n}\nfloat getSpotAttenuation( const in float coneCosine, const in float penumbraCosine, const in float angleCosine ) {\n\treturn smoothstep( coneCosine, penumbraCosine, angleCosine );\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalLightInfo( const in DirectionalLight directionalLight, out IncidentLight light ) {\n\t\tlight.color = directionalLight.color;\n\t\tlight.direction = directionalLight.direction;\n\t\tlight.visible = true;\n\t}\n#endif\n#if NUM_POINT_LIGHTS > 0\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointLightInfo( const in PointLight pointLight, const in vec3 geometryPosition, out IncidentLight light ) {\n\t\tvec3 lVector = pointLight.position - geometryPosition;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tlight.color = pointLight.color;\n\t\tlight.color *= getDistanceAttenuation( lightDistance, pointLight.distance, pointLight.decay );\n\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tstruct SpotLight {\n\t\tvec3 position;\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tfloat coneCos;\n\t\tfloat penumbraCos;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\tvoid getSpotLightInfo( const in SpotLight spotLight, const in vec3 geometryPosition, out IncidentLight light ) {\n\t\tvec3 lVector = spotLight.position - geometryPosition;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat angleCos = dot( light.direction, spotLight.direction );\n\t\tfloat spotAttenuation = getSpotAttenuation( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\tif ( spotAttenuation > 0.0 ) {\n\t\t\tfloat lightDistance = length( lVector );\n\t\t\tlight.color = spotLight.color * spotAttenuation;\n\t\t\tlight.color *= getDistanceAttenuation( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t\t} else {\n\t\t\tlight.color = vec3( 0.0 );\n\t\t\tlight.visible = false;\n\t\t}\n\t}\n#endif\n#if NUM_RECT_AREA_LIGHTS > 0\n\tstruct RectAreaLight {\n\t\tvec3 color;\n\t\tvec3 position;\n\t\tvec3 halfWidth;\n\t\tvec3 halfHeight;\n\t};\n\tuniform sampler2D ltc_1;\tuniform sampler2D ltc_2;\n\tuniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tstruct HemisphereLight {\n\t\tvec3 direction;\n\t\tvec3 skyColor;\n\t\tvec3 groundColor;\n\t};\n\tuniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n\tvec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in vec3 normal ) {\n\t\tfloat dotNL = dot( normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\treturn irradiance;\n\t}\n#endif";
- return this;
+var envmap_physical_pars_fragment = "#ifdef USE_ENVMAP\n\tvec3 getIBLIrradiance( const in vec3 normal ) {\n\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, worldNormal, 1.0 );\n\t\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n\tvec3 getIBLRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness ) {\n\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\tvec3 reflectVec = reflect( - viewDir, normal );\n\t\t\treflectVec = normalize( mix( reflectVec, normal, roughness * roughness) );\n\t\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, reflectVec, roughness );\n\t\t\treturn envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n\t#ifdef USE_ANISOTROPY\n\t\tvec3 getIBLAnisotropyRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness, const in vec3 bitangent, const in float anisotropy ) {\n\t\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\t\tvec3 bentNormal = cross( bitangent, viewDir );\n\t\t\t\tbentNormal = normalize( cross( bentNormal, bitangent ) );\n\t\t\t\tbentNormal = normalize( mix( bentNormal, normal, pow2( pow2( 1.0 - anisotropy * ( 1.0 - roughness ) ) ) ) );\n\t\t\t\treturn getIBLRadiance( viewDir, bentNormal, roughness );\n\t\t\t#else\n\t\t\t\treturn vec3( 0.0 );\n\t\t\t#endif\n\t\t}\n\t#endif\n#endif";
- },
+var lights_toon_fragment = "ToonMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;";
- distanceToPoint: function ( point ) {
+var lights_toon_pars_fragment = "varying vec3 vViewPosition;\nstruct ToonMaterial {\n\tvec3 diffuseColor;\n};\nvoid RE_Direct_Toon( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\tvec3 irradiance = getGradientIrradiance( geometryNormal, directLight.direction ) * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Toon( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_Toon\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Toon";
- return this.normal.dot( point ) + this.constant;
+var lights_phong_fragment = "BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;";
- },
+var lights_phong_pars_fragment = "varying vec3 vViewPosition;\nstruct BlinnPhongMaterial {\n\tvec3 diffuseColor;\n\tvec3 specularColor;\n\tfloat specularShininess;\n\tfloat specularStrength;\n};\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometryNormal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_BlinnPhong( directLight.direction, geometryViewDir, geometryNormal, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_BlinnPhong\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_BlinnPhong";
- distanceToSphere: function ( sphere ) {
+var lights_physical_fragment = "PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nvec3 dxy = max( abs( dFdx( nonPerturbedNormal ) ), abs( dFdy( nonPerturbedNormal ) ) );\nfloat geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z );\nmaterial.roughness = max( roughnessFactor, 0.0525 );material.roughness += geometryRoughness;\nmaterial.roughness = min( material.roughness, 1.0 );\n#ifdef IOR\n\tmaterial.ior = ior;\n\t#ifdef USE_SPECULAR\n\t\tfloat specularIntensityFactor = specularIntensity;\n\t\tvec3 specularColorFactor = specularColor;\n\t\t#ifdef USE_SPECULAR_COLORMAP\n\t\t\tspecularColorFactor *= texture2D( specularColorMap, vSpecularColorMapUv ).rgb;\n\t\t#endif\n\t\t#ifdef USE_SPECULAR_INTENSITYMAP\n\t\t\tspecularIntensityFactor *= texture2D( specularIntensityMap, vSpecularIntensityMapUv ).a;\n\t\t#endif\n\t\tmaterial.specularF90 = mix( specularIntensityFactor, 1.0, metalnessFactor );\n\t#else\n\t\tfloat specularIntensityFactor = 1.0;\n\t\tvec3 specularColorFactor = vec3( 1.0 );\n\t\tmaterial.specularF90 = 1.0;\n\t#endif\n\tmaterial.specularColor = mix( min( pow2( ( material.ior - 1.0 ) / ( material.ior + 1.0 ) ) * specularColorFactor, vec3( 1.0 ) ) * specularIntensityFactor, diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( 0.04 ), diffuseColor.rgb, metalnessFactor );\n\tmaterial.specularF90 = 1.0;\n#endif\n#ifdef USE_CLEARCOAT\n\tmaterial.clearcoat = clearcoat;\n\tmaterial.clearcoatRoughness = clearcoatRoughness;\n\tmaterial.clearcoatF0 = vec3( 0.04 );\n\tmaterial.clearcoatF90 = 1.0;\n\t#ifdef USE_CLEARCOATMAP\n\t\tmaterial.clearcoat *= texture2D( clearcoatMap, vClearcoatMapUv ).x;\n\t#endif\n\t#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\t\tmaterial.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vClearcoatRoughnessMapUv ).y;\n\t#endif\n\tmaterial.clearcoat = saturate( material.clearcoat );\tmaterial.clearcoatRoughness = max( material.clearcoatRoughness, 0.0525 );\n\tmaterial.clearcoatRoughness += geometryRoughness;\n\tmaterial.clearcoatRoughness = min( material.clearcoatRoughness, 1.0 );\n#endif\n#ifdef USE_IRIDESCENCE\n\tmaterial.iridescence = iridescence;\n\tmaterial.iridescenceIOR = iridescenceIOR;\n\t#ifdef USE_IRIDESCENCEMAP\n\t\tmaterial.iridescence *= texture2D( iridescenceMap, vIridescenceMapUv ).r;\n\t#endif\n\t#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\t\tmaterial.iridescenceThickness = (iridescenceThicknessMaximum - iridescenceThicknessMinimum) * texture2D( iridescenceThicknessMap, vIridescenceThicknessMapUv ).g + iridescenceThicknessMinimum;\n\t#else\n\t\tmaterial.iridescenceThickness = iridescenceThicknessMaximum;\n\t#endif\n#endif\n#ifdef USE_SHEEN\n\tmaterial.sheenColor = sheenColor;\n\t#ifdef USE_SHEEN_COLORMAP\n\t\tmaterial.sheenColor *= texture2D( sheenColorMap, vSheenColorMapUv ).rgb;\n\t#endif\n\tmaterial.sheenRoughness = clamp( sheenRoughness, 0.07, 1.0 );\n\t#ifdef USE_SHEEN_ROUGHNESSMAP\n\t\tmaterial.sheenRoughness *= texture2D( sheenRoughnessMap, vSheenRoughnessMapUv ).a;\n\t#endif\n#endif\n#ifdef USE_ANISOTROPY\n\t#ifdef USE_ANISOTROPYMAP\n\t\tmat2 anisotropyMat = mat2( anisotropyVector.x, anisotropyVector.y, - anisotropyVector.y, anisotropyVector.x );\n\t\tvec3 anisotropyPolar = texture2D( anisotropyMap, vAnisotropyMapUv ).rgb;\n\t\tvec2 anisotropyV = anisotropyMat * normalize( 2.0 * anisotropyPolar.rg - vec2( 1.0 ) ) * anisotropyPolar.b;\n\t#else\n\t\tvec2 anisotropyV = anisotropyVector;\n\t#endif\n\tmaterial.anisotropy = length( anisotropyV );\n\tanisotropyV /= material.anisotropy;\n\tmaterial.anisotropy = saturate( material.anisotropy );\n\tmaterial.alphaT = mix( pow2( material.roughness ), 1.0, pow2( material.anisotropy ) );\n\tmaterial.anisotropyT = tbn[ 0 ] * anisotropyV.x - tbn[ 1 ] * anisotropyV.y;\n\tmaterial.anisotropyB = tbn[ 1 ] * anisotropyV.x + tbn[ 0 ] * anisotropyV.y;\n#endif";
- return this.distanceToPoint( sphere.center ) - sphere.radius;
+var lights_physical_pars_fragment = "struct PhysicalMaterial {\n\tvec3 diffuseColor;\n\tfloat roughness;\n\tvec3 specularColor;\n\tfloat specularF90;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat clearcoat;\n\t\tfloat clearcoatRoughness;\n\t\tvec3 clearcoatF0;\n\t\tfloat clearcoatF90;\n\t#endif\n\t#ifdef USE_IRIDESCENCE\n\t\tfloat iridescence;\n\t\tfloat iridescenceIOR;\n\t\tfloat iridescenceThickness;\n\t\tvec3 iridescenceFresnel;\n\t\tvec3 iridescenceF0;\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tvec3 sheenColor;\n\t\tfloat sheenRoughness;\n\t#endif\n\t#ifdef IOR\n\t\tfloat ior;\n\t#endif\n\t#ifdef USE_TRANSMISSION\n\t\tfloat transmission;\n\t\tfloat transmissionAlpha;\n\t\tfloat thickness;\n\t\tfloat attenuationDistance;\n\t\tvec3 attenuationColor;\n\t#endif\n\t#ifdef USE_ANISOTROPY\n\t\tfloat anisotropy;\n\t\tfloat alphaT;\n\t\tvec3 anisotropyT;\n\t\tvec3 anisotropyB;\n\t#endif\n};\nvec3 clearcoatSpecular = vec3( 0.0 );\nvec3 sheenSpecular = vec3( 0.0 );\nvec3 Schlick_to_F0( const in vec3 f, const in float f90, const in float dotVH ) {\n float x = clamp( 1.0 - dotVH, 0.0, 1.0 );\n float x2 = x * x;\n float x5 = clamp( x * x2 * x2, 0.0, 0.9999 );\n return ( f - vec3( f90 ) * x5 ) / ( 1.0 - x5 );\n}\nfloat V_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\n#ifdef USE_ANISOTROPY\n\tfloat V_GGX_SmithCorrelated_Anisotropic( const in float alphaT, const in float alphaB, const in float dotTV, const in float dotBV, const in float dotTL, const in float dotBL, const in float dotNV, const in float dotNL ) {\n\t\tfloat gv = dotNL * length( vec3( alphaT * dotTV, alphaB * dotBV, dotNV ) );\n\t\tfloat gl = dotNV * length( vec3( alphaT * dotTL, alphaB * dotBL, dotNL ) );\n\t\tfloat v = 0.5 / ( gv + gl );\n\t\treturn saturate(v);\n\t}\n\tfloat D_GGX_Anisotropic( const in float alphaT, const in float alphaB, const in float dotNH, const in float dotTH, const in float dotBH ) {\n\t\tfloat a2 = alphaT * alphaB;\n\t\thighp vec3 v = vec3( alphaB * dotTH, alphaT * dotBH, a2 * dotNH );\n\t\thighp float v2 = dot( v, v );\n\t\tfloat w2 = a2 / v2;\n\t\treturn RECIPROCAL_PI * a2 * pow2 ( w2 );\n\t}\n#endif\n#ifdef USE_CLEARCOAT\n\tvec3 BRDF_GGX_Clearcoat( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material) {\n\t\tvec3 f0 = material.clearcoatF0;\n\t\tfloat f90 = material.clearcoatF90;\n\t\tfloat roughness = material.clearcoatRoughness;\n\t\tfloat alpha = pow2( roughness );\n\t\tvec3 halfDir = normalize( lightDir + viewDir );\n\t\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\t\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\t\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\t\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\t\tvec3 F = F_Schlick( f0, f90, dotVH );\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t\treturn F * ( V * D );\n\t}\n#endif\nvec3 BRDF_GGX( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material ) {\n\tvec3 f0 = material.specularColor;\n\tfloat f90 = material.specularF90;\n\tfloat roughness = material.roughness;\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\tvec3 F = F_Schlick( f0, f90, dotVH );\n\t#ifdef USE_IRIDESCENCE\n\t\tF = mix( F, material.iridescenceFresnel, material.iridescence );\n\t#endif\n\t#ifdef USE_ANISOTROPY\n\t\tfloat dotTL = dot( material.anisotropyT, lightDir );\n\t\tfloat dotTV = dot( material.anisotropyT, viewDir );\n\t\tfloat dotTH = dot( material.anisotropyT, halfDir );\n\t\tfloat dotBL = dot( material.anisotropyB, lightDir );\n\t\tfloat dotBV = dot( material.anisotropyB, viewDir );\n\t\tfloat dotBH = dot( material.anisotropyB, halfDir );\n\t\tfloat V = V_GGX_SmithCorrelated_Anisotropic( material.alphaT, alpha, dotTV, dotBV, dotTL, dotBL, dotNV, dotNL );\n\t\tfloat D = D_GGX_Anisotropic( material.alphaT, alpha, dotNH, dotTH, dotBH );\n\t#else\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t#endif\n\treturn F * ( V * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\n#if defined( USE_SHEEN )\nfloat D_Charlie( float roughness, float dotNH ) {\n\tfloat alpha = pow2( roughness );\n\tfloat invAlpha = 1.0 / alpha;\n\tfloat cos2h = dotNH * dotNH;\n\tfloat sin2h = max( 1.0 - cos2h, 0.0078125 );\n\treturn ( 2.0 + invAlpha ) * pow( sin2h, invAlpha * 0.5 ) / ( 2.0 * PI );\n}\nfloat V_Neubelt( float dotNV, float dotNL ) {\n\treturn saturate( 1.0 / ( 4.0 * ( dotNL + dotNV - dotNL * dotNV ) ) );\n}\nvec3 BRDF_Sheen( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, vec3 sheenColor, const in float sheenRoughness ) {\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat D = D_Charlie( sheenRoughness, dotNH );\n\tfloat V = V_Neubelt( dotNV, dotNL );\n\treturn sheenColor * ( D * V );\n}\n#endif\nfloat IBLSheenBRDF( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat r2 = roughness * roughness;\n\tfloat a = roughness < 0.25 ? -339.2 * r2 + 161.4 * roughness - 25.9 : -8.48 * r2 + 14.3 * roughness - 9.95;\n\tfloat b = roughness < 0.25 ? 44.0 * r2 - 23.7 * roughness + 3.26 : 1.97 * r2 - 3.27 * roughness + 0.72;\n\tfloat DG = exp( a * dotNV + b ) + ( roughness < 0.25 ? 0.0 : 0.1 * ( roughness - 0.25 ) );\n\treturn saturate( DG * RECIPROCAL_PI );\n}\nvec2 DFGApprox( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 fab = vec2( - 1.04, 1.04 ) * a004 + r.zw;\n\treturn fab;\n}\nvec3 EnvironmentBRDF( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness ) {\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\treturn specularColor * fab.x + specularF90 * fab.y;\n}\n#ifdef USE_IRIDESCENCE\nvoid computeMultiscatteringIridescence( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float iridescence, const in vec3 iridescenceF0, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#else\nvoid computeMultiscattering( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#endif\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\t#ifdef USE_IRIDESCENCE\n\t\tvec3 Fr = mix( specularColor, iridescenceF0, iridescence );\n\t#else\n\t\tvec3 Fr = specularColor;\n\t#endif\n\tvec3 FssEss = Fr * fab.x + specularF90 * fab.y;\n\tfloat Ess = fab.x + fab.y;\n\tfloat Ems = 1.0 - Ess;\n\tvec3 Favg = Fr + ( 1.0 - Fr ) * 0.047619;\tvec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );\n\tsingleScatter += FssEss;\n\tmultiScatter += Fms * Ems;\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometryNormal;\n\t\tvec3 viewDir = geometryViewDir;\n\t\tvec3 position = geometryPosition;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.roughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos + halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos - halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos - halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos + halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tvec4 t1 = texture2D( ltc_1, uv );\n\t\tvec4 t2 = texture2D( ltc_2, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( t1.x, 0, t1.y ),\n\t\t\tvec3( 0, 1, 0 ),\n\t\t\tvec3( t1.z, 0, t1.w )\n\t\t);\n\t\tvec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y );\n\t\treflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometryNormal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNLcc = saturate( dot( geometryClearcoatNormal, directLight.direction ) );\n\t\tvec3 ccIrradiance = dotNLcc * directLight.color;\n\t\tclearcoatSpecular += ccIrradiance * BRDF_GGX_Clearcoat( directLight.direction, geometryViewDir, geometryClearcoatNormal, material );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecular += irradiance * BRDF_Sheen( directLight.direction, geometryViewDir, geometryNormal, material.sheenColor, material.sheenRoughness );\n\t#endif\n\treflectedLight.directSpecular += irradiance * BRDF_GGX( directLight.direction, geometryViewDir, geometryNormal, material );\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradiance, const in vec3 clearcoatRadiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatSpecular += clearcoatRadiance * EnvironmentBRDF( geometryClearcoatNormal, geometryViewDir, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecular += irradiance * material.sheenColor * IBLSheenBRDF( geometryNormal, geometryViewDir, material.sheenRoughness );\n\t#endif\n\tvec3 singleScattering = vec3( 0.0 );\n\tvec3 multiScattering = vec3( 0.0 );\n\tvec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\n\t#ifdef USE_IRIDESCENCE\n\t\tcomputeMultiscatteringIridescence( geometryNormal, geometryViewDir, material.specularColor, material.specularF90, material.iridescence, material.iridescenceFresnel, material.roughness, singleScattering, multiScattering );\n\t#else\n\t\tcomputeMultiscattering( geometryNormal, geometryViewDir, material.specularColor, material.specularF90, material.roughness, singleScattering, multiScattering );\n\t#endif\n\tvec3 totalScattering = singleScattering + multiScattering;\n\tvec3 diffuse = material.diffuseColor * ( 1.0 - max( max( totalScattering.r, totalScattering.g ), totalScattering.b ) );\n\treflectedLight.indirectSpecular += radiance * singleScattering;\n\treflectedLight.indirectSpecular += multiScattering * cosineWeightedIrradiance;\n\treflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance;\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}";
- },
+var lights_fragment_begin = "\nvec3 geometryPosition = - vViewPosition;\nvec3 geometryNormal = normal;\nvec3 geometryViewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition );\nvec3 geometryClearcoatNormal;\n#ifdef USE_CLEARCOAT\n\tgeometryClearcoatNormal = clearcoatNormal;\n#endif\n#ifdef USE_IRIDESCENCE\n\tfloat dotNVi = saturate( dot( normal, geometryViewDir ) );\n\tif ( material.iridescenceThickness == 0.0 ) {\n\t\tmaterial.iridescence = 0.0;\n\t} else {\n\t\tmaterial.iridescence = saturate( material.iridescence );\n\t}\n\tif ( material.iridescence > 0.0 ) {\n\t\tmaterial.iridescenceFresnel = evalIridescence( 1.0, material.iridescenceIOR, dotNVi, material.iridescenceThickness, material.specularColor );\n\t\tmaterial.iridescenceF0 = Schlick_to_F0( material.iridescenceFresnel, 1.0, dotNVi );\n\t}\n#endif\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointLightInfo( pointLight, geometryPosition, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_POINT_LIGHT_SHADOWS )\n\t\tpointLightShadow = pointLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getPointShadow( pointShadowMap[ i ], pointLightShadow.shadowMapSize, pointLightShadow.shadowBias, pointLightShadow.shadowRadius, vPointShadowCoord[ i ], pointLightShadow.shadowCameraNear, pointLightShadow.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\tvec4 spotColor;\n\tvec3 spotLightCoord;\n\tbool inSpotLightMap;\n\t#if defined( USE_SHADOWMAP ) && NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotLightInfo( spotLight, geometryPosition, directLight );\n\t\t#if ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )\n\t\t#define SPOT_LIGHT_MAP_INDEX UNROLLED_LOOP_INDEX\n\t\t#elif ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\t#define SPOT_LIGHT_MAP_INDEX NUM_SPOT_LIGHT_MAPS\n\t\t#else\n\t\t#define SPOT_LIGHT_MAP_INDEX ( UNROLLED_LOOP_INDEX - NUM_SPOT_LIGHT_SHADOWS + NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )\n\t\t#endif\n\t\t#if ( SPOT_LIGHT_MAP_INDEX < NUM_SPOT_LIGHT_MAPS )\n\t\t\tspotLightCoord = vSpotLightCoord[ i ].xyz / vSpotLightCoord[ i ].w;\n\t\t\tinSpotLightMap = all( lessThan( abs( spotLightCoord * 2. - 1. ), vec3( 1.0 ) ) );\n\t\t\tspotColor = texture2D( spotLightMap[ SPOT_LIGHT_MAP_INDEX ], spotLightCoord.xy );\n\t\t\tdirectLight.color = inSpotLightMap ? directLight.color * spotColor.rgb : directLight.color;\n\t\t#endif\n\t\t#undef SPOT_LIGHT_MAP_INDEX\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\tspotLightShadow = spotLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( spotShadowMap[ i ], spotLightShadow.shadowMapSize, spotLightShadow.shadowBias, spotLightShadow.shadowRadius, vSpotLightCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalLightInfo( directionalLight, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )\n\t\tdirectionalLightShadow = directionalLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 iblIrradiance = vec3( 0.0 );\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\t#if defined( USE_LIGHT_PROBES )\n\t\tirradiance += getLightProbeIrradiance( lightProbe, geometryNormal );\n\t#endif\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometryNormal );\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if defined( RE_IndirectSpecular )\n\tvec3 radiance = vec3( 0.0 );\n\tvec3 clearcoatRadiance = vec3( 0.0 );\n#endif";
- projectPoint: function ( point, target ) {
+var lights_fragment_maps = "#if defined( RE_IndirectDiffuse )\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\n\t\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( STANDARD ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tiblIrradiance += getIBLIrradiance( geometryNormal );\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\t#ifdef USE_ANISOTROPY\n\t\tradiance += getIBLAnisotropyRadiance( geometryViewDir, geometryNormal, material.roughness, material.anisotropyB, material.anisotropy );\n\t#else\n\t\tradiance += getIBLRadiance( geometryViewDir, geometryNormal, material.roughness );\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatRadiance += getIBLRadiance( geometryViewDir, geometryClearcoatNormal, material.clearcoatRoughness );\n\t#endif\n#endif";
- if ( target === undefined ) {
+var lights_fragment_end = "#if defined( RE_IndirectDiffuse )\n\tRE_IndirectDiffuse( irradiance, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n#endif\n#if defined( RE_IndirectSpecular )\n\tRE_IndirectSpecular( radiance, iblIrradiance, clearcoatRadiance, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n#endif";
- console.warn( 'THREE.Plane: .projectPoint() target is now required' );
- target = new Vector3();
+var logdepthbuf_fragment = "#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tgl_FragDepthEXT = vIsPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif";
- }
+var logdepthbuf_pars_fragment = "#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tuniform float logDepthBufFC;\n\tvarying float vFragDepth;\n\tvarying float vIsPerspective;\n#endif";
- return target.copy( this.normal ).multiplyScalar( - this.distanceToPoint( point ) ).add( point );
+var logdepthbuf_pars_vertex = "#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t\tvarying float vIsPerspective;\n\t#else\n\t\tuniform float logDepthBufFC;\n\t#endif\n#endif";
- },
+var logdepthbuf_vertex = "#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvFragDepth = 1.0 + gl_Position.w;\n\t\tvIsPerspective = float( isPerspectiveMatrix( projectionMatrix ) );\n\t#else\n\t\tif ( isPerspectiveMatrix( projectionMatrix ) ) {\n\t\t\tgl_Position.z = log2( max( EPSILON, gl_Position.w + 1.0 ) ) * logDepthBufFC - 1.0;\n\t\t\tgl_Position.z *= gl_Position.w;\n\t\t}\n\t#endif\n#endif";
- intersectLine: function ( line, target ) {
+var map_fragment = "#ifdef USE_MAP\n\tvec4 sampledDiffuseColor = texture2D( map, vMapUv );\n\t#ifdef DECODE_VIDEO_TEXTURE\n\t\tsampledDiffuseColor = vec4( mix( pow( sampledDiffuseColor.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), sampledDiffuseColor.rgb * 0.0773993808, vec3( lessThanEqual( sampledDiffuseColor.rgb, vec3( 0.04045 ) ) ) ), sampledDiffuseColor.w );\n\t\n\t#endif\n\tdiffuseColor *= sampledDiffuseColor;\n#endif";
- if ( target === undefined ) {
+var map_pars_fragment = "#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif";
- console.warn( 'THREE.Plane: .intersectLine() target is now required' );
- target = new Vector3();
+var map_particle_fragment = "#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\t#if defined( USE_POINTS_UV )\n\t\tvec2 uv = vUv;\n\t#else\n\t\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n\t#endif\n#endif\n#ifdef USE_MAP\n\tdiffuseColor *= texture2D( map, uv );\n#endif\n#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, uv ).g;\n#endif";
- }
+var map_particle_pars_fragment = "#if defined( USE_POINTS_UV )\n\tvarying vec2 vUv;\n#else\n\t#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\t\tuniform mat3 uvTransform;\n\t#endif\n#endif\n#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif\n#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif";
- var direction = line.delta( _vector1 );
+var metalnessmap_fragment = "float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vMetalnessMapUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif";
- var denominator = this.normal.dot( direction );
+var metalnessmap_pars_fragment = "#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif";
- if ( denominator === 0 ) {
+var morphcolor_vertex = "#if defined( USE_MORPHCOLORS ) && defined( MORPHTARGETS_TEXTURE )\n\tvColor *= morphTargetBaseInfluence;\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t#if defined( USE_COLOR_ALPHA )\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ) * morphTargetInfluences[ i ];\n\t\t#elif defined( USE_COLOR )\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ).rgb * morphTargetInfluences[ i ];\n\t\t#endif\n\t}\n#endif";
- // line is coplanar, return origin
- if ( this.distanceToPoint( line.start ) === 0 ) {
+var morphnormal_vertex = "#ifdef USE_MORPHNORMALS\n\tobjectNormal *= morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) objectNormal += getMorph( gl_VertexID, i, 1 ).xyz * morphTargetInfluences[ i ];\n\t\t}\n\t#else\n\t\tobjectNormal += morphNormal0 * morphTargetInfluences[ 0 ];\n\t\tobjectNormal += morphNormal1 * morphTargetInfluences[ 1 ];\n\t\tobjectNormal += morphNormal2 * morphTargetInfluences[ 2 ];\n\t\tobjectNormal += morphNormal3 * morphTargetInfluences[ 3 ];\n\t#endif\n#endif";
- return target.copy( line.start );
+var morphtarget_pars_vertex = "#ifdef USE_MORPHTARGETS\n\tuniform float morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tuniform float morphTargetInfluences[ MORPHTARGETS_COUNT ];\n\t\tuniform sampler2DArray morphTargetsTexture;\n\t\tuniform ivec2 morphTargetsTextureSize;\n\t\tvec4 getMorph( const in int vertexIndex, const in int morphTargetIndex, const in int offset ) {\n\t\t\tint texelIndex = vertexIndex * MORPHTARGETS_TEXTURE_STRIDE + offset;\n\t\t\tint y = texelIndex / morphTargetsTextureSize.x;\n\t\t\tint x = texelIndex - y * morphTargetsTextureSize.x;\n\t\t\tivec3 morphUV = ivec3( x, y, morphTargetIndex );\n\t\t\treturn texelFetch( morphTargetsTexture, morphUV, 0 );\n\t\t}\n\t#else\n\t\t#ifndef USE_MORPHNORMALS\n\t\t\tuniform float morphTargetInfluences[ 8 ];\n\t\t#else\n\t\t\tuniform float morphTargetInfluences[ 4 ];\n\t\t#endif\n\t#endif\n#endif";
- }
+var morphtarget_vertex = "#ifdef USE_MORPHTARGETS\n\ttransformed *= morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) transformed += getMorph( gl_VertexID, i, 0 ).xyz * morphTargetInfluences[ i ];\n\t\t}\n\t#else\n\t\ttransformed += morphTarget0 * morphTargetInfluences[ 0 ];\n\t\ttransformed += morphTarget1 * morphTargetInfluences[ 1 ];\n\t\ttransformed += morphTarget2 * morphTargetInfluences[ 2 ];\n\t\ttransformed += morphTarget3 * morphTargetInfluences[ 3 ];\n\t\t#ifndef USE_MORPHNORMALS\n\t\t\ttransformed += morphTarget4 * morphTargetInfluences[ 4 ];\n\t\t\ttransformed += morphTarget5 * morphTargetInfluences[ 5 ];\n\t\t\ttransformed += morphTarget6 * morphTargetInfluences[ 6 ];\n\t\t\ttransformed += morphTarget7 * morphTargetInfluences[ 7 ];\n\t\t#endif\n\t#endif\n#endif";
- // Unsure if this is the correct method to handle this case.
- return undefined;
+var normal_fragment_begin = "float faceDirection = gl_FrontFacing ? 1.0 : - 1.0;\n#ifdef FLAT_SHADED\n\tvec3 fdx = dFdx( vViewPosition );\n\tvec3 fdy = dFdy( vViewPosition );\n\tvec3 normal = normalize( cross( fdx, fdy ) );\n#else\n\tvec3 normal = normalize( vNormal );\n\t#ifdef DOUBLE_SIDED\n\t\tnormal *= faceDirection;\n\t#endif\n#endif\n#if defined( USE_NORMALMAP_TANGENTSPACE ) || defined( USE_CLEARCOAT_NORMALMAP ) || defined( USE_ANISOTROPY )\n\t#ifdef USE_TANGENT\n\t\tmat3 tbn = mat3( normalize( vTangent ), normalize( vBitangent ), normal );\n\t#else\n\t\tmat3 tbn = getTangentFrame( - vViewPosition, normal,\n\t\t#if defined( USE_NORMALMAP )\n\t\t\tvNormalMapUv\n\t\t#elif defined( USE_CLEARCOAT_NORMALMAP )\n\t\t\tvClearcoatNormalMapUv\n\t\t#else\n\t\t\tvUv\n\t\t#endif\n\t\t);\n\t#endif\n\t#if defined( DOUBLE_SIDED ) && ! defined( FLAT_SHADED )\n\t\ttbn[0] *= faceDirection;\n\t\ttbn[1] *= faceDirection;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\t#ifdef USE_TANGENT\n\t\tmat3 tbn2 = mat3( normalize( vTangent ), normalize( vBitangent ), normal );\n\t#else\n\t\tmat3 tbn2 = getTangentFrame( - vViewPosition, normal, vClearcoatNormalMapUv );\n\t#endif\n\t#if defined( DOUBLE_SIDED ) && ! defined( FLAT_SHADED )\n\t\ttbn2[0] *= faceDirection;\n\t\ttbn2[1] *= faceDirection;\n\t#endif\n#endif\nvec3 nonPerturbedNormal = normal;";
- }
+var normal_fragment_maps = "#ifdef USE_NORMALMAP_OBJECTSPACE\n\tnormal = texture2D( normalMap, vNormalMapUv ).xyz * 2.0 - 1.0;\n\t#ifdef FLIP_SIDED\n\t\tnormal = - normal;\n\t#endif\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * faceDirection;\n\t#endif\n\tnormal = normalize( normalMatrix * normal );\n#elif defined( USE_NORMALMAP_TANGENTSPACE )\n\tvec3 mapN = texture2D( normalMap, vNormalMapUv ).xyz * 2.0 - 1.0;\n\tmapN.xy *= normalScale;\n\tnormal = normalize( tbn * mapN );\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( - vViewPosition, normal, dHdxy_fwd(), faceDirection );\n#endif";
- var t = - ( line.start.dot( this.normal ) + this.constant ) / denominator;
+var normal_pars_fragment = "#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif";
- if ( t < 0 || t > 1 ) {
+var normal_pars_vertex = "#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif";
- return undefined;
+var normal_vertex = "#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n\t#ifdef USE_TANGENT\n\t\tvTangent = normalize( transformedTangent );\n\t\tvBitangent = normalize( cross( vNormal, vTangent ) * tangent.w );\n\t#endif\n#endif";
- }
+var normalmap_pars_fragment = "#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n#endif\n#ifdef USE_NORMALMAP_OBJECTSPACE\n\tuniform mat3 normalMatrix;\n#endif\n#if ! defined ( USE_TANGENT ) && ( defined ( USE_NORMALMAP_TANGENTSPACE ) || defined ( USE_CLEARCOAT_NORMALMAP ) || defined( USE_ANISOTROPY ) )\n\tmat3 getTangentFrame( vec3 eye_pos, vec3 surf_norm, vec2 uv ) {\n\t\tvec3 q0 = dFdx( eye_pos.xyz );\n\t\tvec3 q1 = dFdy( eye_pos.xyz );\n\t\tvec2 st0 = dFdx( uv.st );\n\t\tvec2 st1 = dFdy( uv.st );\n\t\tvec3 N = surf_norm;\n\t\tvec3 q1perp = cross( q1, N );\n\t\tvec3 q0perp = cross( N, q0 );\n\t\tvec3 T = q1perp * st0.x + q0perp * st1.x;\n\t\tvec3 B = q1perp * st0.y + q0perp * st1.y;\n\t\tfloat det = max( dot( T, T ), dot( B, B ) );\n\t\tfloat scale = ( det == 0.0 ) ? 0.0 : inversesqrt( det );\n\t\treturn mat3( T * scale, B * scale, N );\n\t}\n#endif";
- return target.copy( direction ).multiplyScalar( t ).add( line.start );
+var clearcoat_normal_fragment_begin = "#ifdef USE_CLEARCOAT\n\tvec3 clearcoatNormal = nonPerturbedNormal;\n#endif";
- },
+var clearcoat_normal_fragment_maps = "#ifdef USE_CLEARCOAT_NORMALMAP\n\tvec3 clearcoatMapN = texture2D( clearcoatNormalMap, vClearcoatNormalMapUv ).xyz * 2.0 - 1.0;\n\tclearcoatMapN.xy *= clearcoatNormalScale;\n\tclearcoatNormal = normalize( tbn2 * clearcoatMapN );\n#endif";
- intersectsLine: function ( line ) {
+var clearcoat_pars_fragment = "#ifdef USE_CLEARCOATMAP\n\tuniform sampler2D clearcoatMap;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tuniform sampler2D clearcoatNormalMap;\n\tuniform vec2 clearcoatNormalScale;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tuniform sampler2D clearcoatRoughnessMap;\n#endif";
- // Note: this tests if a line intersects the plane, not whether it (or its end-points) are coplanar with it.
+var iridescence_pars_fragment = "#ifdef USE_IRIDESCENCEMAP\n\tuniform sampler2D iridescenceMap;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tuniform sampler2D iridescenceThicknessMap;\n#endif";
- var startSign = this.distanceToPoint( line.start );
- var endSign = this.distanceToPoint( line.end );
+var opaque_fragment = "#ifdef OPAQUE\ndiffuseColor.a = 1.0;\n#endif\n#ifdef USE_TRANSMISSION\ndiffuseColor.a *= material.transmissionAlpha;\n#endif\ngl_FragColor = vec4( outgoingLight, diffuseColor.a );";
- return ( startSign < 0 && endSign > 0 ) || ( endSign < 0 && startSign > 0 );
+var packing = "vec3 packNormalToRGB( const in vec3 normal ) {\n\treturn normalize( normal ) * 0.5 + 0.5;\n}\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n\treturn 2.0 * rgb.xyz - 1.0;\n}\nconst float PackUpscale = 256. / 255.;const float UnpackDownscale = 255. / 256.;\nconst vec3 PackFactors = vec3( 256. * 256. * 256., 256. * 256., 256. );\nconst vec4 UnpackFactors = UnpackDownscale / vec4( PackFactors, 1. );\nconst float ShiftRight8 = 1. / 256.;\nvec4 packDepthToRGBA( const in float v ) {\n\tvec4 r = vec4( fract( v * PackFactors ), v );\n\tr.yzw -= r.xyz * ShiftRight8;\treturn r * PackUpscale;\n}\nfloat unpackRGBAToDepth( const in vec4 v ) {\n\treturn dot( v, UnpackFactors );\n}\nvec2 packDepthToRG( in highp float v ) {\n\treturn packDepthToRGBA( v ).yx;\n}\nfloat unpackRGToDepth( const in highp vec2 v ) {\n\treturn unpackRGBAToDepth( vec4( v.xy, 0.0, 0.0 ) );\n}\nvec4 pack2HalfToRGBA( vec2 v ) {\n\tvec4 r = vec4( v.x, fract( v.x * 255.0 ), v.y, fract( v.y * 255.0 ) );\n\treturn vec4( r.x - r.y / 255.0, r.y, r.z - r.w / 255.0, r.w );\n}\nvec2 unpackRGBATo2Half( vec4 v ) {\n\treturn vec2( v.x + ( v.y / 255.0 ), v.z + ( v.w / 255.0 ) );\n}\nfloat viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float depth, const in float near, const in float far ) {\n\treturn depth * ( near - far ) - near;\n}\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( ( near + viewZ ) * far ) / ( ( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float depth, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * depth - far );\n}";
- },
+var premultiplied_alpha_fragment = "#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif";
- intersectsBox: function ( box ) {
+var project_vertex = "vec4 mvPosition = vec4( transformed, 1.0 );\n#ifdef USE_INSTANCING\n\tmvPosition = instanceMatrix * mvPosition;\n#endif\nmvPosition = modelViewMatrix * mvPosition;\ngl_Position = projectionMatrix * mvPosition;";
- return box.intersectsPlane( this );
+var dithering_fragment = "#ifdef DITHERING\n\tgl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif";
- },
+var dithering_pars_fragment = "#ifdef DITHERING\n\tvec3 dithering( vec3 color ) {\n\t\tfloat grid_position = rand( gl_FragCoord.xy );\n\t\tvec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 );\n\t\tdither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position );\n\t\treturn color + dither_shift_RGB;\n\t}\n#endif";
- intersectsSphere: function ( sphere ) {
+var roughnessmap_fragment = "float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vRoughnessMapUv );\n\troughnessFactor *= texelRoughness.g;\n#endif";
- return sphere.intersectsPlane( this );
+var roughnessmap_pars_fragment = "#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif";
- },
+var shadowmap_pars_fragment = "#if NUM_SPOT_LIGHT_COORDS > 0\n\tvarying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#if NUM_SPOT_LIGHT_MAPS > 0\n\tuniform sampler2D spotLightMap[ NUM_SPOT_LIGHT_MAPS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tvec2 texture2DDistribution( sampler2D shadow, vec2 uv ) {\n\t\treturn unpackRGBATo2Half( texture2D( shadow, uv ) );\n\t}\n\tfloat VSMShadow (sampler2D shadow, vec2 uv, float compare ){\n\t\tfloat occlusion = 1.0;\n\t\tvec2 distribution = texture2DDistribution( shadow, uv );\n\t\tfloat hard_shadow = step( compare , distribution.x );\n\t\tif (hard_shadow != 1.0 ) {\n\t\t\tfloat distance = compare - distribution.x ;\n\t\t\tfloat variance = max( 0.00000, distribution.y * distribution.y );\n\t\t\tfloat softness_probability = variance / (variance + distance * distance );\t\t\tsoftness_probability = clamp( ( softness_probability - 0.3 ) / ( 0.95 - 0.3 ), 0.0, 1.0 );\t\t\tocclusion = clamp( max( hard_shadow, softness_probability ), 0.0, 1.0 );\n\t\t}\n\t\treturn occlusion;\n\t}\n\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\tfloat shadow = 1.0;\n\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\tshadowCoord.z += shadowBias;\n\t\tbool inFrustum = shadowCoord.x >= 0.0 && shadowCoord.x <= 1.0 && shadowCoord.y >= 0.0 && shadowCoord.y <= 1.0;\n\t\tbool frustumTest = inFrustum && shadowCoord.z <= 1.0;\n\t\tif ( frustumTest ) {\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tfloat dx2 = dx0 / 2.0;\n\t\t\tfloat dy2 = dy0 / 2.0;\n\t\t\tfloat dx3 = dx1 / 2.0;\n\t\t\tfloat dy3 = dy1 / 2.0;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 17.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx = texelSize.x;\n\t\t\tfloat dy = texelSize.y;\n\t\t\tvec2 uv = shadowCoord.xy;\n\t\t\tvec2 f = fract( uv * shadowMapSize + 0.5 );\n\t\t\tuv -= f * texelSize;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, uv, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( dx, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( 0.0, dy ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + texelSize, shadowCoord.z ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, dy ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( 0.0, -dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 0.0, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( mix( texture2DCompare( shadowMap, uv + vec2( -dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.x ),\n\t\t\t\t\t mix( texture2DCompare( shadowMap, uv + vec2( -dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.x ),\n\t\t\t\t\t f.y )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_VSM )\n\t\t\tshadow = VSMShadow( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#else\n\t\t\tshadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#endif\n\t\t}\n\t\treturn shadow;\n\t}\n\tvec2 cubeToUV( vec3 v, float texelSizeY ) {\n\t\tvec3 absV = abs( v );\n\t\tfloat scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n\t\tabsV *= scaleToCube;\n\t\tv *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n\t\tvec2 planar = v.xy;\n\t\tfloat almostATexel = 1.5 * texelSizeY;\n\t\tfloat almostOne = 1.0 - almostATexel;\n\t\tif ( absV.z >= almostOne ) {\n\t\t\tif ( v.z > 0.0 )\n\t\t\t\tplanar.x = 4.0 - v.x;\n\t\t} else if ( absV.x >= almostOne ) {\n\t\t\tfloat signX = sign( v.x );\n\t\t\tplanar.x = v.z * signX + 2.0 * signX;\n\t\t} else if ( absV.y >= almostOne ) {\n\t\t\tfloat signY = sign( v.y );\n\t\t\tplanar.x = v.x + 2.0 * signY + 2.0;\n\t\t\tplanar.y = v.z * signY - 2.0;\n\t\t}\n\t\treturn vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n\t}\n\tfloat getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\tfloat dp = ( length( lightToPosition ) - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear );\t\tdp += shadowBias;\n\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT ) || defined( SHADOWMAP_TYPE_VSM )\n\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n\t\t\treturn (\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\treturn texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n\t\t#endif\n\t}\n#endif";
- coplanarPoint: function ( target ) {
+var shadowmap_pars_vertex = "#if NUM_SPOT_LIGHT_COORDS > 0\n\tuniform mat4 spotLightMatrix[ NUM_SPOT_LIGHT_COORDS ];\n\tvarying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n#endif";
- if ( target === undefined ) {
+var shadowmap_vertex = "#if ( defined( USE_SHADOWMAP ) && ( NUM_DIR_LIGHT_SHADOWS > 0 || NUM_POINT_LIGHT_SHADOWS > 0 ) ) || ( NUM_SPOT_LIGHT_COORDS > 0 )\n\tvec3 shadowWorldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\tvec4 shadowWorldPosition;\n#endif\n#if defined( USE_SHADOWMAP )\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * directionalLightShadows[ i ].shadowNormalBias, 0 );\n\t\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * shadowWorldPosition;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * pointLightShadows[ i ].shadowNormalBias, 0 );\n\t\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * shadowWorldPosition;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if NUM_SPOT_LIGHT_COORDS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_COORDS; i ++ ) {\n\t\tshadowWorldPosition = worldPosition;\n\t\t#if ( defined( USE_SHADOWMAP ) && UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\t\tshadowWorldPosition.xyz += shadowWorldNormal * spotLightShadows[ i ].shadowNormalBias;\n\t\t#endif\n\t\tvSpotLightCoord[ i ] = spotLightMatrix[ i ] * shadowWorldPosition;\n\t}\n\t#pragma unroll_loop_end\n#endif";
- console.warn( 'THREE.Plane: .coplanarPoint() target is now required' );
- target = new Vector3();
+var shadowmask_pars_fragment = "float getShadowMask() {\n\tfloat shadow = 1.0;\n\t#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\tdirectionalLight = directionalLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_SHADOWS; i ++ ) {\n\t\tspotLight = spotLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotLightCoord[ i ] ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\tpointLight = pointLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#endif\n\treturn shadow;\n}";
- }
+var skinbase_vertex = "#ifdef USE_SKINNING\n\tmat4 boneMatX = getBoneMatrix( skinIndex.x );\n\tmat4 boneMatY = getBoneMatrix( skinIndex.y );\n\tmat4 boneMatZ = getBoneMatrix( skinIndex.z );\n\tmat4 boneMatW = getBoneMatrix( skinIndex.w );\n#endif";
- return target.copy( this.normal ).multiplyScalar( - this.constant );
+var skinning_pars_vertex = "#ifdef USE_SKINNING\n\tuniform mat4 bindMatrix;\n\tuniform mat4 bindMatrixInverse;\n\tuniform highp sampler2D boneTexture;\n\tuniform int boneTextureSize;\n\tmat4 getBoneMatrix( const in float i ) {\n\t\tfloat j = i * 4.0;\n\t\tfloat x = mod( j, float( boneTextureSize ) );\n\t\tfloat y = floor( j / float( boneTextureSize ) );\n\t\tfloat dx = 1.0 / float( boneTextureSize );\n\t\tfloat dy = 1.0 / float( boneTextureSize );\n\t\ty = dy * ( y + 0.5 );\n\t\tvec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );\n\t\tvec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );\n\t\tvec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );\n\t\tvec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );\n\t\tmat4 bone = mat4( v1, v2, v3, v4 );\n\t\treturn bone;\n\t}\n#endif";
- },
+var skinning_vertex = "#ifdef USE_SKINNING\n\tvec4 skinVertex = bindMatrix * vec4( transformed, 1.0 );\n\tvec4 skinned = vec4( 0.0 );\n\tskinned += boneMatX * skinVertex * skinWeight.x;\n\tskinned += boneMatY * skinVertex * skinWeight.y;\n\tskinned += boneMatZ * skinVertex * skinWeight.z;\n\tskinned += boneMatW * skinVertex * skinWeight.w;\n\ttransformed = ( bindMatrixInverse * skinned ).xyz;\n#endif";
- applyMatrix4: function ( matrix, optionalNormalMatrix ) {
+var skinnormal_vertex = "#ifdef USE_SKINNING\n\tmat4 skinMatrix = mat4( 0.0 );\n\tskinMatrix += skinWeight.x * boneMatX;\n\tskinMatrix += skinWeight.y * boneMatY;\n\tskinMatrix += skinWeight.z * boneMatZ;\n\tskinMatrix += skinWeight.w * boneMatW;\n\tskinMatrix = bindMatrixInverse * skinMatrix * bindMatrix;\n\tobjectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;\n\t#ifdef USE_TANGENT\n\t\tobjectTangent = vec4( skinMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n\t#endif\n#endif";
- var normalMatrix = optionalNormalMatrix || _normalMatrix.getNormalMatrix( matrix );
+var specularmap_fragment = "float specularStrength;\n#ifdef USE_SPECULARMAP\n\tvec4 texelSpecular = texture2D( specularMap, vSpecularMapUv );\n\tspecularStrength = texelSpecular.r;\n#else\n\tspecularStrength = 1.0;\n#endif";
- var referencePoint = this.coplanarPoint( _vector1 ).applyMatrix4( matrix );
+var specularmap_pars_fragment = "#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif";
- var normal = this.normal.applyMatrix3( normalMatrix ).normalize();
+var tonemapping_fragment = "#if defined( TONE_MAPPING )\n\tgl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif";
- this.constant = - referencePoint.dot( normal );
+var tonemapping_pars_fragment = "#ifndef saturate\n#define saturate( a ) clamp( a, 0.0, 1.0 )\n#endif\nuniform float toneMappingExposure;\nvec3 LinearToneMapping( vec3 color ) {\n\treturn saturate( toneMappingExposure * color );\n}\nvec3 ReinhardToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( color / ( vec3( 1.0 ) + color ) );\n}\nvec3 OptimizedCineonToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\tcolor = max( vec3( 0.0 ), color - 0.004 );\n\treturn pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );\n}\nvec3 RRTAndODTFit( vec3 v ) {\n\tvec3 a = v * ( v + 0.0245786 ) - 0.000090537;\n\tvec3 b = v * ( 0.983729 * v + 0.4329510 ) + 0.238081;\n\treturn a / b;\n}\nvec3 ACESFilmicToneMapping( vec3 color ) {\n\tconst mat3 ACESInputMat = mat3(\n\t\tvec3( 0.59719, 0.07600, 0.02840 ),\t\tvec3( 0.35458, 0.90834, 0.13383 ),\n\t\tvec3( 0.04823, 0.01566, 0.83777 )\n\t);\n\tconst mat3 ACESOutputMat = mat3(\n\t\tvec3( 1.60475, -0.10208, -0.00327 ),\t\tvec3( -0.53108, 1.10813, -0.07276 ),\n\t\tvec3( -0.07367, -0.00605, 1.07602 )\n\t);\n\tcolor *= toneMappingExposure / 0.6;\n\tcolor = ACESInputMat * color;\n\tcolor = RRTAndODTFit( color );\n\tcolor = ACESOutputMat * color;\n\treturn saturate( color );\n}\nvec3 CustomToneMapping( vec3 color ) { return color; }";
- return this;
+var transmission_fragment = "#ifdef USE_TRANSMISSION\n\tmaterial.transmission = transmission;\n\tmaterial.transmissionAlpha = 1.0;\n\tmaterial.thickness = thickness;\n\tmaterial.attenuationDistance = attenuationDistance;\n\tmaterial.attenuationColor = attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tmaterial.transmission *= texture2D( transmissionMap, vTransmissionMapUv ).r;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tmaterial.thickness *= texture2D( thicknessMap, vThicknessMapUv ).g;\n\t#endif\n\tvec3 pos = vWorldPosition;\n\tvec3 v = normalize( cameraPosition - pos );\n\tvec3 n = inverseTransformDirection( normal, viewMatrix );\n\tvec4 transmitted = getIBLVolumeRefraction(\n\t\tn, v, material.roughness, material.diffuseColor, material.specularColor, material.specularF90,\n\t\tpos, modelMatrix, viewMatrix, projectionMatrix, material.ior, material.thickness,\n\t\tmaterial.attenuationColor, material.attenuationDistance );\n\tmaterial.transmissionAlpha = mix( material.transmissionAlpha, transmitted.a, material.transmission );\n\ttotalDiffuse = mix( totalDiffuse, transmitted.rgb, material.transmission );\n#endif";
- },
+var transmission_pars_fragment = "#ifdef USE_TRANSMISSION\n\tuniform float transmission;\n\tuniform float thickness;\n\tuniform float attenuationDistance;\n\tuniform vec3 attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tuniform sampler2D transmissionMap;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tuniform sampler2D thicknessMap;\n\t#endif\n\tuniform vec2 transmissionSamplerSize;\n\tuniform sampler2D transmissionSamplerMap;\n\tuniform mat4 modelMatrix;\n\tuniform mat4 projectionMatrix;\n\tvarying vec3 vWorldPosition;\n\tfloat w0( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * ( a * ( - a + 3.0 ) - 3.0 ) + 1.0 );\n\t}\n\tfloat w1( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * a * ( 3.0 * a - 6.0 ) + 4.0 );\n\t}\n\tfloat w2( float a ){\n\t\treturn ( 1.0 / 6.0 ) * ( a * ( a * ( - 3.0 * a + 3.0 ) + 3.0 ) + 1.0 );\n\t}\n\tfloat w3( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * a * a );\n\t}\n\tfloat g0( float a ) {\n\t\treturn w0( a ) + w1( a );\n\t}\n\tfloat g1( float a ) {\n\t\treturn w2( a ) + w3( a );\n\t}\n\tfloat h0( float a ) {\n\t\treturn - 1.0 + w1( a ) / ( w0( a ) + w1( a ) );\n\t}\n\tfloat h1( float a ) {\n\t\treturn 1.0 + w3( a ) / ( w2( a ) + w3( a ) );\n\t}\n\tvec4 bicubic( sampler2D tex, vec2 uv, vec4 texelSize, float lod ) {\n\t\tuv = uv * texelSize.zw + 0.5;\n\t\tvec2 iuv = floor( uv );\n\t\tvec2 fuv = fract( uv );\n\t\tfloat g0x = g0( fuv.x );\n\t\tfloat g1x = g1( fuv.x );\n\t\tfloat h0x = h0( fuv.x );\n\t\tfloat h1x = h1( fuv.x );\n\t\tfloat h0y = h0( fuv.y );\n\t\tfloat h1y = h1( fuv.y );\n\t\tvec2 p0 = ( vec2( iuv.x + h0x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p1 = ( vec2( iuv.x + h1x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p2 = ( vec2( iuv.x + h0x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p3 = ( vec2( iuv.x + h1x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;\n\t\treturn g0( fuv.y ) * ( g0x * textureLod( tex, p0, lod ) + g1x * textureLod( tex, p1, lod ) ) +\n\t\t\tg1( fuv.y ) * ( g0x * textureLod( tex, p2, lod ) + g1x * textureLod( tex, p3, lod ) );\n\t}\n\tvec4 textureBicubic( sampler2D sampler, vec2 uv, float lod ) {\n\t\tvec2 fLodSize = vec2( textureSize( sampler, int( lod ) ) );\n\t\tvec2 cLodSize = vec2( textureSize( sampler, int( lod + 1.0 ) ) );\n\t\tvec2 fLodSizeInv = 1.0 / fLodSize;\n\t\tvec2 cLodSizeInv = 1.0 / cLodSize;\n\t\tvec4 fSample = bicubic( sampler, uv, vec4( fLodSizeInv, fLodSize ), floor( lod ) );\n\t\tvec4 cSample = bicubic( sampler, uv, vec4( cLodSizeInv, cLodSize ), ceil( lod ) );\n\t\treturn mix( fSample, cSample, fract( lod ) );\n\t}\n\tvec3 getVolumeTransmissionRay( const in vec3 n, const in vec3 v, const in float thickness, const in float ior, const in mat4 modelMatrix ) {\n\t\tvec3 refractionVector = refract( - v, normalize( n ), 1.0 / ior );\n\t\tvec3 modelScale;\n\t\tmodelScale.x = length( vec3( modelMatrix[ 0 ].xyz ) );\n\t\tmodelScale.y = length( vec3( modelMatrix[ 1 ].xyz ) );\n\t\tmodelScale.z = length( vec3( modelMatrix[ 2 ].xyz ) );\n\t\treturn normalize( refractionVector ) * thickness * modelScale;\n\t}\n\tfloat applyIorToRoughness( const in float roughness, const in float ior ) {\n\t\treturn roughness * clamp( ior * 2.0 - 2.0, 0.0, 1.0 );\n\t}\n\tvec4 getTransmissionSample( const in vec2 fragCoord, const in float roughness, const in float ior ) {\n\t\tfloat lod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior );\n\t\treturn textureBicubic( transmissionSamplerMap, fragCoord.xy, lod );\n\t}\n\tvec3 volumeAttenuation( const in float transmissionDistance, const in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tif ( isinf( attenuationDistance ) ) {\n\t\t\treturn vec3( 1.0 );\n\t\t} else {\n\t\t\tvec3 attenuationCoefficient = -log( attenuationColor ) / attenuationDistance;\n\t\t\tvec3 transmittance = exp( - attenuationCoefficient * transmissionDistance );\t\t\treturn transmittance;\n\t\t}\n\t}\n\tvec4 getIBLVolumeRefraction( const in vec3 n, const in vec3 v, const in float roughness, const in vec3 diffuseColor,\n\t\tconst in vec3 specularColor, const in float specularF90, const in vec3 position, const in mat4 modelMatrix,\n\t\tconst in mat4 viewMatrix, const in mat4 projMatrix, const in float ior, const in float thickness,\n\t\tconst in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tvec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix );\n\t\tvec3 refractedRayExit = position + transmissionRay;\n\t\tvec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n\t\tvec2 refractionCoords = ndcPos.xy / ndcPos.w;\n\t\trefractionCoords += 1.0;\n\t\trefractionCoords /= 2.0;\n\t\tvec4 transmittedLight = getTransmissionSample( refractionCoords, roughness, ior );\n\t\tvec3 transmittance = diffuseColor * volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance );\n\t\tvec3 attenuatedColor = transmittance * transmittedLight.rgb;\n\t\tvec3 F = EnvironmentBRDF( n, v, specularColor, specularF90, roughness );\n\t\tfloat transmittanceFactor = ( transmittance.r + transmittance.g + transmittance.b ) / 3.0;\n\t\treturn vec4( ( 1.0 - F ) * attenuatedColor, 1.0 - ( 1.0 - transmittedLight.a ) * transmittanceFactor );\n\t}\n#endif";
- translate: function ( offset ) {
+var uv_pars_fragment = "#if defined( USE_UV ) || defined( USE_ANISOTROPY )\n\tvarying vec2 vUv;\n#endif\n#ifdef USE_MAP\n\tvarying vec2 vMapUv;\n#endif\n#ifdef USE_ALPHAMAP\n\tvarying vec2 vAlphaMapUv;\n#endif\n#ifdef USE_LIGHTMAP\n\tvarying vec2 vLightMapUv;\n#endif\n#ifdef USE_AOMAP\n\tvarying vec2 vAoMapUv;\n#endif\n#ifdef USE_BUMPMAP\n\tvarying vec2 vBumpMapUv;\n#endif\n#ifdef USE_NORMALMAP\n\tvarying vec2 vNormalMapUv;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tvarying vec2 vEmissiveMapUv;\n#endif\n#ifdef USE_METALNESSMAP\n\tvarying vec2 vMetalnessMapUv;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tvarying vec2 vRoughnessMapUv;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tvarying vec2 vAnisotropyMapUv;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tvarying vec2 vClearcoatMapUv;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tvarying vec2 vClearcoatNormalMapUv;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tvarying vec2 vClearcoatRoughnessMapUv;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tvarying vec2 vIridescenceMapUv;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tvarying vec2 vIridescenceThicknessMapUv;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tvarying vec2 vSheenColorMapUv;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tvarying vec2 vSheenRoughnessMapUv;\n#endif\n#ifdef USE_SPECULARMAP\n\tvarying vec2 vSpecularMapUv;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tvarying vec2 vSpecularColorMapUv;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tvarying vec2 vSpecularIntensityMapUv;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tuniform mat3 transmissionMapTransform;\n\tvarying vec2 vTransmissionMapUv;\n#endif\n#ifdef USE_THICKNESSMAP\n\tuniform mat3 thicknessMapTransform;\n\tvarying vec2 vThicknessMapUv;\n#endif";
- this.constant -= offset.dot( this.normal );
+var uv_pars_vertex = "#if defined( USE_UV ) || defined( USE_ANISOTROPY )\n\tvarying vec2 vUv;\n#endif\n#ifdef USE_MAP\n\tuniform mat3 mapTransform;\n\tvarying vec2 vMapUv;\n#endif\n#ifdef USE_ALPHAMAP\n\tuniform mat3 alphaMapTransform;\n\tvarying vec2 vAlphaMapUv;\n#endif\n#ifdef USE_LIGHTMAP\n\tuniform mat3 lightMapTransform;\n\tvarying vec2 vLightMapUv;\n#endif\n#ifdef USE_AOMAP\n\tuniform mat3 aoMapTransform;\n\tvarying vec2 vAoMapUv;\n#endif\n#ifdef USE_BUMPMAP\n\tuniform mat3 bumpMapTransform;\n\tvarying vec2 vBumpMapUv;\n#endif\n#ifdef USE_NORMALMAP\n\tuniform mat3 normalMapTransform;\n\tvarying vec2 vNormalMapUv;\n#endif\n#ifdef USE_DISPLACEMENTMAP\n\tuniform mat3 displacementMapTransform;\n\tvarying vec2 vDisplacementMapUv;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tuniform mat3 emissiveMapTransform;\n\tvarying vec2 vEmissiveMapUv;\n#endif\n#ifdef USE_METALNESSMAP\n\tuniform mat3 metalnessMapTransform;\n\tvarying vec2 vMetalnessMapUv;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tuniform mat3 roughnessMapTransform;\n\tvarying vec2 vRoughnessMapUv;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tuniform mat3 anisotropyMapTransform;\n\tvarying vec2 vAnisotropyMapUv;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tuniform mat3 clearcoatMapTransform;\n\tvarying vec2 vClearcoatMapUv;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tuniform mat3 clearcoatNormalMapTransform;\n\tvarying vec2 vClearcoatNormalMapUv;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tuniform mat3 clearcoatRoughnessMapTransform;\n\tvarying vec2 vClearcoatRoughnessMapUv;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tuniform mat3 sheenColorMapTransform;\n\tvarying vec2 vSheenColorMapUv;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tuniform mat3 sheenRoughnessMapTransform;\n\tvarying vec2 vSheenRoughnessMapUv;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tuniform mat3 iridescenceMapTransform;\n\tvarying vec2 vIridescenceMapUv;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tuniform mat3 iridescenceThicknessMapTransform;\n\tvarying vec2 vIridescenceThicknessMapUv;\n#endif\n#ifdef USE_SPECULARMAP\n\tuniform mat3 specularMapTransform;\n\tvarying vec2 vSpecularMapUv;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tuniform mat3 specularColorMapTransform;\n\tvarying vec2 vSpecularColorMapUv;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tuniform mat3 specularIntensityMapTransform;\n\tvarying vec2 vSpecularIntensityMapUv;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tuniform mat3 transmissionMapTransform;\n\tvarying vec2 vTransmissionMapUv;\n#endif\n#ifdef USE_THICKNESSMAP\n\tuniform mat3 thicknessMapTransform;\n\tvarying vec2 vThicknessMapUv;\n#endif";
- return this;
+var uv_vertex = "#if defined( USE_UV ) || defined( USE_ANISOTROPY )\n\tvUv = vec3( uv, 1 ).xy;\n#endif\n#ifdef USE_MAP\n\tvMapUv = ( mapTransform * vec3( MAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ALPHAMAP\n\tvAlphaMapUv = ( alphaMapTransform * vec3( ALPHAMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_LIGHTMAP\n\tvLightMapUv = ( lightMapTransform * vec3( LIGHTMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_AOMAP\n\tvAoMapUv = ( aoMapTransform * vec3( AOMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_BUMPMAP\n\tvBumpMapUv = ( bumpMapTransform * vec3( BUMPMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_NORMALMAP\n\tvNormalMapUv = ( normalMapTransform * vec3( NORMALMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_DISPLACEMENTMAP\n\tvDisplacementMapUv = ( displacementMapTransform * vec3( DISPLACEMENTMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tvEmissiveMapUv = ( emissiveMapTransform * vec3( EMISSIVEMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_METALNESSMAP\n\tvMetalnessMapUv = ( metalnessMapTransform * vec3( METALNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tvRoughnessMapUv = ( roughnessMapTransform * vec3( ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tvAnisotropyMapUv = ( anisotropyMapTransform * vec3( ANISOTROPYMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tvClearcoatMapUv = ( clearcoatMapTransform * vec3( CLEARCOATMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tvClearcoatNormalMapUv = ( clearcoatNormalMapTransform * vec3( CLEARCOAT_NORMALMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tvClearcoatRoughnessMapUv = ( clearcoatRoughnessMapTransform * vec3( CLEARCOAT_ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tvIridescenceMapUv = ( iridescenceMapTransform * vec3( IRIDESCENCEMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tvIridescenceThicknessMapUv = ( iridescenceThicknessMapTransform * vec3( IRIDESCENCE_THICKNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tvSheenColorMapUv = ( sheenColorMapTransform * vec3( SHEEN_COLORMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tvSheenRoughnessMapUv = ( sheenRoughnessMapTransform * vec3( SHEEN_ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULARMAP\n\tvSpecularMapUv = ( specularMapTransform * vec3( SPECULARMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tvSpecularColorMapUv = ( specularColorMapTransform * vec3( SPECULAR_COLORMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tvSpecularIntensityMapUv = ( specularIntensityMapTransform * vec3( SPECULAR_INTENSITYMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tvTransmissionMapUv = ( transmissionMapTransform * vec3( TRANSMISSIONMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_THICKNESSMAP\n\tvThicknessMapUv = ( thicknessMapTransform * vec3( THICKNESSMAP_UV, 1 ) ).xy;\n#endif";
- },
+var worldpos_vertex = "#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP ) || defined ( USE_TRANSMISSION ) || NUM_SPOT_LIGHT_COORDS > 0\n\tvec4 worldPosition = vec4( transformed, 1.0 );\n\t#ifdef USE_INSTANCING\n\t\tworldPosition = instanceMatrix * worldPosition;\n\t#endif\n\tworldPosition = modelMatrix * worldPosition;\n#endif";
- equals: function ( plane ) {
+const vertex$h = "varying vec2 vUv;\nuniform mat3 uvTransform;\nvoid main() {\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\tgl_Position = vec4( position.xy, 1.0, 1.0 );\n}";
- return plane.normal.equals( this.normal ) && ( plane.constant === this.constant );
+const fragment$h = "uniform sampler2D t2D;\nuniform float backgroundIntensity;\nvarying vec2 vUv;\nvoid main() {\n\tvec4 texColor = texture2D( t2D, vUv );\n\t#ifdef DECODE_VIDEO_TEXTURE\n\t\ttexColor = vec4( mix( pow( texColor.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), texColor.rgb * 0.0773993808, vec3( lessThanEqual( texColor.rgb, vec3( 0.04045 ) ) ) ), texColor.w );\n\t#endif\n\ttexColor.rgb *= backgroundIntensity;\n\tgl_FragColor = texColor;\n\t#include \n\t#include \n}";
- }
+const vertex$g = "varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n\tgl_Position.z = gl_Position.w;\n}";
- } );
+const fragment$g = "#ifdef ENVMAP_TYPE_CUBE\n\tuniform samplerCube envMap;\n#elif defined( ENVMAP_TYPE_CUBE_UV )\n\tuniform sampler2D envMap;\n#endif\nuniform float flipEnvMap;\nuniform float backgroundBlurriness;\nuniform float backgroundIntensity;\nvarying vec3 vWorldDirection;\n#include \nvoid main() {\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 texColor = textureCube( envMap, vec3( flipEnvMap * vWorldDirection.x, vWorldDirection.yz ) );\n\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\tvec4 texColor = textureCubeUV( envMap, vWorldDirection, backgroundBlurriness );\n\t#else\n\t\tvec4 texColor = vec4( 0.0, 0.0, 0.0, 1.0 );\n\t#endif\n\ttexColor.rgb *= backgroundIntensity;\n\tgl_FragColor = texColor;\n\t#include \n\t#include \n}";
- /**
- * @author mrdoob / http://mrdoob.com/
- * @author alteredq / http://alteredqualia.com/
- * @author bhouston / http://clara.io
- */
+const vertex$f = "varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n\tgl_Position.z = gl_Position.w;\n}";
- var _sphere$1 = new Sphere();
- var _vector$5 = new Vector3();
+const fragment$f = "uniform samplerCube tCube;\nuniform float tFlip;\nuniform float opacity;\nvarying vec3 vWorldDirection;\nvoid main() {\n\tvec4 texColor = textureCube( tCube, vec3( tFlip * vWorldDirection.x, vWorldDirection.yz ) );\n\tgl_FragColor = texColor;\n\tgl_FragColor.a *= opacity;\n\t#include \n\t#include \n}";
- function Frustum( p0, p1, p2, p3, p4, p5 ) {
+const vertex$e = "#include \n#include \n#include \n#include \n#include \n#include \n#include \nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvHighPrecisionZW = gl_Position.zw;\n}";
- this.planes = [
+const fragment$e = "#if DEPTH_PACKING == 3200\n\tuniform float opacity;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( 1.0 );\n\t#if DEPTH_PACKING == 3200\n\t\tdiffuseColor.a = opacity;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tfloat fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5;\n\t#if DEPTH_PACKING == 3200\n\t\tgl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), opacity );\n\t#elif DEPTH_PACKING == 3201\n\t\tgl_FragColor = packDepthToRGBA( fragCoordZ );\n\t#endif\n}";
- ( p0 !== undefined ) ? p0 : new Plane(),
- ( p1 !== undefined ) ? p1 : new Plane(),
- ( p2 !== undefined ) ? p2 : new Plane(),
- ( p3 !== undefined ) ? p3 : new Plane(),
- ( p4 !== undefined ) ? p4 : new Plane(),
- ( p5 !== undefined ) ? p5 : new Plane()
+const vertex$d = "#define DISTANCE\nvarying vec3 vWorldPosition;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvWorldPosition = worldPosition.xyz;\n}";
- ];
+const fragment$d = "#define DISTANCE\nuniform vec3 referencePosition;\nuniform float nearDistance;\nuniform float farDistance;\nvarying vec3 vWorldPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main () {\n\t#include \n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include \n\t#include \n\t#include \n\t#include \n\tfloat dist = length( vWorldPosition - referencePosition );\n\tdist = ( dist - nearDistance ) / ( farDistance - nearDistance );\n\tdist = saturate( dist );\n\tgl_FragColor = packDepthToRGBA( dist );\n}";
- }
+const vertex$c = "varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n}";
- Object.assign( Frustum.prototype, {
+const fragment$c = "uniform sampler2D tEquirect;\nvarying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvec3 direction = normalize( vWorldDirection );\n\tvec2 sampleUV = equirectUv( direction );\n\tgl_FragColor = texture2D( tEquirect, sampleUV );\n\t#include \n\t#include \n}";
- set: function ( p0, p1, p2, p3, p4, p5 ) {
+const vertex$b = "uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvLineDistance = scale * lineDistance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}";
- var planes = this.planes;
+const fragment$b = "uniform vec3 diffuse;\nuniform float opacity;\nuniform float dashSize;\nuniform float totalSize;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}";
- planes[ 0 ].copy( p0 );
- planes[ 1 ].copy( p1 );
- planes[ 2 ].copy( p2 );
- planes[ 3 ].copy( p3 );
- planes[ 4 ].copy( p4 );
- planes[ 5 ].copy( p5 );
+const vertex$a = "#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#if defined ( USE_ENVMAP ) || defined ( USE_SKINNING )\n\t\t#include \n\t\t#include \n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}";
- return this;
+const fragment$a = "uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\n\t\treflectedLight.indirectDiffuse += lightMapTexel.rgb * lightMapIntensity * RECIPROCAL_PI;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include \n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}";
- },
+const vertex$9 = "#define LAMBERT\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n\t#include \n}";
- clone: function () {
+const fragment$9 = "#define LAMBERT\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include