diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 18065a6c86750a..b1c282bb069a94 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -14,7 +14,7 @@ http://jsfiddle.net/hw9rcLL8/ (dev) ##### Three.js version - [ ] Dev -- [ ] r85 +- [ ] r87 - [ ] ... ##### Browser diff --git a/README.md b/README.md index 99661674802220..83237cba34b10b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ three.js ======== +[![Gitter][gitter-badge]][gitter-badge-url] [![Latest NPM release][npm-badge]][npm-badge-url] [![License][license-badge]][license-badge-url] [![Dependencies][dependencies-badge]][dependencies-badge-url] @@ -18,14 +19,14 @@ The aim of the project is to create an easy to use, lightweight, 3D library. The ### Usage ### -Download the [minified library](http://threejs.org/build/three.min.js) and include it in your html. +Download the [minified library](http://threejs.org/build/three.min.js) and include it in your HTML, or install and import it as a [module](http://threejs.org/docs/#manual/introduction/Import-via-modules), Alternatively see [how to build the library yourself](https://github.com/mrdoob/three.js/wiki/Build-instructions). ```html ``` -This code creates a scene, a camera, and a geometric cube, and it adds the cube to the scene. It then creates a `WebGL` renderer for the scene and camera, and it adds that viewport to the document.body element. Finally it animates the cube within the scene for the camera. +This code creates a scene, a camera, and a geometric cube, and it adds the cube to the scene. It then creates a `WebGL` renderer for the scene and camera, and it adds that viewport to the document.body element. Finally, it animates the cube within the scene for the camera. ```javascript var scene, camera, renderer; @@ -66,14 +67,15 @@ function animate() { } ``` -If everything went well you should see [this](http://jsfiddle.net/hfj7gm6t/). +If everything went well you should see [this](https://jsfiddle.net/hfj7gm6t/). ### Change log ### [releases](https://github.com/mrdoob/three.js/releases) - +[gitter-badge]: https://badges.gitter.im/mrdoob/three.js.svg +[gitter-badge-url]: https://gitter.im/mrdoob/three.js [npm-badge]: https://img.shields.io/npm/v/three.svg [npm-badge-url]: https://www.npmjs.com/package/three [license-badge]: https://img.shields.io/npm/l/three.svg diff --git a/build/three.js b/build/three.js index 50057d723dbf7e..c727a2bbac5be7 100644 --- a/build/three.js +++ b/build/three.js @@ -173,16 +173,9 @@ event.target = this; - var array = [], i = 0; - var length = listenerArray.length; + var array = listenerArray.slice( 0 ); - for ( i = 0; i < length; i ++ ) { - - array[ i ] = listenerArray[ i ]; - - } - - for ( i = 0; i < length; i ++ ) { + for ( var i = 0, l = array.length; i < l; i ++ ) { array[ i ].call( this, event ); @@ -194,7 +187,7 @@ } ); - var REVISION = '86dev'; + var REVISION = '88dev'; var MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2 }; var CullFaceNone = 0; var CullFaceBack = 1; @@ -725,6 +718,18 @@ }, + applyMatrix3: function ( m ) { + + 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 ]; + + return this; + + }, + min: function ( v ) { this.x = Math.min( this.x, v.x ); @@ -745,7 +750,7 @@ clamp: function ( min, max ) { - // This function assumes min < max, if this assumption isn't true it will not operate correctly + // 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 ) ); @@ -774,7 +779,7 @@ var length = this.length(); - return this.multiplyScalar( Math.max( min, Math.min( max, length ) ) / length ); + return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) ); }, @@ -849,7 +854,7 @@ normalize: function () { - return this.divideScalar( this.length() ); + return this.divideScalar( this.length() || 1 ); }, @@ -886,7 +891,7 @@ setLength: function ( length ) { - return this.multiplyScalar( length / this.length() ); + return this.normalize().multiplyScalar( length ); }, @@ -967,867 +972,890 @@ /** * @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 szimek / https://github.com/szimek/ + * @author mikael emtinger / http://gomo.se/ + * @author timknip / http://www.floorplanner.com/ + * @author bhouston / http://clara.io + * @author WestLangley / http://github.com/WestLangley */ - var textureId = 0; + function Matrix4() { - function Texture( image, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ) { + this.elements = [ - Object.defineProperty( this, 'id', { value: textureId ++ } ); + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 - this.uuid = _Math.generateUUID(); + ]; - this.name = ''; + if ( arguments.length > 0 ) { - this.image = image !== undefined ? image : Texture.DEFAULT_IMAGE; - this.mipmaps = []; + console.error( 'THREE.Matrix4: the constructor no longer reads arguments. use .set() instead.' ); - this.mapping = mapping !== undefined ? mapping : Texture.DEFAULT_MAPPING; + } - this.wrapS = wrapS !== undefined ? wrapS : ClampToEdgeWrapping; - this.wrapT = wrapT !== undefined ? wrapT : ClampToEdgeWrapping; + } - this.magFilter = magFilter !== undefined ? magFilter : LinearFilter; - this.minFilter = minFilter !== undefined ? minFilter : LinearMipMapLinearFilter; + Object.assign( Matrix4.prototype, { - this.anisotropy = anisotropy !== undefined ? anisotropy : 1; + isMatrix4: true, - this.format = format !== undefined ? format : RGBAFormat; - this.type = type !== undefined ? type : UnsignedByteType; + set: function ( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) { - this.offset = new Vector2( 0, 0 ); - this.repeat = new Vector2( 1, 1 ); + var te = this.elements; - 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) + 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; - // 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; + return this; - this.version = 0; - this.onUpdate = null; + }, - } + identity: function () { - Texture.DEFAULT_IMAGE = undefined; - Texture.DEFAULT_MAPPING = UVMapping; + this.set( - Object.defineProperty( Texture.prototype, "needsUpdate", { + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 - set: function ( value ) { + ); - if ( value === true ) this.version ++; + return this; - } + }, - } ); + clone: function () { - Object.assign( Texture.prototype, EventDispatcher.prototype, { + return new Matrix4().fromArray( this.elements ); - constructor: Texture, + }, - isTexture: true, + copy: function ( m ) { - clone: function () { + var te = this.elements; + var me = m.elements; - return new this.constructor().copy( this ); + 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; }, - copy: function ( source ) { + copyPosition: function ( m ) { - this.name = source.name; + var te = this.elements, me = m.elements; - this.image = source.image; - this.mipmaps = source.mipmaps.slice( 0 ); + te[ 12 ] = me[ 12 ]; + te[ 13 ] = me[ 13 ]; + te[ 14 ] = me[ 14 ]; - this.mapping = source.mapping; + return this; - this.wrapS = source.wrapS; - this.wrapT = source.wrapT; + }, - this.magFilter = source.magFilter; - this.minFilter = source.minFilter; + extractBasis: function ( xAxis, yAxis, zAxis ) { - this.anisotropy = source.anisotropy; + xAxis.setFromMatrixColumn( this, 0 ); + yAxis.setFromMatrixColumn( this, 1 ); + zAxis.setFromMatrixColumn( this, 2 ); - this.format = source.format; - this.type = source.type; + return this; - this.offset.copy( source.offset ); - this.repeat.copy( source.repeat ); + }, - this.generateMipmaps = source.generateMipmaps; - this.premultiplyAlpha = source.premultiplyAlpha; - this.flipY = source.flipY; - this.unpackAlignment = source.unpackAlignment; - this.encoding = source.encoding; + makeBasis: function ( xAxis, yAxis, zAxis ) { + + 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; }, - toJSON: function ( meta ) { + extractRotation: function () { - if ( meta.textures[ this.uuid ] !== undefined ) { + var v1 = new Vector3(); - return meta.textures[ this.uuid ]; + return function extractRotation( m ) { - } + var te = this.elements; + var me = m.elements; - function getDataURL( image ) { + var scaleX = 1 / v1.setFromMatrixColumn( m, 0 ).length(); + var scaleY = 1 / v1.setFromMatrixColumn( m, 1 ).length(); + var scaleZ = 1 / v1.setFromMatrixColumn( m, 2 ).length(); - var canvas; + te[ 0 ] = me[ 0 ] * scaleX; + te[ 1 ] = me[ 1 ] * scaleX; + te[ 2 ] = me[ 2 ] * scaleX; - if ( image.toDataURL !== undefined ) { + te[ 4 ] = me[ 4 ] * scaleY; + te[ 5 ] = me[ 5 ] * scaleY; + te[ 6 ] = me[ 6 ] * scaleY; - canvas = image; + te[ 8 ] = me[ 8 ] * scaleZ; + te[ 9 ] = me[ 9 ] * scaleZ; + te[ 10 ] = me[ 10 ] * scaleZ; - } else { + return this; - canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' ); - canvas.width = image.width; - canvas.height = image.height; + }; - canvas.getContext( '2d' ).drawImage( image, 0, 0, image.width, image.height ); + }(), - } + makeRotationFromEuler: function ( euler ) { - if ( canvas.width > 2048 || canvas.height > 2048 ) { + if ( ! ( euler && euler.isEuler ) ) { - return canvas.toDataURL( 'image/jpeg', 0.6 ); + console.error( 'THREE.Matrix4: .makeRotationFromEuler() now expects a Euler rotation rather than a Vector3 and order.' ); - } else { + } - return canvas.toDataURL( 'image/png' ); + var te = this.elements; - } + 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 ); - } + if ( euler.order === 'XYZ' ) { - var output = { - metadata: { - version: 4.5, - type: 'Texture', - generator: 'Texture.toJSON' - }, + var ae = a * e, af = a * f, be = b * e, bf = b * f; - uuid: this.uuid, - name: this.name, + te[ 0 ] = c * e; + te[ 4 ] = - c * f; + te[ 8 ] = d; - mapping: this.mapping, + te[ 1 ] = af + be * d; + te[ 5 ] = ae - bf * d; + te[ 9 ] = - b * c; - repeat: [ this.repeat.x, this.repeat.y ], - offset: [ this.offset.x, this.offset.y ], - wrap: [ this.wrapS, this.wrapT ], + te[ 2 ] = bf - ae * d; + te[ 6 ] = be + af * d; + te[ 10 ] = a * c; - minFilter: this.minFilter, - magFilter: this.magFilter, - anisotropy: this.anisotropy, + } else if ( euler.order === 'YXZ' ) { - flipY: this.flipY - }; + var ce = c * e, cf = c * f, de = d * e, df = d * f; - if ( this.image !== undefined ) { + te[ 0 ] = ce + df * b; + te[ 4 ] = de * b - cf; + te[ 8 ] = a * d; - // TODO: Move to THREE.Image + te[ 1 ] = a * f; + te[ 5 ] = a * e; + te[ 9 ] = - b; - var image = this.image; + te[ 2 ] = cf * b - de; + te[ 6 ] = df + ce * b; + te[ 10 ] = a * c; - if ( image.uuid === undefined ) { + } else if ( euler.order === 'ZXY' ) { - image.uuid = _Math.generateUUID(); // UGH + var ce = c * e, cf = c * f, de = d * e, df = d * f; - } + te[ 0 ] = ce - df * b; + te[ 4 ] = - a * f; + te[ 8 ] = de + cf * b; - if ( meta.images[ image.uuid ] === undefined ) { + te[ 1 ] = cf + de * b; + te[ 5 ] = a * e; + te[ 9 ] = df - ce * b; - meta.images[ image.uuid ] = { - uuid: image.uuid, - url: getDataURL( image ) - }; + te[ 2 ] = - a * d; + te[ 6 ] = b; + te[ 10 ] = a * c; - } + } else if ( euler.order === 'ZYX' ) { - output.image = image.uuid; + var ae = a * e, af = a * f, be = b * e, bf = b * f; - } + te[ 0 ] = c * e; + te[ 4 ] = be * d - af; + te[ 8 ] = ae * d + bf; - meta.textures[ this.uuid ] = output; + te[ 1 ] = c * f; + te[ 5 ] = bf * d + ae; + te[ 9 ] = af * d - be; - return output; + te[ 2 ] = - d; + te[ 6 ] = b * c; + te[ 10 ] = a * c; - }, + } else if ( euler.order === 'YZX' ) { - dispose: function () { + var ac = a * c, ad = a * d, bc = b * c, bd = b * d; - this.dispatchEvent( { type: 'dispose' } ); + te[ 0 ] = c * e; + te[ 4 ] = bd - ac * f; + te[ 8 ] = bc * f + ad; - }, + te[ 1 ] = f; + te[ 5 ] = a * e; + te[ 9 ] = - b * e; - transformUv: function ( uv ) { + te[ 2 ] = - d * e; + te[ 6 ] = ad * f + bc; + te[ 10 ] = ac - bd * f; - if ( this.mapping !== UVMapping ) return; + } else if ( euler.order === 'XZY' ) { - uv.multiply( this.repeat ); - uv.add( this.offset ); + var ac = a * c, ad = a * d, bc = b * c, bd = b * d; - if ( uv.x < 0 || uv.x > 1 ) { + te[ 0 ] = c * e; + te[ 4 ] = - f; + te[ 8 ] = d * e; - switch ( this.wrapS ) { + te[ 1 ] = ac * f + bd; + te[ 5 ] = a * e; + te[ 9 ] = ad * f - bc; - case RepeatWrapping: + te[ 2 ] = bc * f - ad; + te[ 6 ] = b * e; + te[ 10 ] = bd * f + ac; - uv.x = uv.x - Math.floor( uv.x ); - break; + } - case ClampToEdgeWrapping: + // last column + te[ 3 ] = 0; + te[ 7 ] = 0; + te[ 11 ] = 0; - uv.x = uv.x < 0 ? 0 : 1; - break; + // bottom row + te[ 12 ] = 0; + te[ 13 ] = 0; + te[ 14 ] = 0; + te[ 15 ] = 1; - case MirroredRepeatWrapping: + return this; - if ( Math.abs( Math.floor( uv.x ) % 2 ) === 1 ) { + }, - uv.x = Math.ceil( uv.x ) - uv.x; + makeRotationFromQuaternion: function ( q ) { - } else { + var te = this.elements; - uv.x = uv.x - Math.floor( uv.x ); + var x = q._x, y = q._y, z = q._z, w = q._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; - } - break; + te[ 0 ] = 1 - ( yy + zz ); + te[ 4 ] = xy - wz; + te[ 8 ] = xz + wy; - } + te[ 1 ] = xy + wz; + te[ 5 ] = 1 - ( xx + zz ); + te[ 9 ] = yz - wx; - } + te[ 2 ] = xz - wy; + te[ 6 ] = yz + wx; + te[ 10 ] = 1 - ( xx + yy ); - if ( uv.y < 0 || uv.y > 1 ) { + // last column + te[ 3 ] = 0; + te[ 7 ] = 0; + te[ 11 ] = 0; - switch ( this.wrapT ) { + // bottom row + te[ 12 ] = 0; + te[ 13 ] = 0; + te[ 14 ] = 0; + te[ 15 ] = 1; - case RepeatWrapping: + return this; - uv.y = uv.y - Math.floor( uv.y ); - break; + }, - case ClampToEdgeWrapping: + lookAt: function () { - uv.y = uv.y < 0 ? 0 : 1; - break; + var x = new Vector3(); + var y = new Vector3(); + var z = new Vector3(); - case MirroredRepeatWrapping: + return function lookAt( eye, target, up ) { - if ( Math.abs( Math.floor( uv.y ) % 2 ) === 1 ) { + var te = this.elements; - uv.y = Math.ceil( uv.y ) - uv.y; + z.subVectors( eye, target ); - } else { + if ( z.lengthSq() === 0 ) { - uv.y = uv.y - Math.floor( uv.y ); + // eye and target are in the same position - } - break; + z.z = 1; } - } + z.normalize(); + x.crossVectors( up, z ); - if ( this.flipY ) { + if ( x.lengthSq() === 0 ) { - uv.y = 1 - uv.y; + // up and z are parallel - } + if ( Math.abs( up.z ) === 1 ) { - } + z.x += 0.0001; - } ); + } else { - /** - * @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 - */ + z.z += 0.0001; - function Vector4( x, y, z, w ) { + } - this.x = x || 0; - this.y = y || 0; - this.z = z || 0; - this.w = ( w !== undefined ) ? w : 1; + z.normalize(); + x.crossVectors( up, z ); - } + } - Object.assign( Vector4.prototype, { + x.normalize(); + y.crossVectors( z, x ); - isVector4: true, + 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; - set: function ( x, y, z, w ) { + return this; - this.x = x; - this.y = y; - this.z = z; - this.w = w; + }; - return this; + }(), - }, + multiply: function ( m, n ) { - setScalar: function ( scalar ) { + if ( n !== undefined ) { - this.x = scalar; - this.y = scalar; - this.z = scalar; - this.w = scalar; + console.warn( 'THREE.Matrix4: .multiply() now only accepts one argument. Use .multiplyMatrices( a, b ) instead.' ); + return this.multiplyMatrices( m, n ); - return this; + } - }, + return this.multiplyMatrices( this, m ); - setX: function ( x ) { + }, - this.x = x; + premultiply: function ( m ) { - return this; + return this.multiplyMatrices( m, this ); }, - setY: function ( y ) { - - this.y = y; - - return this; + multiplyMatrices: function ( a, b ) { - }, + var ae = a.elements; + var be = b.elements; + var te = this.elements; - setZ: function ( z ) { + 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 ]; - this.z = z; + 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 ]; - return this; + 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; - }, + 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; - setW: function ( w ) { + 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; - this.w = w; + 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; }, - setComponent: function ( index, value ) { - - switch ( index ) { + multiplyScalar: function ( s ) { - 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 ); + var 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; }, - getComponent: function ( index ) { + applyToBufferAttribute: function () { - switch ( index ) { + var v1 = new Vector3(); - 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 ); + return function applyToBufferAttribute( attribute ) { - } + for ( var i = 0, l = attribute.count; i < l; i ++ ) { - }, + v1.x = attribute.getX( i ); + v1.y = attribute.getY( i ); + v1.z = attribute.getZ( i ); - clone: function () { + v1.applyMatrix4( this ); - return new this.constructor( this.x, this.y, this.z, this.w ); - - }, + attribute.setXYZ( i, v1.x, v1.y, v1.z ); - copy: function ( v ) { + } - this.x = v.x; - this.y = v.y; - this.z = v.z; - this.w = ( v.w !== undefined ) ? v.w : 1; + return attribute; - return this; + }; - }, + }(), - add: function ( v, w ) { + determinant: function () { - if ( w !== undefined ) { + var te = this.elements; - console.warn( 'THREE.Vector4: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' ); - return this.addVectors( v, w ); + 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 ) - this.x += v.x; - this.y += v.y; - this.z += v.z; - this.w += v.w; + 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; + ); }, - addScalar: function ( s ) { - - this.x += s; - this.y += s; - this.z += s; - this.w += s; - - return this; + transpose: function () { - }, + var te = this.elements; + var tmp; - addVectors: function ( a, b ) { + 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; - this.x = a.x + b.x; - this.y = a.y + b.y; - this.z = a.z + b.z; - this.w = a.w + b.w; + 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; return this; }, - addScaledVector: function ( v, s ) { + setPosition: function ( v ) { - this.x += v.x * s; - this.y += v.y * s; - this.z += v.z * s; - this.w += v.w * s; + var te = this.elements; + + te[ 12 ] = v.x; + te[ 13 ] = v.y; + te[ 14 ] = v.z; return this; }, - sub: function ( v, w ) { + getInverse: function ( m, throwOnDegenerate ) { - if ( w !== undefined ) { + // based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm + var te = this.elements, + me = m.elements, - console.warn( 'THREE.Vector4: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' ); - return this.subVectors( v, w ); + 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 ], - } + 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; - this.x -= v.x; - this.y -= v.y; - this.z -= v.z; - this.w -= v.w; + var det = n11 * t11 + n21 * t12 + n31 * t13 + n41 * t14; - return this; + if ( det === 0 ) { - }, + var msg = "THREE.Matrix4: .getInverse() can't invert matrix, determinant is 0"; - subScalar: function ( s ) { + if ( throwOnDegenerate === true ) { - this.x -= s; - this.y -= s; - this.z -= s; - this.w -= s; + throw new Error( msg ); - return this; + } else { - }, + console.warn( msg ); - subVectors: function ( a, b ) { + } - 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(); - return this; + } - }, + var detInv = 1 / det; - multiplyScalar: function ( scalar ) { + 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; - this.x *= scalar; - this.y *= scalar; - this.z *= scalar; - this.w *= scalar; + 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; + + 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; + + 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; }, - applyMatrix4: function ( m ) { + scale: function ( v ) { - var x = this.x, y = this.y, z = this.z, w = this.w; - var e = m.elements; + var te = this.elements; + var x = v.x, y = v.y, z = v.z; - 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; + 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; return this; }, - divideScalar: function ( scalar ) { - - return this.multiplyScalar( 1 / scalar ); - - }, - - setAxisAngleFromQuaternion: function ( q ) { - - // http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm + getMaxScaleOnAxis: function () { - // q is assumed to be normalized + var te = this.elements; - this.w = 2 * Math.acos( q.w ); + 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 ]; - var s = Math.sqrt( 1 - q.w * q.w ); + return Math.sqrt( Math.max( scaleXSq, scaleYSq, scaleZSq ) ); - if ( s < 0.0001 ) { + }, - this.x = 1; - this.y = 0; - this.z = 0; + makeTranslation: function ( x, y, z ) { - } else { + this.set( - this.x = q.x / s; - this.y = q.y / s; - this.z = q.z / s; + 1, 0, 0, x, + 0, 1, 0, y, + 0, 0, 1, z, + 0, 0, 0, 1 - } + ); return this; }, - setAxisAngleFromRotationMatrix: function ( m ) { - - // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm - - // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) - - 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 - - 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 ]; - - if ( ( Math.abs( m12 - m21 ) < epsilon ) && - ( Math.abs( m13 - m31 ) < epsilon ) && - ( Math.abs( m23 - m32 ) < epsilon ) ) { - - // singularity found - // first check for identity matrix which must have +1 for all terms - // in leading diagonal and zero in other terms + makeRotationX: function ( theta ) { - if ( ( Math.abs( m12 + m21 ) < epsilon2 ) && - ( Math.abs( m13 + m31 ) < epsilon2 ) && - ( Math.abs( m23 + m32 ) < epsilon2 ) && - ( Math.abs( m11 + m22 + m33 - 3 ) < epsilon2 ) ) { + var c = Math.cos( theta ), s = Math.sin( theta ); - // this singularity is identity matrix so angle = 0 + this.set( - this.set( 1, 0, 0, 0 ); + 1, 0, 0, 0, + 0, c, - s, 0, + 0, s, c, 0, + 0, 0, 0, 1 - return this; // zero angle, arbitrary axis + ); - } + return this; - // otherwise this singularity is angle = 180 + }, - angle = Math.PI; + makeRotationY: function ( theta ) { - 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; + var c = Math.cos( theta ), s = Math.sin( theta ); - if ( ( xx > yy ) && ( xx > zz ) ) { + this.set( - // m11 is the largest diagonal term + c, 0, s, 0, + 0, 1, 0, 0, + - s, 0, c, 0, + 0, 0, 0, 1 - if ( xx < epsilon ) { + ); - x = 0; - y = 0.707106781; - z = 0.707106781; + return this; - } else { + }, - x = Math.sqrt( xx ); - y = xy / x; - z = xz / x; + makeRotationZ: function ( theta ) { - } + var c = Math.cos( theta ), s = Math.sin( theta ); - } else if ( yy > zz ) { + this.set( - // m22 is the largest diagonal term + c, - s, 0, 0, + s, c, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 - if ( yy < epsilon ) { + ); - x = 0.707106781; - y = 0; - z = 0.707106781; + return this; - } else { + }, - y = Math.sqrt( yy ); - x = xy / y; - z = yz / y; + makeRotationAxis: function ( axis, angle ) { - } + // Based on http://www.gamedev.net/reference/articles/article1199.asp - } else { + 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; - // m33 is the largest diagonal term so base result on this + this.set( - if ( zz < epsilon ) { + 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 - x = 0.707106781; - y = 0.707106781; - z = 0; + ); - } else { + return this; - z = Math.sqrt( zz ); - x = xz / z; - y = yz / z; + }, - } + makeScale: function ( x, y, z ) { - } + this.set( - this.set( x, y, z, angle ); + x, 0, 0, 0, + 0, y, 0, 0, + 0, 0, z, 0, + 0, 0, 0, 1 - return this; // return 180 deg rotation + ); - } + return this; - // as we have reached here there are no singularities so we can handle normally + }, - var s = Math.sqrt( ( m32 - m23 ) * ( m32 - m23 ) + - ( m13 - m31 ) * ( m13 - m31 ) + - ( m21 - m12 ) * ( m21 - m12 ) ); // used to normalize + makeShear: function ( x, y, z ) { - if ( Math.abs( s ) < 0.001 ) s = 1; + this.set( - // 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 + 1, y, z, 0, + x, 1, z, 0, + x, y, 1, 0, + 0, 0, 0, 1 - 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; }, - min: function ( v ) { + compose: function ( position, quaternion, scale ) { - 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 ); + this.makeRotationFromQuaternion( quaternion ); + this.scale( scale ); + this.setPosition( position ); return this; }, - max: function ( v ) { + decompose: function () { - 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 ); + var vector = new Vector3(); + var matrix = new Matrix4(); - return this; + return function decompose( position, quaternion, scale ) { - }, + var te = this.elements; - clamp: function ( min, max ) { + var sx = vector.set( te[ 0 ], te[ 1 ], te[ 2 ] ).length(); + var sy = vector.set( te[ 4 ], te[ 5 ], te[ 6 ] ).length(); + var sz = vector.set( te[ 8 ], te[ 9 ], te[ 10 ] ).length(); - // This function assumes min < max, if this assumption isn't true it will not operate correctly + // if determine is negative, we need to invert one scale + var det = this.determinant(); + if ( det < 0 ) sx = - sx; - 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 ) ); + position.x = te[ 12 ]; + position.y = te[ 13 ]; + position.z = te[ 14 ]; - return this; + // scale the rotation part + matrix.copy( this ); - }, + var invSX = 1 / sx; + var invSY = 1 / sy; + var invSZ = 1 / sz; - clampScalar: function () { + matrix.elements[ 0 ] *= invSX; + matrix.elements[ 1 ] *= invSX; + matrix.elements[ 2 ] *= invSX; + + matrix.elements[ 4 ] *= invSY; + matrix.elements[ 5 ] *= invSY; + matrix.elements[ 6 ] *= invSY; - var min = new Vector4(); - var max = new Vector4(); + matrix.elements[ 8 ] *= invSZ; + matrix.elements[ 9 ] *= invSZ; + matrix.elements[ 10 ] *= invSZ; - return function clampScalar( minVal, maxVal ) { + quaternion.setFromRotationMatrix( matrix ); - min.set( minVal, minVal, minVal, minVal ); - max.set( maxVal, maxVal, maxVal, maxVal ); + scale.x = sx; + scale.y = sy; + scale.z = sz; - return this.clamp( min, max ); + return this; }; }(), - floor: function () { + makePerspective: function ( left, right, top, bottom, near, far ) { - this.x = Math.floor( this.x ); - this.y = Math.floor( this.y ); - this.z = Math.floor( this.z ); - this.w = Math.floor( this.w ); + if ( far === undefined ) { - return this; + console.warn( 'THREE.Matrix4: .makePerspective() has been redefined and has a new signature. Please check the docs.' ); - }, + } - ceil: function () { + var te = this.elements; + var x = 2 * near / ( right - left ); + var y = 2 * near / ( top - bottom ); - this.x = Math.ceil( this.x ); - this.y = Math.ceil( this.y ); - this.z = Math.ceil( this.z ); - this.w = Math.ceil( this.w ); + 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 ); + + 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; return this; }, - 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 ); - - return this; + makeOrthographic: function ( left, right, top, bottom, near, far ) { - }, + var te = this.elements; + var w = 1.0 / ( right - left ); + var h = 1.0 / ( top - bottom ); + var p = 1.0 / ( far - near ); - roundToZero: function () { + var x = ( right + left ) * w; + var y = ( top + bottom ) * h; + var z = ( far + near ) * p; - 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 ); + 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; }, - negate: function () { + equals: function ( matrix ) { - this.x = - this.x; - this.y = - this.y; - this.z = - this.z; - this.w = - this.w; + var te = this.elements; + var me = matrix.elements; - return this; + for ( var i = 0; i < 16; i ++ ) { - }, + if ( te[ i ] !== me[ i ] ) return false; - dot: function ( v ) { + } - return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w; + return true; }, - lengthSq: function () { + fromArray: function ( array, offset ) { - return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w; + if ( offset === undefined ) offset = 0; - }, + for ( var i = 0; i < 16; i ++ ) { - length: function () { + this.elements[ i ] = array[ i + offset ]; - return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w ); - - }, - - lengthManhattan: function () { - - return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ) + Math.abs( this.w ); - - }, - - normalize: function () { - - return this.divideScalar( this.length() ); - - }, - - setLength: function ( length ) { - - return this.multiplyScalar( length / this.length() ); - - }, - - lerp: function ( v, alpha ) { - - 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: function ( v1, v2, alpha ) { - - return this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 ); - - }, - - equals: function ( v ) { - - return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) && ( v.w === this.w ) ); - - }, - - fromArray: function ( array, offset ) { - - if ( offset === undefined ) offset = 0; - - this.x = array[ offset ]; - this.y = array[ offset + 1 ]; - this.z = array[ offset + 2 ]; - this.w = array[ offset + 3 ]; - - return this; + } + + return this; }, @@ -1836,138 +1864,34 @@ if ( array === undefined ) array = []; if ( offset === undefined ) offset = 0; - array[ offset ] = this.x; - array[ offset + 1 ] = this.y; - array[ offset + 2 ] = this.z; - array[ offset + 3 ] = this.w; - - return array; - - }, - - fromBufferAttribute: function ( attribute, index, offset ) { - - if ( offset !== undefined ) { - - console.warn( 'THREE.Vector4: offset has been removed from .fromBufferAttribute().' ); - - } - - this.x = attribute.getX( index ); - this.y = attribute.getY( index ); - this.z = attribute.getZ( index ); - this.w = attribute.getW( index ); - - return this; - - } - - } ); - - /** - * @author szimek / https://github.com/szimek/ - * @author alteredq / http://alteredqualia.com/ - * @author Marius Kintel / https://github.com/kintel - */ - - /* - 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 ) { - - this.uuid = _Math.generateUUID(); - - this.width = width; - this.height = height; - - this.scissor = new Vector4( 0, 0, width, height ); - this.scissorTest = false; - - this.viewport = new Vector4( 0, 0, width, height ); - - options = options || {}; - - if ( options.minFilter === undefined ) options.minFilter = LinearFilter; - - this.texture = new Texture( undefined, undefined, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding ); - - this.depthBuffer = options.depthBuffer !== undefined ? options.depthBuffer : true; - this.stencilBuffer = options.stencilBuffer !== undefined ? options.stencilBuffer : true; - this.depthTexture = options.depthTexture !== undefined ? options.depthTexture : null; - - } - - Object.assign( WebGLRenderTarget.prototype, EventDispatcher.prototype, { - - isWebGLRenderTarget: true, - - setSize: function ( width, height ) { - - if ( this.width !== width || this.height !== height ) { - - this.width = width; - this.height = height; - - this.dispose(); - - } - - this.viewport.set( 0, 0, width, height ); - this.scissor.set( 0, 0, width, height ); - - }, - - clone: function () { - - return new this.constructor().copy( this ); - - }, - - copy: function ( source ) { - - this.width = source.width; - this.height = source.height; - - this.viewport.copy( source.viewport ); - - this.texture = source.texture.clone(); + var te = this.elements; - this.depthBuffer = source.depthBuffer; - this.stencilBuffer = source.stencilBuffer; - this.depthTexture = source.depthTexture; + array[ offset ] = te[ 0 ]; + array[ offset + 1 ] = te[ 1 ]; + array[ offset + 2 ] = te[ 2 ]; + array[ offset + 3 ] = te[ 3 ]; - return this; + 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 ]; + array[ offset + 9 ] = te[ 9 ]; + array[ offset + 10 ] = te[ 10 ]; + array[ offset + 11 ] = te[ 11 ]; - dispose: function () { + array[ offset + 12 ] = te[ 12 ]; + array[ offset + 13 ] = te[ 13 ]; + array[ offset + 14 ] = te[ 14 ]; + array[ offset + 15 ] = te[ 15 ]; - this.dispatchEvent( { type: 'dispose' } ); + return array; } } ); - /** - * @author alteredq / http://alteredqualia.com - */ - - function WebGLRenderTargetCube( width, height, options ) { - - WebGLRenderTarget.call( this, width, height, options ); - - this.activeCubeFace = 0; // PX 0, NX 1, PY 2, NY 3, PZ 4, NZ 5 - this.activeMipMapLevel = 0; - - } - - WebGLRenderTargetCube.prototype = Object.create( WebGLRenderTarget.prototype ); - WebGLRenderTargetCube.prototype.constructor = WebGLRenderTargetCube; - - WebGLRenderTargetCube.prototype.isWebGLRenderTargetCube = true; - /** * @author mikael emtinger / http://gomo.se/ * @author alteredq / http://alteredqualia.com/ @@ -2164,7 +2088,7 @@ setFromEuler: function ( euler, update ) { - if ( ( euler && euler.isEuler ) === false ) { + if ( ! ( euler && euler.isEuler ) ) { throw new Error( 'THREE.Quaternion: .setFromEuler() now expects an Euler rotation rather than a Vector3 and order.' ); @@ -2576,7 +2500,7 @@ /** * @author mrdoob / http://mrdoob.com/ - * @author *kile / http://kile.stravaganza.org/ + * @author kile / http://kile.stravaganza.org/ * @author philogb / http://blog.thejit.org/ * @author mikael emtinger / http://gomo.se/ * @author egraether / http://egraether.com/ @@ -2810,7 +2734,7 @@ return function applyEuler( euler ) { - if ( ( euler && euler.isEuler ) === false ) { + if ( ! ( euler && euler.isEuler ) ) { console.error( 'THREE.Vector3: .applyEuler() now expects an Euler rotation rather than a Vector3 and order.' ); @@ -2852,12 +2776,13 @@ var x = this.x, y = this.y, z = this.z; var e = m.elements; - this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ]; - this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ]; - this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ]; - var w = e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ]; + 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.divideScalar( w ); + return this; }, @@ -2963,7 +2888,7 @@ clamp: function ( min, max ) { - // This function assumes min < max, if this assumption isn't true it will not operate correctly + // 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 ) ); @@ -2993,7 +2918,7 @@ var length = this.length(); - return this.multiplyScalar( Math.max( min, Math.min( max, length ) ) / length ); + return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) ); }, @@ -3075,13 +3000,13 @@ normalize: function () { - return this.divideScalar( this.length() ); + return this.divideScalar( this.length() || 1 ); }, setLength: function ( length ) { - return this.multiplyScalar( length / this.length() ); + return this.normalize().multiplyScalar( length ); }, @@ -3224,7 +3149,13 @@ setFromMatrixPosition: function ( m ) { - return this.setFromMatrixColumn( m, 3 ); + var e = m.elements; + + this.x = e[ 12 ]; + this.y = e[ 13 ]; + this.z = e[ 14 ]; + + return this; }, @@ -3244,7 +3175,6 @@ setFromMatrixColumn: function ( m, index ) { - return this.fromArray( m.elements, index * 4 ); }, @@ -3299,49 +3229,41 @@ } ); /** - * @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 + * @author bhouston / http://clara.io + * @author tschw */ - function Matrix4() { + function Matrix3() { this.elements = [ - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1 + 1, 0, 0, + 0, 1, 0, + 0, 0, 1 ]; if ( arguments.length > 0 ) { - console.error( 'THREE.Matrix4: the constructor no longer reads arguments. use .set() instead.' ); + console.error( 'THREE.Matrix3: the constructor no longer reads arguments. use .set() instead.' ); } } - Object.assign( Matrix4.prototype, { + Object.assign( Matrix3.prototype, { - isMatrix4: true, + isMatrix3: true, - set: function ( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) { + set: function ( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) { 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; + 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; @@ -3351,10 +3273,9 @@ this.set( - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1 + 1, 0, 0, + 0, 1, 0, + 0, 0, 1 ); @@ -3364,7 +3285,7 @@ clone: function () { - return new Matrix4().fromArray( this.elements ); + return new this.constructor().fromArray( this.elements ); }, @@ -3373,842 +3294,1359 @@ var te = this.elements; var me = m.elements; - 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; - - }, - - copyPosition: function ( m ) { - - var te = this.elements, me = m.elements; - - te[ 12 ] = me[ 12 ]; - te[ 13 ] = me[ 13 ]; - te[ 14 ] = me[ 14 ]; + 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; }, - extractBasis: function ( xAxis, yAxis, zAxis ) { - - xAxis.setFromMatrixColumn( this, 0 ); - yAxis.setFromMatrixColumn( this, 1 ); - zAxis.setFromMatrixColumn( this, 2 ); + setFromMatrix4: function ( m ) { - return this; + var me = m.elements; - }, + this.set( - makeBasis: function ( xAxis, yAxis, zAxis ) { + me[ 0 ], me[ 4 ], me[ 8 ], + me[ 1 ], me[ 5 ], me[ 9 ], + me[ 2 ], me[ 6 ], me[ 10 ] - 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; }, - extractRotation: function () { + applyToBufferAttribute: function () { var v1 = new Vector3(); - return function extractRotation( m ) { + return function applyToBufferAttribute( attribute ) { - var te = this.elements; - var me = m.elements; + for ( var i = 0, l = attribute.count; i < l; i ++ ) { - var scaleX = 1 / v1.setFromMatrixColumn( m, 0 ).length(); - var scaleY = 1 / v1.setFromMatrixColumn( m, 1 ).length(); - var scaleZ = 1 / v1.setFromMatrixColumn( m, 2 ).length(); + v1.x = attribute.getX( i ); + v1.y = attribute.getY( i ); + v1.z = attribute.getZ( i ); - te[ 0 ] = me[ 0 ] * scaleX; - te[ 1 ] = me[ 1 ] * scaleX; - te[ 2 ] = me[ 2 ] * scaleX; + v1.applyMatrix3( this ); - te[ 4 ] = me[ 4 ] * scaleY; - te[ 5 ] = me[ 5 ] * scaleY; - te[ 6 ] = me[ 6 ] * scaleY; + attribute.setXYZ( i, v1.x, v1.y, v1.z ); - te[ 8 ] = me[ 8 ] * scaleZ; - te[ 9 ] = me[ 9 ] * scaleZ; - te[ 10 ] = me[ 10 ] * scaleZ; + } - return this; + return attribute; }; }(), - makeRotationFromEuler: function ( euler ) { - - if ( ( euler && euler.isEuler ) === false ) { - - console.error( 'THREE.Matrix: .makeRotationFromEuler() now expects a Euler rotation rather than a Vector3 and order.' ); - - } + multiply: function ( m ) { - var te = this.elements; + return this.multiplyMatrices( this, m ); - 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 ); + }, - if ( euler.order === 'XYZ' ) { + premultiply: function ( m ) { - var ae = a * e, af = a * f, be = b * e, bf = b * f; + return this.multiplyMatrices( m, this ); - 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; + multiplyMatrices: function ( a, b ) { - te[ 2 ] = bf - ae * d; - te[ 6 ] = be + af * d; - te[ 10 ] = a * c; + var ae = a.elements; + var be = b.elements; + var te = this.elements; - } else if ( euler.order === 'YXZ' ) { + 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 ]; - var ce = c * e, cf = c * f, de = d * e, df = d * f; + 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 ]; - te[ 0 ] = ce + df * b; - te[ 4 ] = de * b - cf; - te[ 8 ] = a * d; + te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31; + te[ 3 ] = a11 * b12 + a12 * b22 + a13 * b32; + te[ 6 ] = a11 * b13 + a12 * b23 + a13 * b33; - te[ 1 ] = a * f; - te[ 5 ] = a * e; - te[ 9 ] = - b; + te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31; + te[ 4 ] = a21 * b12 + a22 * b22 + a23 * b32; + te[ 7 ] = a21 * b13 + a22 * b23 + a23 * b33; - te[ 2 ] = cf * b - de; - te[ 6 ] = df + ce * b; - te[ 10 ] = a * c; + te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31; + te[ 5 ] = a31 * b12 + a32 * b22 + a33 * b32; + te[ 8 ] = a31 * b13 + a32 * b23 + a33 * b33; - } else if ( euler.order === 'ZXY' ) { + return this; - var ce = c * e, cf = c * f, de = d * e, df = d * f; + }, - te[ 0 ] = ce - df * b; - te[ 4 ] = - a * f; - te[ 8 ] = de + cf * b; + multiplyScalar: function ( s ) { - te[ 1 ] = cf + de * b; - te[ 5 ] = a * e; - te[ 9 ] = df - ce * b; + var te = this.elements; - te[ 2 ] = - a * d; - te[ 6 ] = b; - te[ 10 ] = a * c; + 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; - } else if ( euler.order === 'ZYX' ) { + return this; - var ae = a * e, af = a * f, be = b * e, bf = b * f; + }, - te[ 0 ] = c * e; - te[ 4 ] = be * d - af; - te[ 8 ] = ae * d + bf; + determinant: function () { - te[ 1 ] = c * f; - te[ 5 ] = bf * d + ae; - te[ 9 ] = af * d - be; + var te = this.elements; - te[ 2 ] = - d; - te[ 6 ] = b * c; - te[ 10 ] = a * c; + 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 ]; - } else if ( euler.order === 'YZX' ) { + return a * e * i - a * f * h - b * d * i + b * f * g + c * d * h - c * e * g; - 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; + getInverse: function ( matrix, throwOnDegenerate ) { - te[ 1 ] = f; - te[ 5 ] = a * e; - te[ 9 ] = - b * e; + if ( matrix && matrix.isMatrix4 ) { - te[ 2 ] = - d * e; - te[ 6 ] = ad * f + bc; - te[ 10 ] = ac - bd * f; + console.error( "THREE.Matrix3: .getInverse() no longer takes a Matrix4 argument." ); - } else if ( euler.order === 'XZY' ) { + } - var ac = a * c, ad = a * d, bc = b * c, bd = b * d; + var me = matrix.elements, + te = this.elements, - te[ 0 ] = c * e; - te[ 4 ] = - f; - te[ 8 ] = d * e; + 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 ], - te[ 1 ] = ac * f + bd; - te[ 5 ] = a * e; - te[ 9 ] = ad * f - bc; + t11 = n33 * n22 - n32 * n23, + t12 = n32 * n13 - n33 * n12, + t13 = n23 * n12 - n22 * n13, - te[ 2 ] = bc * f - ad; - te[ 6 ] = b * e; - te[ 10 ] = bd * f + ac; + det = n11 * t11 + n21 * t12 + n31 * t13; - } + if ( det === 0 ) { - // last column - te[ 3 ] = 0; - te[ 7 ] = 0; - te[ 11 ] = 0; + var msg = "THREE.Matrix3: .getInverse() can't invert matrix, determinant is 0"; - // bottom row - te[ 12 ] = 0; - te[ 13 ] = 0; - te[ 14 ] = 0; - te[ 15 ] = 1; + if ( throwOnDegenerate === true ) { - return this; + throw new Error( msg ); - }, + } else { - makeRotationFromQuaternion: function ( q ) { + console.warn( msg ); - var te = this.elements; + } - var x = q._x, y = q._y, z = q._z, w = q._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.identity(); - te[ 0 ] = 1 - ( yy + zz ); - te[ 4 ] = xy - wz; - te[ 8 ] = xz + wy; + } - te[ 1 ] = xy + wz; - te[ 5 ] = 1 - ( xx + zz ); - te[ 9 ] = yz - wx; + var detInv = 1 / det; - te[ 2 ] = xz - wy; - te[ 6 ] = yz + wx; - te[ 10 ] = 1 - ( xx + yy ); + te[ 0 ] = t11 * detInv; + te[ 1 ] = ( n31 * n23 - n33 * n21 ) * detInv; + te[ 2 ] = ( n32 * n21 - n31 * n22 ) * detInv; - // last column - te[ 3 ] = 0; - te[ 7 ] = 0; - te[ 11 ] = 0; + te[ 3 ] = t12 * detInv; + te[ 4 ] = ( n33 * n11 - n31 * n13 ) * detInv; + te[ 5 ] = ( n31 * n12 - n32 * n11 ) * detInv; - // bottom row - te[ 12 ] = 0; - te[ 13 ] = 0; - te[ 14 ] = 0; - te[ 15 ] = 1; + te[ 6 ] = t13 * detInv; + te[ 7 ] = ( n21 * n13 - n23 * n11 ) * detInv; + te[ 8 ] = ( n22 * n11 - n21 * n12 ) * detInv; return this; }, - lookAt: function () { + transpose: function () { - var x = new Vector3(); - var y = new Vector3(); - var z = new Vector3(); + var tmp, m = this.elements; - return function lookAt( eye, target, up ) { + 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; - var te = this.elements; + return this; - z.subVectors( eye, target ); + }, - if ( z.lengthSq() === 0 ) { + getNormalMatrix: function ( matrix4 ) { - // eye and target are in the same position + return this.setFromMatrix4( matrix4 ).getInverse( this ).transpose(); - z.z = 1; + }, + + transposeIntoArray: function ( r ) { + + 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 ]; + + return this; + + }, + + setUvTransform: function ( tx, ty, sx, sy, rotation, cx, cy ) { + + var c = Math.cos( rotation ); + var s = Math.sin( rotation ); + + this.set( + sx * c, sx * s, - sx * ( c * cx + s * cy ) + cx + tx, + - sy * s, sy * c, - sy * ( - s * cx + c * cy ) + cy + ty, + 0, 0, 1 + ); + + }, + + scale: function ( sx, sy ) { + + var te = this.elements; + + te[ 0 ] *= sx; te[ 3 ] *= sx; te[ 6 ] *= sx; + te[ 1 ] *= sy; te[ 4 ] *= sy; te[ 7 ] *= sy; + + 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 ]; + + te[ 0 ] = c * a11 + s * a21; + te[ 3 ] = c * a12 + s * a22; + te[ 6 ] = c * a13 + s * a23; + + te[ 1 ] = - s * a11 + c * a21; + te[ 4 ] = - s * a12 + c * a22; + te[ 7 ] = - s * a13 + c * a23; + + return this; + + }, + + translate: function ( tx, ty ) { + + var te = this.elements; + + 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; + + }, + + equals: function ( matrix ) { + + var te = this.elements; + var me = matrix.elements; + + for ( var i = 0; i < 9; i ++ ) { + + if ( te[ i ] !== me[ i ] ) return false; + + } + + return true; + + }, + + fromArray: function ( array, offset ) { + + if ( offset === undefined ) offset = 0; + + for ( var i = 0; i < 9; i ++ ) { + + this.elements[ i ] = array[ i + offset ]; + + } + + return this; + + }, + + toArray: function ( array, offset ) { + + if ( array === undefined ) array = []; + if ( offset === undefined ) offset = 0; + + var te = this.elements; + + array[ offset ] = te[ 0 ]; + array[ offset + 1 ] = te[ 1 ]; + array[ offset + 2 ] = te[ 2 ]; + + 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 ]; + + return array; + + } + + } ); + + /** + * @author mrdoob / http://mrdoob.com/ + * @author alteredq / http://alteredqualia.com/ + * @author szimek / https://github.com/szimek/ + */ + + var textureId = 0; + + function Texture( image, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ) { + + Object.defineProperty( this, 'id', { value: textureId ++ } ); + + this.uuid = _Math.generateUUID(); + + this.name = ''; + + this.image = image !== undefined ? image : Texture.DEFAULT_IMAGE; + this.mipmaps = []; + + this.mapping = mapping !== undefined ? mapping : Texture.DEFAULT_MAPPING; + + this.wrapS = wrapS !== undefined ? wrapS : ClampToEdgeWrapping; + this.wrapT = wrapT !== undefined ? wrapT : ClampToEdgeWrapping; + + this.magFilter = magFilter !== undefined ? magFilter : LinearFilter; + this.minFilter = minFilter !== undefined ? minFilter : LinearMipMapLinearFilter; + + this.anisotropy = anisotropy !== undefined ? anisotropy : 1; + + this.format = format !== undefined ? format : RGBAFormat; + this.type = type !== undefined ? type : UnsignedByteType; + + this.offset = new Vector2( 0, 0 ); + this.repeat = new Vector2( 1, 1 ); + this.rotation = 0; + + 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) + + // 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.version = 0; + this.onUpdate = null; + + } + + Texture.DEFAULT_IMAGE = undefined; + Texture.DEFAULT_MAPPING = UVMapping; + + Object.defineProperty( Texture.prototype, "needsUpdate", { + + set: function ( value ) { + + if ( value === true ) this.version ++; + + } + + } ); + + Object.assign( Texture.prototype, EventDispatcher.prototype, { + + constructor: Texture, + + isTexture: true, + + clone: function () { + + return new this.constructor().copy( this ); + + }, + + copy: function ( source ) { + + this.name = source.name; + + this.image = source.image; + this.mipmaps = source.mipmaps.slice( 0 ); + + this.mapping = source.mapping; + + this.wrapS = source.wrapS; + this.wrapT = source.wrapT; + + this.magFilter = source.magFilter; + this.minFilter = source.minFilter; + + this.anisotropy = source.anisotropy; + + this.format = source.format; + this.type = source.type; + + this.offset.copy( source.offset ); + this.repeat.copy( source.repeat ); + this.rotation = source.rotation; + + 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.encoding = source.encoding; + + return this; + + }, + + toJSON: function ( meta ) { + + if ( meta.textures[ this.uuid ] !== undefined ) { + + return meta.textures[ this.uuid ]; + + } + + function getDataURL( image ) { + + var canvas; + + if ( image instanceof HTMLCanvasElement ) { + + canvas = image; + + } else { + + canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' ); + canvas.width = image.width; + canvas.height = image.height; + + var context = canvas.getContext( '2d' ); + + if ( image instanceof ImageData ) { + + context.putImageData( image, 0, 0 ); + + } else { + + context.drawImage( image, 0, 0, image.width, image.height ); + + } } - z.normalize(); - x.crossVectors( up, z ); + if ( canvas.width > 2048 || canvas.height > 2048 ) { - if ( x.lengthSq() === 0 ) { + return canvas.toDataURL( 'image/jpeg', 0.6 ); - // eye and target are in the same vertical + } else { - z.z += 0.0001; - x.crossVectors( up, z ); + return canvas.toDataURL( 'image/png' ); } - x.normalize(); - y.crossVectors( z, x ); + } - 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; + var output = { + metadata: { + version: 4.5, + type: 'Texture', + generator: 'Texture.toJSON' + }, - return this; + uuid: this.uuid, + name: this.name, + mapping: this.mapping, + + repeat: [ this.repeat.x, this.repeat.y ], + offset: [ this.offset.x, this.offset.y ], + rotation: this.rotation, + + wrap: [ this.wrapS, this.wrapT ], + + minFilter: this.minFilter, + magFilter: this.magFilter, + anisotropy: this.anisotropy, + + flipY: this.flipY }; - }(), + if ( this.image !== undefined ) { - multiply: function ( m, n ) { + // TODO: Move to THREE.Image - if ( n !== undefined ) { + var image = this.image; - console.warn( 'THREE.Matrix4: .multiply() now only accepts one argument. Use .multiplyMatrices( a, b ) instead.' ); - return this.multiplyMatrices( m, n ); + if ( image.uuid === undefined ) { + + image.uuid = _Math.generateUUID(); // UGH + + } + + if ( meta.images[ image.uuid ] === undefined ) { + + meta.images[ image.uuid ] = { + uuid: image.uuid, + url: getDataURL( image ) + }; + + } + + output.image = image.uuid; } - return this.multiplyMatrices( this, m ); + meta.textures[ this.uuid ] = output; + + return output; }, - premultiply: function ( m ) { + dispose: function () { - return this.multiplyMatrices( m, this ); + this.dispatchEvent( { type: 'dispose' } ); }, - multiplyMatrices: function ( a, b ) { + transformUv: function ( uv ) { - var ae = a.elements; - var be = b.elements; - var te = this.elements; + if ( this.mapping !== UVMapping ) return; - 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 ]; + uv.applyMatrix3( this.matrix ); - 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 ]; + if ( uv.x < 0 || uv.x > 1 ) { - 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; + switch ( this.wrapS ) { - 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; + case RepeatWrapping: - 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; + uv.x = uv.x - Math.floor( uv.x ); + break; - 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; + case ClampToEdgeWrapping: + + uv.x = uv.x < 0 ? 0 : 1; + break; + + case MirroredRepeatWrapping: + + if ( Math.abs( Math.floor( uv.x ) % 2 ) === 1 ) { + + uv.x = Math.ceil( uv.x ) - uv.x; + + } else { + + uv.x = uv.x - Math.floor( uv.x ); + + } + break; + + } + + } + + if ( uv.y < 0 || uv.y > 1 ) { + + switch ( this.wrapT ) { + + case RepeatWrapping: + + uv.y = uv.y - Math.floor( uv.y ); + break; + + case ClampToEdgeWrapping: + + uv.y = uv.y < 0 ? 0 : 1; + break; + + case MirroredRepeatWrapping: + + if ( Math.abs( Math.floor( uv.y ) % 2 ) === 1 ) { + + uv.y = Math.ceil( uv.y ) - uv.y; + + } else { + + uv.y = uv.y - Math.floor( uv.y ); + + } + break; + + } + + } + + if ( this.flipY ) { + + uv.y = 1 - uv.y; + + } + + } + + } ); + + /** + * @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.assign( Vector4.prototype, { + + isVector4: true, + + set: function ( x, y, z, w ) { + + this.x = x; + this.y = y; + this.z = z; + this.w = w; return this; }, - multiplyScalar: function ( s ) { + setScalar: function ( scalar ) { - var te = this.elements; + this.x = scalar; + this.y = scalar; + this.z = scalar; + this.w = scalar; - 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; + + }, + + setX: function ( x ) { + + this.x = x; return this; }, - applyToBufferAttribute: function () { + setY: function ( y ) { - var v1 = new Vector3(); + this.y = y; - return function applyToBufferAttribute( attribute ) { + return this; - for ( var i = 0, l = attribute.count; i < l; i ++ ) { + }, - v1.x = attribute.getX( i ); - v1.y = attribute.getY( i ); - v1.z = attribute.getZ( i ); + setZ: function ( z ) { - v1.applyMatrix4( this ); + this.z = z; - attribute.setXYZ( i, v1.x, v1.y, v1.z ); + return this; + + }, + + setW: function ( w ) { + + this.w = w; + + return this; + + }, + + setComponent: function ( index, value ) { + + 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 ); + + } + + return this; + + }, + + getComponent: function ( index ) { + + switch ( index ) { + + 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 ); + + } + + }, + + clone: function () { + + return new this.constructor( this.x, this.y, this.z, this.w ); + + }, + + copy: function ( v ) { + + this.x = v.x; + this.y = v.y; + this.z = v.z; + this.w = ( v.w !== undefined ) ? v.w : 1; + + return this; + + }, + + add: function ( v, w ) { + + if ( w !== undefined ) { + + console.warn( 'THREE.Vector4: .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; + this.w += v.w; + + return this; + + }, + + addScalar: function ( s ) { + + this.x += s; + this.y += s; + this.z += s; + this.w += s; + + return this; + + }, + + addVectors: function ( a, b ) { + + 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; + + }, + + addScaledVector: function ( v, s ) { + + this.x += v.x * s; + this.y += v.y * s; + this.z += v.z * s; + this.w += v.w * s; + + return this; + + }, + + sub: function ( v, w ) { + + if ( w !== undefined ) { + + console.warn( 'THREE.Vector4: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' ); + return this.subVectors( v, w ); + + } + + this.x -= v.x; + this.y -= v.y; + this.z -= v.z; + this.w -= v.w; + + return this; + + }, + + subScalar: function ( s ) { + + this.x -= s; + this.y -= s; + this.z -= s; + this.w -= s; + + return this; + + }, + + subVectors: function ( a, b ) { + + 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; + + }, + + multiplyScalar: function ( scalar ) { + + this.x *= scalar; + this.y *= scalar; + this.z *= scalar; + this.w *= scalar; + + return this; + + }, + + applyMatrix4: function ( m ) { + + var x = this.x, y = this.y, z = this.z, w = this.w; + var e = m.elements; + + 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; + + }, + + divideScalar: function ( scalar ) { + + return this.multiplyScalar( 1 / scalar ); + + }, + + setAxisAngleFromQuaternion: function ( q ) { + + // http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm + + // q is assumed to be normalized + + this.w = 2 * Math.acos( q.w ); + + var s = Math.sqrt( 1 - q.w * q.w ); + + if ( s < 0.0001 ) { + + this.x = 1; + this.y = 0; + this.z = 0; + + } else { + + this.x = q.x / s; + this.y = q.y / s; + this.z = q.z / s; + + } + + return this; + + }, + + setAxisAngleFromRotationMatrix: function ( m ) { + + // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm + + // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) + + 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 + + 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 ]; + + if ( ( Math.abs( m12 - m21 ) < epsilon ) && + ( Math.abs( m13 - m31 ) < epsilon ) && + ( Math.abs( m23 - m32 ) < epsilon ) ) { + + // 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 ) ) { + + // this singularity is identity matrix so angle = 0 + + this.set( 1, 0, 0, 0 ); + + return this; // zero angle, arbitrary axis } - return attribute; + // otherwise this singularity is angle = 180 - }; + angle = Math.PI; - }(), + 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; - determinant: function () { + if ( ( xx > yy ) && ( xx > zz ) ) { - var te = this.elements; + // m11 is the largest diagonal term - 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 ]; + if ( xx < epsilon ) { - //TODO: make this more efficient - //( based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm ) + x = 0; + y = 0.707106781; + z = 0.707106781; - 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 - ) + } else { + + x = Math.sqrt( xx ); + y = xy / x; + z = xz / x; + + } + + } else if ( yy > zz ) { + + // m22 is the largest diagonal term + + if ( yy < epsilon ) { + + x = 0.707106781; + y = 0; + z = 0.707106781; + + } else { + + y = Math.sqrt( yy ); + x = xy / y; + z = yz / y; + + } + + } else { + + // m33 is the largest diagonal term so base result on this + + if ( zz < epsilon ) { + + x = 0.707106781; + y = 0.707106781; + z = 0; + + } else { + + z = Math.sqrt( zz ); + x = xz / z; + y = yz / z; + + } + + } + + this.set( x, y, z, angle ); + + return this; // return 180 deg rotation + + } + + // as we have reached here there are no singularities so we can handle normally + + var 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; - }, + // 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 - transpose: function () { + this.x = ( m32 - m23 ) / s; + this.y = ( m13 - m31 ) / s; + this.z = ( m21 - m12 ) / s; + this.w = Math.acos( ( m11 + m22 + m33 - 1 ) / 2 ); - var te = this.elements; - var tmp; + return this; - 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; + 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 ); + this.w = Math.min( this.w, v.w ); return this; }, - setPosition: function ( v ) { - - var te = this.elements; + max: function ( v ) { - te[ 12 ] = v.x; - te[ 13 ] = v.y; - te[ 14 ] = v.z; + 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 ); return this; }, - getInverse: function ( m, throwOnDegenerate ) { - - // based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm - var te = this.elements, - me = m.elements, + clamp: function ( min, max ) { - 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 ], + // assumes min < max, componentwise - 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; + 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 ) ); - var det = n11 * t11 + n21 * t12 + n31 * t13 + n41 * t14; + return this; - if ( det === 0 ) { + }, - var msg = "THREE.Matrix4.getInverse(): can't invert matrix, determinant is 0"; + clampScalar: function () { - if ( throwOnDegenerate === true ) { + var min, max; - throw new Error( msg ); + return function clampScalar( minVal, maxVal ) { - } else { + if ( min === undefined ) { - console.warn( msg ); + min = new Vector4(); + max = new Vector4(); } - return this.identity(); - - } + min.set( minVal, minVal, minVal, minVal ); + max.set( maxVal, maxVal, maxVal, maxVal ); - var detInv = 1 / det; + return this.clamp( min, max ); - 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; + }(), - 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; + clampLength: function ( min, max ) { - 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; + var length = this.length(); - return this; + return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) ); }, - scale: function ( v ) { - - var te = this.elements; - var x = v.x, y = v.y, z = v.z; + floor: function () { - 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; + 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; }, - getMaxScaleOnAxis: function () { - - var te = this.elements; + ceil: function () { - 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 ]; + 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 Math.sqrt( Math.max( scaleXSq, scaleYSq, scaleZSq ) ); + return this; }, - makeTranslation: function ( x, y, z ) { - - this.set( - - 1, 0, 0, x, - 0, 1, 0, y, - 0, 0, 1, z, - 0, 0, 0, 1 + 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 ); return this; }, - makeRotationX: function ( theta ) { - - var c = Math.cos( theta ), s = Math.sin( theta ); - - this.set( - - 1, 0, 0, 0, - 0, c, - s, 0, - 0, s, c, 0, - 0, 0, 0, 1 + 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 ); + 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 ); return this; }, - makeRotationY: function ( theta ) { - - var c = Math.cos( theta ), s = Math.sin( theta ); - - this.set( - - c, 0, s, 0, - 0, 1, 0, 0, - - s, 0, c, 0, - 0, 0, 0, 1 + negate: function () { - ); + this.x = - this.x; + this.y = - this.y; + this.z = - this.z; + this.w = - this.w; return this; }, - makeRotationZ: function ( theta ) { - - var c = Math.cos( theta ), s = Math.sin( theta ); + dot: function ( v ) { - this.set( + return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w; - c, - s, 0, 0, - s, c, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1 + }, - ); + lengthSq: function () { - return this; + return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w; }, - makeRotationAxis: function ( axis, angle ) { + length: function () { - // Based on http://www.gamedev.net/reference/articles/article1199.asp + return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w ); - 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; + }, - this.set( + lengthManhattan: function () { - 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 + return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ) + Math.abs( this.w ); - ); + }, - return this; + normalize: function () { + + return this.divideScalar( this.length() || 1 ); }, - makeScale: function ( x, y, z ) { + setLength: function ( length ) { - this.set( + return this.normalize().multiplyScalar( length ); - x, 0, 0, 0, - 0, y, 0, 0, - 0, 0, z, 0, - 0, 0, 0, 1 + }, - ); + lerp: function ( v, alpha ) { + + 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; }, - makeShear: function ( x, y, z ) { + lerpVectors: function ( v1, v2, alpha ) { - this.set( + return this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 ); - 1, y, z, 0, - x, 1, z, 0, - x, y, 1, 0, - 0, 0, 0, 1 + }, - ); + equals: function ( v ) { - return this; + return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) && ( v.w === this.w ) ); }, - compose: function ( position, quaternion, scale ) { + fromArray: function ( array, offset ) { - this.makeRotationFromQuaternion( quaternion ); - this.scale( scale ); - this.setPosition( position ); + if ( offset === undefined ) offset = 0; + + this.x = array[ offset ]; + this.y = array[ offset + 1 ]; + this.z = array[ offset + 2 ]; + this.w = array[ offset + 3 ]; return this; }, - decompose: function () { - - var vector = new Vector3(); - var matrix = new Matrix4(); - - return function decompose( position, quaternion, scale ) { - - var te = this.elements; + toArray: function ( array, offset ) { - var sx = vector.set( te[ 0 ], te[ 1 ], te[ 2 ] ).length(); - var sy = vector.set( te[ 4 ], te[ 5 ], te[ 6 ] ).length(); - var sz = vector.set( te[ 8 ], te[ 9 ], te[ 10 ] ).length(); + if ( array === undefined ) array = []; + if ( offset === undefined ) offset = 0; - // if determine is negative, we need to invert one scale - var det = this.determinant(); - if ( det < 0 ) sx = - sx; + array[ offset ] = this.x; + array[ offset + 1 ] = this.y; + array[ offset + 2 ] = this.z; + array[ offset + 3 ] = this.w; - position.x = te[ 12 ]; - position.y = te[ 13 ]; - position.z = te[ 14 ]; + return array; - // scale the rotation part - matrix.copy( this ); + }, - var invSX = 1 / sx; - var invSY = 1 / sy; - var invSZ = 1 / sz; + fromBufferAttribute: function ( attribute, index, offset ) { - matrix.elements[ 0 ] *= invSX; - matrix.elements[ 1 ] *= invSX; - matrix.elements[ 2 ] *= invSX; + if ( offset !== undefined ) { - matrix.elements[ 4 ] *= invSY; - matrix.elements[ 5 ] *= invSY; - matrix.elements[ 6 ] *= invSY; + console.warn( 'THREE.Vector4: offset has been removed from .fromBufferAttribute().' ); - matrix.elements[ 8 ] *= invSZ; - matrix.elements[ 9 ] *= invSZ; - matrix.elements[ 10 ] *= invSZ; + } - quaternion.setFromRotationMatrix( matrix ); + this.x = attribute.getX( index ); + this.y = attribute.getY( index ); + this.z = attribute.getZ( index ); + this.w = attribute.getW( index ); - scale.x = sx; - scale.y = sy; - scale.z = sz; + return this; - return this; + } - }; + } ); - }(), + /** + * @author szimek / https://github.com/szimek/ + * @author alteredq / http://alteredqualia.com/ + * @author Marius Kintel / https://github.com/kintel + */ - makePerspective: function ( left, right, top, bottom, near, far ) { + /* + 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 ) { - if ( far === undefined ) { + this.uuid = _Math.generateUUID(); - console.warn( 'THREE.Matrix4: .makePerspective() has been redefined and has a new signature. Please check the docs.' ); + this.width = width; + this.height = height; - } + this.scissor = new Vector4( 0, 0, width, height ); + this.scissorTest = false; - var te = this.elements; - var x = 2 * near / ( right - left ); - var y = 2 * near / ( top - bottom ); + this.viewport = new Vector4( 0, 0, width, height ); - 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 ); + options = options || {}; - 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; + if ( options.minFilter === undefined ) options.minFilter = LinearFilter; - return this; + this.texture = new Texture( undefined, undefined, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding ); - }, + this.depthBuffer = options.depthBuffer !== undefined ? options.depthBuffer : true; + this.stencilBuffer = options.stencilBuffer !== undefined ? options.stencilBuffer : true; + this.depthTexture = options.depthTexture !== undefined ? options.depthTexture : null; - makeOrthographic: function ( left, right, top, bottom, near, far ) { + } - var te = this.elements; - var w = 1.0 / ( right - left ); - var h = 1.0 / ( top - bottom ); - var p = 1.0 / ( far - near ); + Object.assign( WebGLRenderTarget.prototype, EventDispatcher.prototype, { - var x = ( right + left ) * w; - var y = ( top + bottom ) * h; - var z = ( far + near ) * p; + isWebGLRenderTarget: true, - 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; + setSize: function ( width, height ) { - return this; + if ( this.width !== width || this.height !== height ) { - }, + this.width = width; + this.height = height; - equals: function ( matrix ) { + this.dispose(); - var te = this.elements; - var me = matrix.elements; + } - for ( var i = 0; i < 16; i ++ ) { + this.viewport.set( 0, 0, width, height ); + this.scissor.set( 0, 0, width, height ); - if ( te[ i ] !== me[ i ] ) return false; + }, - } + clone: function () { - return true; + return new this.constructor().copy( this ); }, - fromArray: function ( array, offset ) { + copy: function ( source ) { - if ( offset === undefined ) offset = 0; + this.width = source.width; + this.height = source.height; - for ( var i = 0; i < 16; i ++ ) { + this.viewport.copy( source.viewport ); - this.elements[ i ] = array[ i + offset ]; + this.texture = source.texture.clone(); - } + this.depthBuffer = source.depthBuffer; + this.stencilBuffer = source.stencilBuffer; + this.depthTexture = source.depthTexture; return this; }, - toArray: function ( array, offset ) { + dispose: function () { - if ( array === undefined ) array = []; - if ( offset === undefined ) offset = 0; + this.dispatchEvent( { type: 'dispose' } ); - var te = this.elements; + } - array[ offset ] = te[ 0 ]; - array[ offset + 1 ] = te[ 1 ]; - array[ offset + 2 ] = te[ 2 ]; - 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 ]; + /** + * @author alteredq / http://alteredqualia.com + */ - array[ offset + 8 ] = te[ 8 ]; - array[ offset + 9 ] = te[ 9 ]; - array[ offset + 10 ] = te[ 10 ]; - array[ offset + 11 ] = te[ 11 ]; + function WebGLRenderTargetCube( width, height, options ) { - array[ offset + 12 ] = te[ 12 ]; - array[ offset + 13 ] = te[ 13 ]; - array[ offset + 14 ] = te[ 14 ]; - array[ offset + 15 ] = te[ 15 ]; + WebGLRenderTarget.call( this, width, height, options ); - return array; + this.activeCubeFace = 0; // PX 0, NX 1, PY 2, NY 3, PZ 4, NZ 5 + this.activeMipMapLevel = 0; - } + } - } ); + WebGLRenderTargetCube.prototype = Object.create( WebGLRenderTarget.prototype ); + WebGLRenderTargetCube.prototype.constructor = WebGLRenderTargetCube; + + WebGLRenderTargetCube.prototype.isWebGLRenderTargetCube = true; /** * @author alteredq / http://alteredqualia.com/ @@ -4514,7 +4952,7 @@ case 0x8b5b: return setValue3fm; // _MAT3 case 0x8b5c: return setValue4fm; // _MAT4 - case 0x8b5e: return setValueT1; // SAMPLER_2D + case 0x8b5e: case 0x8d66: return setValueT1; // SAMPLER_2D, SAMPLER_EXTERNAL_OES case 0x8b60: return setValueT6; // SAMPLER_CUBE case 0x1404: case 0x8b56: return setValue1i; // INT, BOOL @@ -4846,7 +5284,7 @@ '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, 'red': 0xFF0000, 'rosybrown': 0xBC8F8F, + '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, @@ -5354,11 +5792,20 @@ opacity: { value: 1.0 }, map: { value: null }, - offsetRepeat: { value: new Vector4( 0, 0, 1, 1 ) }, + uvTransform: { value: new Matrix3() }, - specularMap: { value: null }, alphaMap: { value: null }, + }, + + specularmap: { + + specularMap: { value: null }, + + }, + + envmap: { + envMap: { value: null }, flipEnvMap: { value: - 1 }, reflectivity: { value: 1.0 }, @@ -5479,7 +5926,9 @@ shadow: {}, shadowBias: {}, shadowRadius: {}, - shadowMapSize: {} + shadowMapSize: {}, + shadowCameraNear: {}, + shadowCameraFar: {} } }, pointShadowMap: { value: [] }, @@ -5508,7 +5957,7 @@ size: { value: 1.0 }, scale: { value: 1.0 }, map: { value: null }, - offsetRepeat: { value: new Vector4( 0, 0, 1, 1 ) } + uvTransform: { value: new Matrix3() } } @@ -5595,7 +6044,7 @@ var bsdfs = "float punctualLightIntensityToIrradianceFactor( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\tif( decayExponent > 0.0 ) {\n#if defined ( PHYSICALLY_CORRECT_LIGHTS )\n\t\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\t\tfloat maxDistanceCutoffFactor = pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t\treturn distanceFalloff * maxDistanceCutoffFactor;\n#else\n\t\treturn pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );\n#endif\n\t}\n\treturn 1.0;\n}\nvec3 BRDF_Diffuse_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 specularColor, const in float dotLH ) {\n\tfloat fresnel = exp2( ( -5.55473 * dotLH - 6.98316 ) * dotLH );\n\treturn ( 1.0 - specularColor ) * fresnel + specularColor;\n}\nfloat G_GGX_Smith( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gl = dotNL + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\tfloat gv = dotNV + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\treturn 1.0 / ( gl * gv );\n}\nfloat G_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}\nvec3 BRDF_Specular_GGX( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNL = saturate( dot( geometry.normal, incidentLight.direction ) );\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\tfloat D = D_GGX( alpha, dotNH );\n\treturn F * ( G * 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 theta = acos( dot( N, V ) );\n\tvec2 uv = vec2(\n\t\tsqrt( saturate( roughness ) ),\n\t\tsaturate( theta / ( 0.5 * PI ) ) );\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.86267 + (0.49788 + 0.01436 * y ) * y;\n\tfloat b = 3.45068 + (4.18814 + y) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = (x > 0.0) ? v : 0.5 * inversesqrt( 1.0 - x * x ) - 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 * transpose( 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\tvec3 result = vec3( LTC_ClippedSphereFormFactor( vectorFormFactor ) );\n\treturn result;\n}\nvec3 BRDF_Specular_GGX_Environment( const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.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 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;\n\treturn specularColor * AB.x + AB.y;\n}\nfloat 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_Specular_BlinnPhong( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float shininess ) {\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n}\nfloat GGXRoughnessToBlinnExponent( const in float ggxRoughness ) {\n\treturn ( 2.0 / pow2( ggxRoughness + 0.0001 ) - 2.0 );\n}\nfloat BlinnExponentToGGXRoughness( const in float blinnExponent ) {\n\treturn sqrt( 2.0 / ( blinnExponent + 2.0 ) );\n}\n"; - var bumpmap_pars_fragment = "#ifdef USE_BUMPMAP\n\tuniform sampler2D bumpMap;\n\tuniform float bumpScale;\n\tvec2 dHdxy_fwd() {\n\t\tvec2 dSTdx = dFdx( vUv );\n\t\tvec2 dSTdy = dFdy( vUv );\n\t\tfloat Hll = bumpScale * texture2D( bumpMap, vUv ).x;\n\t\tfloat dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;\n\t\tfloat dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;\n\t\treturn vec2( dBx, dBy );\n\t}\n\tvec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy ) {\n\t\tvec3 vSigmaX = dFdx( surf_pos );\n\t\tvec3 vSigmaY = dFdy( surf_pos );\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 );\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\n"; + var bumpmap_pars_fragment = "#ifdef USE_BUMPMAP\n\tuniform sampler2D bumpMap;\n\tuniform float bumpScale;\n\tvec2 dHdxy_fwd() {\n\t\tvec2 dSTdx = dFdx( vUv );\n\t\tvec2 dSTdy = dFdy( vUv );\n\t\tfloat Hll = bumpScale * texture2D( bumpMap, vUv ).x;\n\t\tfloat dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;\n\t\tfloat dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;\n\t\treturn vec2( dBx, dBy );\n\t}\n\tvec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy ) {\n\t\tvec3 vSigmaX = vec3( dFdx( surf_pos.x ), dFdx( surf_pos.y ), dFdx( surf_pos.z ) );\n\t\tvec3 vSigmaY = vec3( dFdy( surf_pos.x ), dFdy( surf_pos.y ), dFdy( surf_pos.z ) );\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 );\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\n"; var clipping_planes_fragment = "#if NUM_CLIPPING_PLANES > 0\n\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; ++ i ) {\n\t\tvec4 plane = clippingPlanes[ i ];\n\t\tif ( dot( vViewPosition, plane.xyz ) > plane.w ) discard;\n\t}\n\t\t\n\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\tbool clipped = true;\n\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; ++ i ) {\n\t\t\tvec4 plane = clippingPlanes[ i ];\n\t\t\tclipped = ( dot( vViewPosition, plane.xyz ) > plane.w ) && clipped;\n\t\t}\n\t\tif ( clipped ) discard;\n\t\n\t#endif\n#endif\n"; @@ -5613,15 +6062,15 @@ var color_vertex = "#ifdef USE_COLOR\n\tvColor.xyz = color.xyz;\n#endif"; - var common = "#define PI 3.14159265359\n#define PI2 6.28318530718\n#define PI_HALF 1.5707963267949\n#define RECIPROCAL_PI 0.31830988618\n#define RECIPROCAL_PI2 0.15915494\n#define LOG2 1.442695\n#define EPSILON 1e-6\n#define saturate(a) clamp( a, 0.0, 1.0 )\n#define whiteCompliment(a) ( 1.0 - saturate( a ) )\nfloat pow2( const in float 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 average( const in vec3 color ) { return dot( color, vec3( 0.3333 ) ); }\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}\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};\nstruct GeometricContext {\n\tvec3 position;\n\tvec3 normal;\n\tvec3 viewDir;\n};\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}\nvec3 projectOnPlane(in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\tfloat distance = dot( planeNormal, point - pointOnPlane );\n\treturn - distance * planeNormal + point;\n}\nfloat sideOfPlane( in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn sign( dot( point - pointOnPlane, planeNormal ) );\n}\nvec3 linePlaneIntersect( in vec3 pointOnLine, in vec3 lineDirection, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn lineDirection * ( dot( planeNormal, pointOnPlane - pointOnLine ) / dot( planeNormal, lineDirection ) ) + pointOnLine;\n}\nmat3 transpose( const in mat3 v ) {\n\tmat3 tmp;\n\ttmp[0] = vec3(v[0].x, v[1].x, v[2].x);\n\ttmp[1] = vec3(v[0].y, v[1].y, v[2].y);\n\ttmp[2] = vec3(v[0].z, v[1].z, v[2].z);\n\treturn tmp;\n}\n"; + var common = "#define PI 3.14159265359\n#define PI2 6.28318530718\n#define PI_HALF 1.5707963267949\n#define RECIPROCAL_PI 0.31830988618\n#define RECIPROCAL_PI2 0.15915494\n#define LOG2 1.442695\n#define EPSILON 1e-6\n#define saturate(a) clamp( a, 0.0, 1.0 )\n#define whiteCompliment(a) ( 1.0 - saturate( a ) )\nfloat pow2( const in float 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 average( const in vec3 color ) { return dot( color, vec3( 0.3333 ) ); }\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}\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};\nstruct GeometricContext {\n\tvec3 position;\n\tvec3 normal;\n\tvec3 viewDir;\n};\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}\nvec3 projectOnPlane(in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\tfloat distance = dot( planeNormal, point - pointOnPlane );\n\treturn - distance * planeNormal + point;\n}\nfloat sideOfPlane( in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn sign( dot( point - pointOnPlane, planeNormal ) );\n}\nvec3 linePlaneIntersect( in vec3 pointOnLine, in vec3 lineDirection, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn lineDirection * ( dot( planeNormal, pointOnPlane - pointOnLine ) / dot( planeNormal, lineDirection ) ) + pointOnLine;\n}\nmat3 transpose( const in mat3 v ) {\n\tmat3 tmp;\n\ttmp[0] = vec3(v[0].x, v[1].x, v[2].x);\n\ttmp[1] = vec3(v[0].y, v[1].y, v[2].y);\n\ttmp[2] = vec3(v[0].z, v[1].z, v[2].z);\n\treturn tmp;\n}\nfloat linearToRelativeLuminance( const in vec3 color ) {\n\tvec3 weights = vec3( 0.2126, 0.7152, 0.0722 );\n\treturn dot( weights, color.rgb );\n}\n"; var cube_uv_reflection_fragment = "#ifdef ENVMAP_TYPE_CUBE_UV\n#define cubeUV_textureSize (1024.0)\nint getFaceFromDirection(vec3 direction) {\n\tvec3 absDirection = abs(direction);\n\tint face = -1;\n\tif( absDirection.x > absDirection.z ) {\n\t\tif(absDirection.x > absDirection.y )\n\t\t\tface = direction.x > 0.0 ? 0 : 3;\n\t\telse\n\t\t\tface = direction.y > 0.0 ? 1 : 4;\n\t}\n\telse {\n\t\tif(absDirection.z > absDirection.y )\n\t\t\tface = direction.z > 0.0 ? 2 : 5;\n\t\telse\n\t\t\tface = direction.y > 0.0 ? 1 : 4;\n\t}\n\treturn face;\n}\n#define cubeUV_maxLods1 (log2(cubeUV_textureSize*0.25) - 1.0)\n#define cubeUV_rangeClamp (exp2((6.0 - 1.0) * 2.0))\nvec2 MipLevelInfo( vec3 vec, float roughnessLevel, float roughness ) {\n\tfloat scale = exp2(cubeUV_maxLods1 - roughnessLevel);\n\tfloat dxRoughness = dFdx(roughness);\n\tfloat dyRoughness = dFdy(roughness);\n\tvec3 dx = dFdx( vec * scale * dxRoughness );\n\tvec3 dy = dFdy( vec * scale * dyRoughness );\n\tfloat d = max( dot( dx, dx ), dot( dy, dy ) );\n\td = clamp(d, 1.0, cubeUV_rangeClamp);\n\tfloat mipLevel = 0.5 * log2(d);\n\treturn vec2(floor(mipLevel), fract(mipLevel));\n}\n#define cubeUV_maxLods2 (log2(cubeUV_textureSize*0.25) - 2.0)\n#define cubeUV_rcpTextureSize (1.0 / cubeUV_textureSize)\nvec2 getCubeUV(vec3 direction, float roughnessLevel, float mipLevel) {\n\tmipLevel = roughnessLevel > cubeUV_maxLods2 - 3.0 ? 0.0 : mipLevel;\n\tfloat a = 16.0 * cubeUV_rcpTextureSize;\n\tvec2 exp2_packed = exp2( vec2( roughnessLevel, mipLevel ) );\n\tvec2 rcp_exp2_packed = vec2( 1.0 ) / exp2_packed;\n\tfloat powScale = exp2_packed.x * exp2_packed.y;\n\tfloat scale = rcp_exp2_packed.x * rcp_exp2_packed.y * 0.25;\n\tfloat mipOffset = 0.75*(1.0 - rcp_exp2_packed.y) * rcp_exp2_packed.x;\n\tbool bRes = mipLevel == 0.0;\n\tscale = bRes && (scale < a) ? a : scale;\n\tvec3 r;\n\tvec2 offset;\n\tint face = getFaceFromDirection(direction);\n\tfloat rcpPowScale = 1.0 / powScale;\n\tif( face == 0) {\n\t\tr = vec3(direction.x, -direction.z, direction.y);\n\t\toffset = vec2(0.0+mipOffset,0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 1) {\n\t\tr = vec3(direction.y, direction.x, direction.z);\n\t\toffset = vec2(scale+mipOffset, 0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 2) {\n\t\tr = vec3(direction.z, direction.x, direction.y);\n\t\toffset = vec2(2.0*scale+mipOffset, 0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 3) {\n\t\tr = vec3(direction.x, direction.z, direction.y);\n\t\toffset = vec2(0.0+mipOffset,0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\telse if( face == 4) {\n\t\tr = vec3(direction.y, direction.x, -direction.z);\n\t\toffset = vec2(scale+mipOffset, 0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\telse {\n\t\tr = vec3(direction.z, -direction.x, direction.y);\n\t\toffset = vec2(2.0*scale+mipOffset, 0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\tr = normalize(r);\n\tfloat texelOffset = 0.5 * cubeUV_rcpTextureSize;\n\tvec2 s = ( r.yz / abs( r.x ) + vec2( 1.0 ) ) * 0.5;\n\tvec2 base = offset + vec2( texelOffset );\n\treturn base + s * ( scale - 2.0 * texelOffset );\n}\n#define cubeUV_maxLods3 (log2(cubeUV_textureSize*0.25) - 3.0)\nvec4 textureCubeUV(vec3 reflectedDirection, float roughness ) {\n\tfloat roughnessVal = roughness* cubeUV_maxLods3;\n\tfloat r1 = floor(roughnessVal);\n\tfloat r2 = r1 + 1.0;\n\tfloat t = fract(roughnessVal);\n\tvec2 mipInfo = MipLevelInfo(reflectedDirection, r1, roughness);\n\tfloat s = mipInfo.y;\n\tfloat level0 = mipInfo.x;\n\tfloat level1 = level0 + 1.0;\n\tlevel1 = level1 > 5.0 ? 5.0 : level1;\n\tlevel0 += min( floor( s + 0.5 ), 5.0 );\n\tvec2 uv_10 = getCubeUV(reflectedDirection, r1, level0);\n\tvec4 color10 = envMapTexelToLinear(texture2D(envMap, uv_10));\n\tvec2 uv_20 = getCubeUV(reflectedDirection, r2, level0);\n\tvec4 color20 = envMapTexelToLinear(texture2D(envMap, uv_20));\n\tvec4 result = mix(color10, color20, t);\n\treturn vec4(result.rgb, 1.0);\n}\n#endif\n"; - var defaultnormal_vertex = "#ifdef FLIP_SIDED\n\tobjectNormal = -objectNormal;\n#endif\nvec3 transformedNormal = normalMatrix * objectNormal;\n"; + var defaultnormal_vertex = "vec3 transformedNormal = normalMatrix * objectNormal;\n#ifdef FLIP_SIDED\n\ttransformedNormal = - transformedNormal;\n#endif\n"; var displacementmap_pars_vertex = "#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif\n"; - var displacementmap_vertex = "#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normal * ( texture2D( displacementMap, uv ).x * displacementScale + displacementBias );\n#endif\n"; + var displacementmap_vertex = "#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, uv ).x * displacementScale + displacementBias );\n#endif\n"; var emissivemap_fragment = "#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vUv );\n\temissiveColor.rgb = emissiveMapTexelToLinear( emissiveColor ).rgb;\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif\n"; @@ -5631,7 +6080,7 @@ var encodings_pars_fragment = "\nvec4 LinearToLinear( in vec4 value ) {\n\treturn value;\n}\nvec4 GammaToLinear( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.xyz, vec3( gammaFactor ) ), value.w );\n}\nvec4 LinearToGamma( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.xyz, vec3( 1.0 / gammaFactor ) ), value.w );\n}\nvec4 sRGBToLinear( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), value.rgb * 0.0773993808, vec3( lessThanEqual( value.rgb, vec3( 0.04045 ) ) ) ), value.w );\n}\nvec4 LinearTosRGB( 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.w );\n}\nvec4 RGBEToLinear( in vec4 value ) {\n\treturn vec4( value.rgb * exp2( value.a * 255.0 - 128.0 ), 1.0 );\n}\nvec4 LinearToRGBE( in vec4 value ) {\n\tfloat maxComponent = max( max( value.r, value.g ), value.b );\n\tfloat fExp = clamp( ceil( log2( maxComponent ) ), -128.0, 127.0 );\n\treturn vec4( value.rgb / exp2( fExp ), ( fExp + 128.0 ) / 255.0 );\n}\nvec4 RGBMToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.xyz * value.w * maxRange, 1.0 );\n}\nvec4 LinearToRGBM( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.x, max( value.g, value.b ) );\n\tfloat M = clamp( maxRGB / maxRange, 0.0, 1.0 );\n\tM = ceil( M * 255.0 ) / 255.0;\n\treturn vec4( value.rgb / ( M * maxRange ), M );\n}\nvec4 RGBDToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.rgb * ( ( maxRange / 255.0 ) / value.a ), 1.0 );\n}\nvec4 LinearToRGBD( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.x, max( value.g, value.b ) );\n\tfloat D = max( maxRange / maxRGB, 1.0 );\n\tD = min( floor( D ) / 255.0, 1.0 );\n\treturn vec4( value.rgb * ( D * ( 255.0 / maxRange ) ), D );\n}\nconst mat3 cLogLuvM = mat3( 0.2209, 0.3390, 0.4184, 0.1138, 0.6780, 0.7319, 0.0102, 0.1130, 0.2969 );\nvec4 LinearToLogLuv( in vec4 value ) {\n\tvec3 Xp_Y_XYZp = value.rgb * cLogLuvM;\n\tXp_Y_XYZp = max(Xp_Y_XYZp, vec3(1e-6, 1e-6, 1e-6));\n\tvec4 vResult;\n\tvResult.xy = Xp_Y_XYZp.xy / Xp_Y_XYZp.z;\n\tfloat Le = 2.0 * log2(Xp_Y_XYZp.y) + 127.0;\n\tvResult.w = fract(Le);\n\tvResult.z = (Le - (floor(vResult.w*255.0))/255.0)/255.0;\n\treturn vResult;\n}\nconst mat3 cLogLuvInverseM = mat3( 6.0014, -2.7008, -1.7996, -1.3320, 3.1029, -5.7721, 0.3008, -1.0882, 5.6268 );\nvec4 LogLuvToLinear( in vec4 value ) {\n\tfloat Le = value.z * 255.0 + value.w;\n\tvec3 Xp_Y_XYZp;\n\tXp_Y_XYZp.y = exp2((Le - 127.0) / 2.0);\n\tXp_Y_XYZp.z = Xp_Y_XYZp.y / value.y;\n\tXp_Y_XYZp.x = value.x * Xp_Y_XYZp.z;\n\tvec3 vRGB = Xp_Y_XYZp.rgb * cLogLuvInverseM;\n\treturn vec4( max(vRGB, 0.0), 1.0 );\n}\n"; - var envmap_fragment = "#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvec3 cameraToVertex = normalize( vWorldPosition - cameraPosition );\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToVertex, 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, flipNormal * vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\t#elif defined( ENVMAP_TYPE_EQUIREC )\n\t\tvec2 sampleUV;\n\t\tsampleUV.y = saturate( flipNormal * reflectVec.y * 0.5 + 0.5 );\n\t\tsampleUV.x = atan( flipNormal * reflectVec.z, flipNormal * reflectVec.x ) * RECIPROCAL_PI2 + 0.5;\n\t\tvec4 envColor = texture2D( envMap, sampleUV );\n\t#elif defined( ENVMAP_TYPE_SPHERE )\n\t\tvec3 reflectView = flipNormal * normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0, 0.0, 1.0 ) );\n\t\tvec4 envColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5 );\n\t#else\n\t\tvec4 envColor = vec4( 0.0 );\n\t#endif\n\tenvColor = envMapTexelToLinear( envColor );\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\n"; + var envmap_fragment = "#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvec3 cameraToVertex = normalize( vWorldPosition - cameraPosition );\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToVertex, 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#elif defined( ENVMAP_TYPE_EQUIREC )\n\t\tvec2 sampleUV;\n\t\treflectVec = normalize( reflectVec );\n\t\tsampleUV.y = asin( clamp( reflectVec.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\t\tsampleUV.x = atan( reflectVec.z, reflectVec.x ) * RECIPROCAL_PI2 + 0.5;\n\t\tvec4 envColor = texture2D( envMap, sampleUV );\n\t#elif defined( ENVMAP_TYPE_SPHERE )\n\t\treflectVec = normalize( reflectVec );\n\t\tvec3 reflectView = normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0, 0.0, 1.0 ) );\n\t\tvec4 envColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5 );\n\t#else\n\t\tvec4 envColor = vec4( 0.0 );\n\t#endif\n\tenvColor = envMapTexelToLinear( envColor );\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\n"; var envmap_pars_fragment = "#if defined( USE_ENVMAP ) || defined( PHYSICAL )\n\tuniform float reflectivity;\n\tuniform float envMapIntensity;\n#endif\n#ifdef USE_ENVMAP\n\t#if ! defined( PHYSICAL ) && ( defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) )\n\t\tvarying vec3 vWorldPosition;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tuniform samplerCube envMap;\n\t#else\n\t\tuniform sampler2D envMap;\n\t#endif\n\tuniform float flipEnvMap;\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( PHYSICAL )\n\t\tuniform float refractionRatio;\n\t#else\n\t\tvarying vec3 vReflect;\n\t#endif\n#endif\n"; @@ -5655,7 +6104,7 @@ var lights_lambert_vertex = "vec3 diffuse = vec3( 1.0 );\nGeometricContext geometry;\ngeometry.position = mvPosition.xyz;\ngeometry.normal = normalize( transformedNormal );\ngeometry.viewDir = normalize( -mvPosition.xyz );\nGeometricContext backGeometry;\nbackGeometry.position = geometry.position;\nbackGeometry.normal = -geometry.normal;\nbackGeometry.viewDir = geometry.viewDir;\nvLightFront = vec3( 0.0 );\n#ifdef DOUBLE_SIDED\n\tvLightBack = vec3( 0.0 );\n#endif\nIncidentLight directLight;\nfloat dotNL;\nvec3 directLightColor_Diffuse;\n#if NUM_POINT_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tgetPointDirectLightIrradiance( pointLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tgetSpotDirectLightIrradiance( spotLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_DIR_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tgetDirectionalDirectLightIrradiance( directionalLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\tvLightFront += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += getHemisphereLightIrradiance( hemisphereLights[ i ], backGeometry );\n\t\t#endif\n\t}\n#endif\n"; - var lights_pars = "uniform vec3 ambientLightColor;\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treturn irradiance;\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalDirectLightIrradiance( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tdirectLight.color = directionalLight.color;\n\t\tdirectLight.direction = directionalLight.direction;\n\t\tdirectLight.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\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointDirectLightIrradiance( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tvec3 lVector = pointLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tdirectLight.color = pointLight.color;\n\t\tdirectLight.color *= punctualLightIntensityToIrradianceFactor( lightDistance, pointLight.distance, pointLight.decay );\n\t\tdirectLight.visible = ( directLight.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\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\tvoid getSpotDirectLightIrradiance( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tvec3 lVector = spotLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tfloat angleCos = dot( directLight.direction, spotLight.direction );\n\t\tif ( angleCos > spotLight.coneCos ) {\n\t\t\tfloat spotEffect = smoothstep( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\t\tdirectLight.color = spotLight.color;\n\t\t\tdirectLight.color *= spotEffect * punctualLightIntensityToIrradianceFactor( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tdirectLight.visible = true;\n\t\t} else {\n\t\t\tdirectLight.color = vec3( 0.0 );\n\t\t\tdirectLight.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 ltcMat;\tuniform sampler2D ltcMag;\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 GeometricContext geometry ) {\n\t\tfloat dotNL = dot( geometry.normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tirradiance *= PI;\n\t\t#endif\n\t\treturn irradiance;\n\t}\n#endif\n#if defined( USE_ENVMAP ) && defined( PHYSICAL )\n\tvec3 getLightProbeIndirectIrradiance( const in GeometricContext geometry, const in int maxMIPLevel ) {\n\t\tvec3 worldNormal = inverseTransformDirection( geometry.normal, viewMatrix );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\tvec4 envMapColor = textureCubeUV( queryVec, 1.0 );\n\t\t#else\n\t\t\tvec4 envMapColor = vec4( 0.0 );\n\t\t#endif\n\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t}\n\tfloat getSpecularMIPLevel( const in float blinnShininessExponent, const in int maxMIPLevel ) {\n\t\tfloat maxMIPLevelScalar = float( maxMIPLevel );\n\t\tfloat desiredMIPLevel = maxMIPLevelScalar - 0.79248 - 0.5 * log2( pow2( blinnShininessExponent ) + 1.0 );\n\t\treturn clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );\n\t}\n\tvec3 getLightProbeIndirectRadiance( const in GeometricContext geometry, const in float blinnShininessExponent, const in int maxMIPLevel ) {\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( -geometry.viewDir, geometry.normal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( -geometry.viewDir, geometry.normal, refractionRatio );\n\t\t#endif\n\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\tfloat specularMIPLevel = getSpecularMIPLevel( blinnShininessExponent, maxMIPLevel );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\tvec4 envMapColor = textureCubeUV(queryReflectVec, BlinnExponentToGGXRoughness(blinnShininessExponent));\n\t\t#elif defined( ENVMAP_TYPE_EQUIREC )\n\t\t\tvec2 sampleUV;\n\t\t\tsampleUV.y = saturate( reflectVec.y * 0.5 + 0.5 );\n\t\t\tsampleUV.x = atan( reflectVec.z, reflectVec.x ) * RECIPROCAL_PI2 + 0.5;\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = texture2DLodEXT( envMap, sampleUV, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = texture2D( envMap, sampleUV, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_SPHERE )\n\t\t\tvec3 reflectView = normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0,0.0,1.0 ) );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = texture2DLodEXT( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#endif\n\t\treturn envMapColor.rgb * envMapIntensity;\n\t}\n#endif\n"; + var lights_pars = "uniform vec3 ambientLightColor;\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treturn irradiance;\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalDirectLightIrradiance( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tdirectLight.color = directionalLight.color;\n\t\tdirectLight.direction = directionalLight.direction;\n\t\tdirectLight.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\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t\tfloat shadowCameraNear;\n\t\tfloat shadowCameraFar;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointDirectLightIrradiance( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tvec3 lVector = pointLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tdirectLight.color = pointLight.color;\n\t\tdirectLight.color *= punctualLightIntensityToIrradianceFactor( lightDistance, pointLight.distance, pointLight.decay );\n\t\tdirectLight.visible = ( directLight.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\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\tvoid getSpotDirectLightIrradiance( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tvec3 lVector = spotLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tfloat angleCos = dot( directLight.direction, spotLight.direction );\n\t\tif ( angleCos > spotLight.coneCos ) {\n\t\t\tfloat spotEffect = smoothstep( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\t\tdirectLight.color = spotLight.color;\n\t\t\tdirectLight.color *= spotEffect * punctualLightIntensityToIrradianceFactor( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tdirectLight.visible = true;\n\t\t} else {\n\t\t\tdirectLight.color = vec3( 0.0 );\n\t\t\tdirectLight.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 ltcMat;\tuniform sampler2D ltcMag;\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 GeometricContext geometry ) {\n\t\tfloat dotNL = dot( geometry.normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tirradiance *= PI;\n\t\t#endif\n\t\treturn irradiance;\n\t}\n#endif\n#if defined( USE_ENVMAP ) && defined( PHYSICAL )\n\tvec3 getLightProbeIndirectIrradiance( const in GeometricContext geometry, const in int maxMIPLevel ) {\n\t\tvec3 worldNormal = inverseTransformDirection( geometry.normal, viewMatrix );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\tvec4 envMapColor = textureCubeUV( queryVec, 1.0 );\n\t\t#else\n\t\t\tvec4 envMapColor = vec4( 0.0 );\n\t\t#endif\n\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t}\n\tfloat getSpecularMIPLevel( const in float blinnShininessExponent, const in int maxMIPLevel ) {\n\t\tfloat maxMIPLevelScalar = float( maxMIPLevel );\n\t\tfloat desiredMIPLevel = maxMIPLevelScalar - 0.79248 - 0.5 * log2( pow2( blinnShininessExponent ) + 1.0 );\n\t\treturn clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );\n\t}\n\tvec3 getLightProbeIndirectRadiance( const in GeometricContext geometry, const in float blinnShininessExponent, const in int maxMIPLevel ) {\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( -geometry.viewDir, geometry.normal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( -geometry.viewDir, geometry.normal, refractionRatio );\n\t\t#endif\n\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\tfloat specularMIPLevel = getSpecularMIPLevel( blinnShininessExponent, maxMIPLevel );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\tvec4 envMapColor = textureCubeUV(queryReflectVec, BlinnExponentToGGXRoughness(blinnShininessExponent));\n\t\t#elif defined( ENVMAP_TYPE_EQUIREC )\n\t\t\tvec2 sampleUV;\n\t\t\tsampleUV.y = asin( clamp( reflectVec.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\t\t\tsampleUV.x = atan( reflectVec.z, reflectVec.x ) * RECIPROCAL_PI2 + 0.5;\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = texture2DLodEXT( envMap, sampleUV, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = texture2D( envMap, sampleUV, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_SPHERE )\n\t\t\tvec3 reflectView = normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0,0.0,1.0 ) );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = texture2DLodEXT( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#endif\n\t\treturn envMapColor.rgb * envMapIntensity;\n\t}\n#endif\n"; var lights_phong_fragment = "BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;\n"; @@ -5665,23 +6114,23 @@ var lights_physical_pars_fragment = "struct PhysicalMaterial {\n\tvec3\tdiffuseColor;\n\tfloat\tspecularRoughness;\n\tvec3\tspecularColor;\n\t#ifndef STANDARD\n\t\tfloat clearCoat;\n\t\tfloat clearCoatRoughness;\n\t#endif\n};\n#define MAXIMUM_SPECULAR_COEFFICIENT 0.16\n#define DEFAULT_SPECULAR_COEFFICIENT 0.04\nfloat clearCoatDHRApprox( const in float roughness, const in float dotNL ) {\n\treturn DEFAULT_SPECULAR_COEFFICIENT + ( 1.0 - DEFAULT_SPECULAR_COEFFICIENT ) * ( pow( 1.0 - dotNL, 5.0 ) * pow( 1.0 - roughness, 2.0 ) );\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometry.normal;\n\t\tvec3 viewDir = geometry.viewDir;\n\t\tvec3 position = geometry.position;\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.specularRoughness;\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\tfloat norm = texture2D( ltcMag, uv ).a;\n\t\tvec4 t = texture2D( ltcMat, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( 1, 0, t.y ),\n\t\t\tvec3( 0, t.z, 0 ),\n\t\t\tvec3( t.w, 0, t.x )\n\t\t);\n\t\treflectedLight.directSpecular += lightColor * material.specularColor * norm * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\t#ifndef STANDARD\n\t\tfloat clearCoatDHR = material.clearCoat * clearCoatDHRApprox( material.clearCoatRoughness, dotNL );\n\t#else\n\t\tfloat clearCoatDHR = 0.0;\n\t#endif\n\treflectedLight.directSpecular += ( 1.0 - clearCoatDHR ) * irradiance * BRDF_Specular_GGX( directLight, geometry, material.specularColor, material.specularRoughness );\n\treflectedLight.directDiffuse += ( 1.0 - clearCoatDHR ) * irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\t#ifndef STANDARD\n\t\treflectedLight.directSpecular += irradiance * material.clearCoat * BRDF_Specular_GGX( directLight, geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness );\n\t#endif\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 clearCoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t#ifndef STANDARD\n\t\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\t\tfloat dotNL = dotNV;\n\t\tfloat clearCoatDHR = material.clearCoat * clearCoatDHRApprox( material.clearCoatRoughness, dotNL );\n\t#else\n\t\tfloat clearCoatDHR = 0.0;\n\t#endif\n\treflectedLight.indirectSpecular += ( 1.0 - clearCoatDHR ) * radiance * BRDF_Specular_GGX_Environment( geometry, material.specularColor, material.specularRoughness );\n\t#ifndef STANDARD\n\t\treflectedLight.indirectSpecular += clearCoatRadiance * material.clearCoat * BRDF_Specular_GGX_Environment( geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness );\n\t#endif\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\n#define Material_BlinnShininessExponent( material ) GGXRoughnessToBlinnExponent( material.specularRoughness )\n#define Material_ClearCoat_BlinnShininessExponent( material ) GGXRoughnessToBlinnExponent( material.clearCoatRoughness )\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}\n"; - var lights_template = "\nGeometricContext geometry;\ngeometry.position = - vViewPosition;\ngeometry.normal = normal;\ngeometry.viewDir = normalize( vViewPosition );\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointDirectLightIrradiance( pointLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( pointLight.shadow, directLight.visible ) ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotDirectLightIrradiance( spotLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( spotLight.shadow, directLight.visible ) ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalDirectLightIrradiance( directionalLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( directionalLight.shadow, directLight.visible ) ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\t#ifdef USE_LIGHTMAP\n\t\tvec3 lightMapIrradiance = texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tlightMapIrradiance *= PI;\n\t\t#endif\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t}\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( PHYSICAL ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tirradiance += getLightProbeIndirectIrradiance( geometry, 8 );\n\t#endif\n\tRE_IndirectDiffuse( irradiance, geometry, material, reflectedLight );\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\tvec3 radiance = getLightProbeIndirectRadiance( geometry, Material_BlinnShininessExponent( material ), 8 );\n\t#ifndef STANDARD\n\t\tvec3 clearCoatRadiance = getLightProbeIndirectRadiance( geometry, Material_ClearCoat_BlinnShininessExponent( material ), 8 );\n\t#else\n\t\tvec3 clearCoatRadiance = vec3( 0.0 );\n\t#endif\n\tRE_IndirectSpecular( radiance, clearCoatRadiance, geometry, material, reflectedLight );\n#endif\n"; + var lights_template = "\nGeometricContext geometry;\ngeometry.position = - vViewPosition;\ngeometry.normal = normal;\ngeometry.viewDir = normalize( vViewPosition );\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointDirectLightIrradiance( pointLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( pointLight.shadow, directLight.visible ) ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotDirectLightIrradiance( spotLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( spotLight.shadow, directLight.visible ) ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalDirectLightIrradiance( directionalLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( directionalLight.shadow, directLight.visible ) ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\t#ifdef USE_LIGHTMAP\n\t\tvec3 lightMapIrradiance = texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tlightMapIrradiance *= PI;\n\t\t#endif\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t}\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( PHYSICAL ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tirradiance += getLightProbeIndirectIrradiance( geometry, 8 );\n\t#endif\n\tRE_IndirectDiffuse( irradiance, geometry, material, reflectedLight );\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\tvec3 radiance = getLightProbeIndirectRadiance( geometry, Material_BlinnShininessExponent( material ), 8 );\n\t#ifndef STANDARD\n\t\tvec3 clearCoatRadiance = getLightProbeIndirectRadiance( geometry, Material_ClearCoat_BlinnShininessExponent( material ), 8 );\n\t#else\n\t\tvec3 clearCoatRadiance = vec3( 0.0 );\n\t#endif\n\tRE_IndirectSpecular( radiance, clearCoatRadiance, geometry, material, reflectedLight );\n#endif\n"; - var logdepthbuf_fragment = "#if defined(USE_LOGDEPTHBUF) && defined(USE_LOGDEPTHBUF_EXT)\n\tgl_FragDepthEXT = log2(vFragDepth) * logDepthBufFC * 0.5;\n#endif"; + var logdepthbuf_fragment = "#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tgl_FragDepthEXT = log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif"; var logdepthbuf_pars_fragment = "#ifdef USE_LOGDEPTHBUF\n\tuniform float logDepthBufFC;\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t#endif\n#endif\n"; var logdepthbuf_pars_vertex = "#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t#endif\n\tuniform float logDepthBufFC;\n#endif"; - var logdepthbuf_vertex = "#ifdef USE_LOGDEPTHBUF\n\tgl_Position.z = log2(max( EPSILON, gl_Position.w + 1.0 )) * logDepthBufFC;\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvFragDepth = 1.0 + gl_Position.w;\n\t#else\n\t\tgl_Position.z = (gl_Position.z - 1.0) * gl_Position.w;\n\t#endif\n#endif\n"; + var logdepthbuf_vertex = "#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvFragDepth = 1.0 + gl_Position.w;\n\t#else\n\t\tgl_Position.z = log2( max( EPSILON, gl_Position.w + 1.0 ) ) * logDepthBufFC - 1.0;\n\t\tgl_Position.z *= gl_Position.w;\n\t#endif\n#endif\n"; var map_fragment = "#ifdef USE_MAP\n\tvec4 texelColor = texture2D( map, vUv );\n\ttexelColor = mapTexelToLinear( texelColor );\n\tdiffuseColor *= texelColor;\n#endif\n"; var map_pars_fragment = "#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif\n"; - var map_particle_fragment = "#ifdef USE_MAP\n\tvec4 mapTexel = texture2D( map, vec2( gl_PointCoord.x, 1.0 - gl_PointCoord.y ) * offsetRepeat.zw + offsetRepeat.xy );\n\tdiffuseColor *= mapTexelToLinear( mapTexel );\n#endif\n"; + var map_particle_fragment = "#ifdef USE_MAP\n\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n\tvec4 mapTexel = texture2D( map, uv );\n\tdiffuseColor *= mapTexelToLinear( mapTexel );\n#endif\n"; - var map_particle_pars_fragment = "#ifdef USE_MAP\n\tuniform vec4 offsetRepeat;\n\tuniform sampler2D map;\n#endif\n"; + var map_particle_pars_fragment = "#ifdef USE_MAP\n\tuniform mat3 uvTransform;\n\tuniform sampler2D map;\n#endif\n"; var metalnessmap_fragment = "float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif\n"; @@ -5693,17 +6142,15 @@ var morphtarget_vertex = "#ifdef USE_MORPHTARGETS\n\ttransformed += ( morphTarget0 - position ) * morphTargetInfluences[ 0 ];\n\ttransformed += ( morphTarget1 - position ) * morphTargetInfluences[ 1 ];\n\ttransformed += ( morphTarget2 - position ) * morphTargetInfluences[ 2 ];\n\ttransformed += ( morphTarget3 - position ) * morphTargetInfluences[ 3 ];\n\t#ifndef USE_MORPHNORMALS\n\ttransformed += ( morphTarget4 - position ) * morphTargetInfluences[ 4 ];\n\ttransformed += ( morphTarget5 - position ) * morphTargetInfluences[ 5 ];\n\ttransformed += ( morphTarget6 - position ) * morphTargetInfluences[ 6 ];\n\ttransformed += ( morphTarget7 - position ) * morphTargetInfluences[ 7 ];\n\t#endif\n#endif\n"; - var normal_flip = "#ifdef DOUBLE_SIDED\n\tfloat flipNormal = ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n#else\n\tfloat flipNormal = 1.0;\n#endif\n"; - - var normal_fragment = "#ifdef FLAT_SHADED\n\tvec3 fdx = vec3( dFdx( vViewPosition.x ), dFdx( vViewPosition.y ), dFdx( vViewPosition.z ) );\n\tvec3 fdy = vec3( dFdy( vViewPosition.x ), dFdy( vViewPosition.y ), dFdy( vViewPosition.z ) );\n\tvec3 normal = normalize( cross( fdx, fdy ) );\n#else\n\tvec3 normal = normalize( vNormal ) * flipNormal;\n#endif\n#ifdef USE_NORMALMAP\n\tnormal = perturbNormal2Arb( -vViewPosition, normal );\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );\n#endif\n"; + var normal_fragment = "#ifdef FLAT_SHADED\n\tvec3 fdx = vec3( dFdx( vViewPosition.x ), dFdx( vViewPosition.y ), dFdx( vViewPosition.z ) );\n\tvec3 fdy = vec3( dFdy( vViewPosition.x ), dFdy( vViewPosition.y ), dFdy( vViewPosition.z ) );\n\tvec3 normal = normalize( cross( fdx, fdy ) );\n#else\n\tvec3 normal = normalize( vNormal );\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t#endif\n#endif\n#ifdef USE_NORMALMAP\n\tnormal = perturbNormal2Arb( -vViewPosition, normal );\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );\n#endif\n"; - var normalmap_pars_fragment = "#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n\tvec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm ) {\n\t\tvec3 q0 = dFdx( eye_pos.xyz );\n\t\tvec3 q1 = dFdy( eye_pos.xyz );\n\t\tvec2 st0 = dFdx( vUv.st );\n\t\tvec2 st1 = dFdy( vUv.st );\n\t\tvec3 S = normalize( q0 * st1.t - q1 * st0.t );\n\t\tvec3 T = normalize( -q0 * st1.s + q1 * st0.s );\n\t\tvec3 N = normalize( surf_norm );\n\t\tvec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\t\tmapN.xy = normalScale * mapN.xy;\n\t\tmat3 tsn = mat3( S, T, N );\n\t\treturn normalize( tsn * mapN );\n\t}\n#endif\n"; + var normalmap_pars_fragment = "#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n\tvec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm ) {\n\t\tvec3 q0 = vec3( dFdx( eye_pos.x ), dFdx( eye_pos.y ), dFdx( eye_pos.z ) );\n\t\tvec3 q1 = vec3( dFdy( eye_pos.x ), dFdy( eye_pos.y ), dFdy( eye_pos.z ) );\n\t\tvec2 st0 = dFdx( vUv.st );\n\t\tvec2 st1 = dFdy( vUv.st );\n\t\tvec3 S = normalize( q0 * st1.t - q1 * st0.t );\n\t\tvec3 T = normalize( -q0 * st1.s + q1 * st0.s );\n\t\tvec3 N = normalize( surf_norm );\n\t\tvec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\t\tmapN.xy = normalScale * mapN.xy;\n\t\tmat3 tsn = mat3( S, T, N );\n\t\treturn normalize( tsn * mapN );\n\t}\n#endif\n"; 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 1.0 - 2.0 * rgb.xyz;\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}\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 linearClipZ, const in float near, const in float far ) {\n\treturn linearClipZ * ( 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 invClipZ, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * invClipZ - far );\n}\n"; var premultiplied_alpha_fragment = "#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif\n"; - var project_vertex = "#ifdef USE_SKINNING\n\tvec4 mvPosition = modelViewMatrix * skinned;\n#else\n\tvec4 mvPosition = modelViewMatrix * vec4( transformed, 1.0 );\n#endif\ngl_Position = projectionMatrix * mvPosition;\n"; + var project_vertex = "vec4 mvPosition = modelViewMatrix * vec4( transformed, 1.0 );\ngl_Position = projectionMatrix * mvPosition;\n"; var dithering_fragment = "#if defined( DITHERING )\n gl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif\n"; @@ -5713,19 +6160,19 @@ var roughnessmap_pars_fragment = "#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif"; - var shadowmap_pars_fragment = "#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHTS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHTS ];\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHTS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHTS ];\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHTS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHTS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tfloat texture2DShadowLerp( sampler2D depths, vec2 size, vec2 uv, float compare ) {\n\t\tconst vec2 offset = vec2( 0.0, 1.0 );\n\t\tvec2 texelSize = vec2( 1.0 ) / size;\n\t\tvec2 centroidUV = floor( uv * size + 0.5 ) / size;\n\t\tfloat lb = texture2DCompare( depths, centroidUV + texelSize * offset.xx, compare );\n\t\tfloat lt = texture2DCompare( depths, centroidUV + texelSize * offset.xy, compare );\n\t\tfloat rb = texture2DCompare( depths, centroidUV + texelSize * offset.yx, compare );\n\t\tfloat rt = texture2DCompare( depths, centroidUV + texelSize * offset.yy, compare );\n\t\tvec2 f = fract( uv * size + 0.5 );\n\t\tfloat a = mix( lb, lt, f.y );\n\t\tfloat b = mix( rb, rt, f.y );\n\t\tfloat c = mix( a, b, f.x );\n\t\treturn c;\n\t}\n\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\tshadowCoord.z += shadowBias;\n\t\tbvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );\n\t\tbool inFrustum = all( inFrustumVec );\n\t\tbvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );\n\t\tbool frustumTest = all( frustumTestVec );\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\treturn (\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( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, 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( 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 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\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\treturn (\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\treturn texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#endif\n\t\t}\n\t\treturn 1.0;\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 ) {\n\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\tvec3 bd3D = normalize( lightToPosition );\n\t\tfloat dp = ( length( lightToPosition ) - shadowBias ) / 1000.0;\n\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT )\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\n"; + var shadowmap_pars_fragment = "#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHTS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHTS ];\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHTS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHTS ];\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHTS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHTS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tfloat texture2DShadowLerp( sampler2D depths, vec2 size, vec2 uv, float compare ) {\n\t\tconst vec2 offset = vec2( 0.0, 1.0 );\n\t\tvec2 texelSize = vec2( 1.0 ) / size;\n\t\tvec2 centroidUV = floor( uv * size + 0.5 ) / size;\n\t\tfloat lb = texture2DCompare( depths, centroidUV + texelSize * offset.xx, compare );\n\t\tfloat lt = texture2DCompare( depths, centroidUV + texelSize * offset.xy, compare );\n\t\tfloat rb = texture2DCompare( depths, centroidUV + texelSize * offset.yx, compare );\n\t\tfloat rt = texture2DCompare( depths, centroidUV + texelSize * offset.yy, compare );\n\t\tvec2 f = fract( uv * size + 0.5 );\n\t\tfloat a = mix( lb, lt, f.y );\n\t\tfloat b = mix( rb, rt, f.y );\n\t\tfloat c = mix( a, b, f.x );\n\t\treturn c;\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\tbvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );\n\t\tbool inFrustum = all( inFrustumVec );\n\t\tbvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );\n\t\tbool frustumTest = all( frustumTestVec );\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\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( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, 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( 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 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\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\tshadow = (\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 9.0 );\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 )\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\n"; var shadowmap_pars_vertex = "#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHTS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHTS ];\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\t\tuniform mat4 spotShadowMatrix[ NUM_SPOT_LIGHTS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHTS ];\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHTS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHTS ];\n\t#endif\n#endif\n"; var shadowmap_vertex = "#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tvSpotShadowCoord[ i ] = spotShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n#endif\n"; - var shadowmask_pars_fragment = "float getShadowMask() {\n\tfloat shadow = 1.0;\n\t#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\tDirectionalLight directionalLight;\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tshadow *= bool( directionalLight.shadow ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t}\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\tSpotLight spotLight;\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tshadow *= bool( spotLight.shadow ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t}\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\tPointLight pointLight;\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tshadow *= bool( pointLight.shadow ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ] ) : 1.0;\n\t}\n\t#endif\n\t#endif\n\treturn shadow;\n}\n"; + var shadowmask_pars_fragment = "float getShadowMask() {\n\tfloat shadow = 1.0;\n\t#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\tDirectionalLight directionalLight;\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tshadow *= bool( directionalLight.shadow ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t}\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\tSpotLight spotLight;\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tshadow *= bool( spotLight.shadow ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t}\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\tPointLight pointLight;\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tshadow *= bool( pointLight.shadow ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t}\n\t#endif\n\t#endif\n\treturn shadow;\n}\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"; var skinning_pars_vertex = "#ifdef USE_SKINNING\n\tuniform mat4 bindMatrix;\n\tuniform mat4 bindMatrixInverse;\n\t#ifdef BONE_TEXTURE\n\t\tuniform sampler2D boneTexture;\n\t\tuniform int boneTextureSize;\n\t\tmat4 getBoneMatrix( const in float i ) {\n\t\t\tfloat j = i * 4.0;\n\t\t\tfloat x = mod( j, float( boneTextureSize ) );\n\t\t\tfloat y = floor( j / float( boneTextureSize ) );\n\t\t\tfloat dx = 1.0 / float( boneTextureSize );\n\t\t\tfloat dy = 1.0 / float( boneTextureSize );\n\t\t\ty = dy * ( y + 0.5 );\n\t\t\tvec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );\n\t\t\tvec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );\n\t\t\tvec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );\n\t\t\tvec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );\n\t\t\tmat4 bone = mat4( v1, v2, v3, v4 );\n\t\t\treturn bone;\n\t\t}\n\t#else\n\t\tuniform mat4 boneMatrices[ MAX_BONES ];\n\t\tmat4 getBoneMatrix( const in float i ) {\n\t\t\tmat4 bone = boneMatrices[ int(i) ];\n\t\t\treturn bone;\n\t\t}\n\t#endif\n#endif\n"; - 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\tskinned = bindMatrixInverse * skinned;\n#endif\n"; + 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\n"; 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#endif\n"; @@ -5739,9 +6186,9 @@ var uv_pars_fragment = "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvarying vec2 vUv;\n#endif"; - var uv_pars_vertex = "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvarying vec2 vUv;\n\tuniform vec4 offsetRepeat;\n#endif\n"; + var uv_pars_vertex = "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvarying vec2 vUv;\n\tuniform mat3 uvTransform;\n#endif\n"; - var uv_vertex = "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvUv = uv * offsetRepeat.zw + offsetRepeat.xy;\n#endif"; + var uv_vertex = "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n#endif"; var uv2_pars_fragment = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvarying vec2 vUv2;\n#endif"; @@ -5749,21 +6196,21 @@ var uv2_vertex = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvUv2 = uv2;\n#endif"; - var worldpos_vertex = "#if defined( USE_ENVMAP ) || defined( PHONG ) || defined( PHYSICAL ) || defined( LAMBERT ) || defined ( USE_SHADOWMAP )\n\t#ifdef USE_SKINNING\n\t\tvec4 worldPosition = modelMatrix * skinned;\n\t#else\n\t\tvec4 worldPosition = modelMatrix * vec4( transformed, 1.0 );\n\t#endif\n#endif\n"; + var worldpos_vertex = "#if defined( USE_ENVMAP ) || defined( PHONG ) || defined( PHYSICAL ) || defined( LAMBERT ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP )\n\tvec4 worldPosition = modelMatrix * vec4( transformed, 1.0 );\n#endif\n"; - var cube_frag = "uniform samplerCube tCube;\nuniform float tFlip;\nuniform float opacity;\nvarying vec3 vWorldPosition;\n#include \nvoid main() {\n\tgl_FragColor = textureCube( tCube, vec3( tFlip * vWorldPosition.x, vWorldPosition.yz ) );\n\tgl_FragColor.a *= opacity;\n}\n"; + var cube_frag = "uniform samplerCube tCube;\nuniform float tFlip;\nuniform float opacity;\nvarying vec3 vWorldPosition;\nvoid main() {\n\tgl_FragColor = textureCube( tCube, vec3( tFlip * vWorldPosition.x, vWorldPosition.yz ) );\n\tgl_FragColor.a *= opacity;\n}\n"; var cube_vert = "varying vec3 vWorldPosition;\n#include \nvoid main() {\n\tvWorldPosition = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n}\n"; var depth_frag = "#if DEPTH_PACKING == 3200\n\tuniform float opacity;\n#endif\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#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#if DEPTH_PACKING == 3200\n\t\tgl_FragColor = vec4( vec3( gl_FragCoord.z ), opacity );\n\t#elif DEPTH_PACKING == 3201\n\t\tgl_FragColor = packDepthToRGBA( gl_FragCoord.z );\n\t#endif\n}\n"; - var depth_vert = "#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}\n"; + var depth_vert = "#include \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}\n"; - var distanceRGBA_frag = "uniform vec3 lightPos;\nvarying vec4 vWorldPosition;\n#include \n#include \n#include \nvoid main () {\n\t#include \n\tgl_FragColor = packDepthToRGBA( length( vWorldPosition.xyz - lightPos.xyz ) / 1000.0 );\n}\n"; + var distanceRGBA_frag = "#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 \nvoid main () {\n\t#include \n\tvec4 diffuseColor = vec4( 1.0 );\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}\n"; - var distanceRGBA_vert = "varying vec4 vWorldPosition;\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\tvWorldPosition = worldPosition;\n}\n"; + var distanceRGBA_vert = "#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}\n"; - var equirect_frag = "uniform sampler2D tEquirect;\nuniform float tFlip;\nvarying vec3 vWorldPosition;\n#include \nvoid main() {\n\tvec3 direction = normalize( vWorldPosition );\n\tvec2 sampleUV;\n\tsampleUV.y = saturate( tFlip * direction.y * -0.5 + 0.5 );\n\tsampleUV.x = atan( direction.z, direction.x ) * RECIPROCAL_PI2 + 0.5;\n\tgl_FragColor = texture2D( tEquirect, sampleUV );\n}\n"; + var equirect_frag = "uniform sampler2D tEquirect;\nvarying vec3 vWorldPosition;\n#include \nvoid main() {\n\tvec3 direction = normalize( vWorldPosition );\n\tvec2 sampleUV;\n\tsampleUV.y = asin( clamp( direction.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\tsampleUV.x = atan( direction.z, direction.x ) * RECIPROCAL_PI2 + 0.5;\n\tgl_FragColor = texture2D( tEquirect, sampleUV );\n}\n"; var equirect_vert = "varying vec3 vWorldPosition;\n#include \nvoid main() {\n\tvWorldPosition = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n}\n"; @@ -5771,33 +6218,33 @@ var linedashed_vert = "uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvLineDistance = scale * lineDistance;\n\tvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\n\tgl_Position = projectionMatrix * mvPosition;\n\t#include \n\t#include \n\t#include \n}\n"; - var meshbasic_frag = "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 \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\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\treflectedLight.indirectDiffuse += texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\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\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; + var meshbasic_frag = "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 \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\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\treflectedLight.indirectDiffuse += texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\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\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; var meshbasic_vert = "#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#ifdef USE_ENVMAP\n\t#include \n\t#include \n\t#include \n\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}\n"; - var meshlambert_frag = "uniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\nvarying vec3 vLightFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\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 \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\treflectedLight.indirectDiffuse = getAmbientLightIrradiance( ambientLightColor );\n\t#include \n\treflectedLight.indirectDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb );\n\t#ifdef DOUBLE_SIDED\n\t\treflectedLight.directDiffuse = ( gl_FrontFacing ) ? vLightFront : vLightBack;\n\t#else\n\t\treflectedLight.directDiffuse = vLightFront;\n\t#endif\n\treflectedLight.directDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb ) * getShadowMask();\n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\t#include \n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; + var meshlambert_frag = "uniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\nvarying vec3 vLightFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\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 \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\treflectedLight.indirectDiffuse = getAmbientLightIrradiance( ambientLightColor );\n\t#include \n\treflectedLight.indirectDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb );\n\t#ifdef DOUBLE_SIDED\n\t\treflectedLight.directDiffuse = ( gl_FrontFacing ) ? vLightFront : vLightBack;\n\t#else\n\t\treflectedLight.directDiffuse = vLightFront;\n\t#endif\n\treflectedLight.directDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb ) * getShadowMask();\n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; var meshlambert_vert = "#define LAMBERT\nvarying vec3 vLightFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\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 \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\t#include \n\t#include \n\t#include \n}\n"; - var meshphong_frag = "#define PHONG\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;\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 \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\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\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\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include \n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; + var meshphong_frag = "#define PHONG\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;\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 \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\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\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\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include \n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; - var meshphong_vert = "#define PHONG\nvarying vec3 vViewPosition;\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 \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#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\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}\n"; + var meshphong_vert = "#define PHONG\nvarying vec3 vViewPosition;\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 \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#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\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}\n"; - var meshphysical_frag = "#define PHYSICAL\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifndef STANDARD\n\tuniform float clearCoat;\n\tuniform float clearCoatRoughness;\n#endif\nvarying vec3 vViewPosition;\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 \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\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\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\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; + var meshphysical_frag = "#define PHYSICAL\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifndef STANDARD\n\tuniform float clearCoat;\n\tuniform float clearCoatRoughness;\n#endif\nvarying vec3 vViewPosition;\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 \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\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\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\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; - var meshphysical_vert = "#define PHYSICAL\nvarying vec3 vViewPosition;\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 \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#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\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}\n"; + var meshphysical_vert = "#define PHYSICAL\nvarying vec3 vViewPosition;\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 \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#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\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}\n"; - var normal_frag = "#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\tgl_FragColor = vec4( packNormalToRGB( normal ), opacity );\n}\n"; + var normal_frag = "#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\tgl_FragColor = vec4( packNormalToRGB( normal ), opacity );\n}\n"; - var normal_vert = "#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\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#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}\n"; + var normal_vert = "#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\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#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}\n"; var points_frag = "uniform vec3 diffuse;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; var points_vert = "uniform float size;\nuniform float scale;\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#ifdef USE_SIZEATTENUATION\n\t\tgl_PointSize = size * ( scale / - mvPosition.z );\n\t#else\n\t\tgl_PointSize = size;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; - var shadow_frag = "uniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tgl_FragColor = vec4( 0.0, 0.0, 0.0, opacity * ( 1.0 - getShadowMask() ) );\n}\n"; + var shadow_frag = "uniform vec3 color;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tgl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\n\t#include \n}\n"; - var shadow_vert = "#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; + var shadow_vert = "#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; var ShaderChunk = { alphamap_fragment: alphamap_fragment, @@ -5857,7 +6304,6 @@ morphnormal_vertex: morphnormal_vertex, morphtarget_pars_vertex: morphtarget_pars_vertex, morphtarget_vertex: morphtarget_vertex, - normal_flip: normal_flip, normal_fragment: normal_fragment, normalmap_pars_fragment: normalmap_pars_fragment, packing: packing, @@ -5925,6 +6371,8 @@ uniforms: UniformsUtils.merge( [ UniformsLib.common, + UniformsLib.specularmap, + UniformsLib.envmap, UniformsLib.aomap, UniformsLib.lightmap, UniformsLib.fog @@ -5939,6 +6387,8 @@ uniforms: UniformsUtils.merge( [ UniformsLib.common, + UniformsLib.specularmap, + UniformsLib.envmap, UniformsLib.aomap, UniformsLib.lightmap, UniformsLib.emissivemap, @@ -5958,6 +6408,8 @@ uniforms: UniformsUtils.merge( [ UniformsLib.common, + UniformsLib.specularmap, + UniformsLib.envmap, UniformsLib.aomap, UniformsLib.lightmap, UniformsLib.emissivemap, @@ -5983,6 +6435,7 @@ uniforms: UniformsUtils.merge( [ UniformsLib.common, + UniformsLib.envmap, UniformsLib.aomap, UniformsLib.lightmap, UniformsLib.emissivemap, @@ -6081,15 +6534,10 @@ }, - /* ------------------------------------------------------------------------- - // Cube map shader - ------------------------------------------------------------------------- */ - equirect: { uniforms: { tEquirect: { value: null }, - tFlip: { value: - 1 } }, vertexShader: ShaderChunk.equirect_vert, @@ -6099,13 +6547,35 @@ distanceRGBA: { - uniforms: { - lightPos: { value: new Vector3() } - }, + uniforms: UniformsUtils.merge( [ + UniformsLib.common, + UniformsLib.displacementmap, + { + referencePosition: { value: new Vector3() }, + nearDistance: { value: 1 }, + farDistance: { value: 1000 } + } + ] ), vertexShader: ShaderChunk.distanceRGBA_vert, fragmentShader: ShaderChunk.distanceRGBA_frag + }, + + shadow: { + + uniforms: UniformsUtils.merge( [ + UniformsLib.lights, + UniformsLib.fog, + { + color: { value: new Color( 0x00000 ) }, + opacity: { value: 1.0 } + }, + ] ), + + vertexShader: ShaderChunk.shadow_vert, + fragmentShader: ShaderChunk.shadow_frag + } }; @@ -6347,10 +6817,7 @@ * @author alteredq / http://alteredqualia.com/ */ - function LensFlarePlugin( renderer, flares ) { - - var gl = renderer.context; - var state = renderer.state; + function WebGLFlareRenderer( renderer, gl, state, textures, capabilities ) { var vertexBuffer, elementBuffer; var shader, program, attributes, uniforms; @@ -6521,7 +6988,7 @@ * reads these back and calculates occlusion. */ - this.render = function ( scene, camera, viewport ) { + this.render = function ( flares, scene, camera, viewport ) { if ( flares.length === 0 ) return; @@ -6548,7 +7015,7 @@ } - gl.useProgram( program ); + state.useProgram( program ); state.initAttributes(); state.enableAttribute( attributes.vertex ); @@ -6677,7 +7144,8 @@ gl.uniform3f( uniforms.color, sprite.color.r, sprite.color.g, sprite.color.b ); state.setBlending( sprite.blending, sprite.blendEquation, sprite.blendSrc, sprite.blendDst ); - renderer.setTexture2D( sprite.texture, 1 ); + + textures.setTexture2D( sprite.texture, 1 ); gl.drawElements( gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 ); @@ -6695,7 +7163,7 @@ state.enable( gl.DEPTH_TEST ); state.buffers.depth.setMask( true ); - renderer.resetGLState(); + state.reset(); }; @@ -6706,7 +7174,7 @@ var fragmentShader = gl.createShader( gl.FRAGMENT_SHADER ); var vertexShader = gl.createShader( gl.VERTEX_SHADER ); - var prefix = "precision " + renderer.getPrecision() + " float;\n"; + var prefix = "precision " + capabilities.precision + " float;\n"; gl.shaderSource( fragmentShader, prefix + shader.fragmentShader ); gl.shaderSource( vertexShader, prefix + shader.vertexShader ); @@ -6725,15 +7193,27 @@ } + /** + * @author mrdoob / http://mrdoob.com/ + */ + + function CanvasTexture( canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) { + + Texture.call( this, canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ); + + this.needsUpdate = true; + + } + + CanvasTexture.prototype = Object.create( Texture.prototype ); + CanvasTexture.prototype.constructor = CanvasTexture; + /** * @author mikael emtinger / http://gomo.se/ * @author alteredq / http://alteredqualia.com/ */ - function SpritePlugin( renderer, sprites ) { - - var gl = renderer.context; - var state = renderer.state; + function WebGLSpriteRenderer( renderer, gl, state, textures, capabilities ) { var vertexBuffer, elementBuffer; var program, attributes, uniforms; @@ -6795,6 +7275,7 @@ fogNear: gl.getUniformLocation( program, 'fogNear' ), fogFar: gl.getUniformLocation( program, 'fogFar' ), fogColor: gl.getUniformLocation( program, 'fogColor' ), + fogDepth: gl.getUniformLocation( program, 'fogDepth' ), alphaTest: gl.getUniformLocation( program, 'alphaTest' ) }; @@ -6807,12 +7288,11 @@ context.fillStyle = 'white'; context.fillRect( 0, 0, 8, 8 ); - texture = new Texture( canvas ); - texture.needsUpdate = true; + texture = new CanvasTexture( canvas ); } - this.render = function ( scene, camera ) { + this.render = function ( sprites, scene, camera ) { if ( sprites.length === 0 ) return; @@ -6824,7 +7304,7 @@ } - gl.useProgram( program ); + state.useProgram( program ); state.initAttributes(); state.enableAttribute( attributes.position ); @@ -6905,6 +7385,8 @@ if ( material.visible === false ) continue; + sprite.onBeforeRender( renderer, scene, camera, undefined, material, undefined ); + gl.uniform1f( uniforms.alphaTest, material.alphaTest ); gl.uniformMatrix4fv( uniforms.modelViewMatrix, false, sprite.modelViewMatrix.elements ); @@ -6950,25 +7432,19 @@ state.buffers.depth.setTest( material.depthTest ); state.buffers.depth.setMask( material.depthWrite ); - if ( material.map ) { - - renderer.setTexture2D( material.map, 0 ); - - } else { - - renderer.setTexture2D( texture, 0 ); - - } + textures.setTexture2D( material.map || texture, 0 ); gl.drawElements( gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 ); + sprite.onAfterRender( renderer, scene, camera, undefined, material, undefined ); + } // restore gl state.enable( gl.CULL_FACE ); - renderer.resetGLState(); + state.reset(); }; @@ -6981,7 +7457,9 @@ gl.shaderSource( vertexShader, [ - 'precision ' + renderer.getPrecision() + ' float;', + 'precision ' + capabilities.precision + ' float;', + + '#define SHADER_NAME ' + 'SpriteMaterial', 'uniform mat4 modelViewMatrix;', 'uniform mat4 projectionMatrix;', @@ -6994,6 +7472,7 @@ 'attribute vec2 uv;', 'varying vec2 vUV;', + 'varying float fogDepth;', 'void main() {', @@ -7005,13 +7484,14 @@ 'rotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;', 'rotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;', - 'vec4 finalPosition;', + 'vec4 mvPosition;', + + 'mvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );', + 'mvPosition.xy += rotatedPosition;', - 'finalPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );', - 'finalPosition.xy += rotatedPosition;', - 'finalPosition = projectionMatrix * finalPosition;', + 'gl_Position = projectionMatrix * mvPosition;', - 'gl_Position = finalPosition;', + 'fogDepth = - mvPosition.z;', '}' @@ -7019,7 +7499,9 @@ gl.shaderSource( fragmentShader, [ - 'precision ' + renderer.getPrecision() + ' float;', + 'precision ' + capabilities.precision + ' float;', + + '#define SHADER_NAME ' + 'SpriteMaterial', 'uniform vec3 color;', 'uniform sampler2D map;', @@ -7033,33 +7515,33 @@ 'uniform float alphaTest;', 'varying vec2 vUV;', + 'varying float fogDepth;', 'void main() {', 'vec4 texture = texture2D( map, vUV );', - 'if ( texture.a < alphaTest ) discard;', - 'gl_FragColor = vec4( color * texture.xyz, texture.a * opacity );', + 'if ( gl_FragColor.a < alphaTest ) discard;', + 'if ( fogType > 0 ) {', - 'float depth = gl_FragCoord.z / gl_FragCoord.w;', 'float fogFactor = 0.0;', 'if ( fogType == 1 ) {', - 'fogFactor = smoothstep( fogNear, fogFar, depth );', + 'fogFactor = smoothstep( fogNear, fogFar, fogDepth );', '} else {', 'const float LOG2 = 1.442695;', - 'fogFactor = exp2( - fogDensity * fogDensity * depth * depth * LOG2 );', + 'fogFactor = exp2( - fogDensity * fogDensity * fogDepth * fogDepth * LOG2 );', 'fogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 );', '}', - 'gl_FragColor = mix( gl_FragColor, vec4( fogColor, gl_FragColor.w ), fogFactor );', + 'gl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );', '}', @@ -7120,7 +7602,7 @@ this.blending = NormalBlending; this.side = FrontSide; - this.shading = SmoothShading; // THREE.FlatShading, THREE.SmoothShading + this.flatShading = false; this.vertexColors = NoColors; // THREE.NoColors, THREE.VertexColors, THREE.FaceColors this.opacity = 1; @@ -7158,6 +7640,8 @@ this.visible = true; + this.userData = {}; + this.needsUpdate = true; } @@ -7166,6 +7650,8 @@ isMaterial: true, + onBeforeCompile: function () {}, + setValues: function ( values ) { if ( values === undefined ) return; @@ -7181,6 +7667,15 @@ } + // for backward compatability if shading is set in the constructor + if ( key === 'shading' ) { + + console.warn( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' ); + this.flatShading = ( newValue === FlatShading ) ? true : false; + continue; + + } + var currentValue = this[ key ]; if ( currentValue === undefined ) { @@ -7296,7 +7791,7 @@ if ( this.sizeAttenuation !== undefined ) data.sizeAttenuation = this.sizeAttenuation; if ( this.blending !== NormalBlending ) data.blending = this.blending; - if ( this.shading !== SmoothShading ) data.shading = this.shading; + if ( this.flatShading === true ) data.flatShading = this.flatShading; if ( this.side !== FrontSide ) data.side = this.side; if ( this.vertexColors !== NoColors ) data.vertexColors = this.vertexColors; @@ -7307,17 +7802,21 @@ data.depthTest = this.depthTest; data.depthWrite = this.depthWrite; + 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.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.skinning = this.skinning; - data.morphTargets = this.morphTargets; + if ( this.morphTargets === true ) data.morphTargets = true; + if ( this.skinning === true ) data.skinning = true; - data.dithering = this.dithering; + if ( this.visible === false ) data.visible = false; + if ( JSON.stringify( this.userData ) !== '{}' ) data.userData = this.userData; // TODO: Copied from Object3D.toJSON @@ -7366,7 +7865,7 @@ this.blending = source.blending; this.side = source.side; - this.shading = source.shading; + this.flatShading = source.flatShading; this.vertexColors = source.vertexColors; this.opacity = source.opacity; @@ -7394,12 +7893,13 @@ this.dithering = source.dithering; this.alphaTest = source.alphaTest; - this.premultipliedAlpha = source.premultipliedAlpha; this.overdraw = source.overdraw; this.visible = source.visible; + this.userData = JSON.parse( JSON.stringify( source.userData ) ); + this.clipShadows = source.clipShadows; this.clipIntersection = source.clipIntersection; @@ -7633,6 +8133,85 @@ }; + /** + * @author WestLangley / http://github.com/WestLangley + * + * parameters = { + * + * referencePosition: , + * nearDistance: , + * farDistance: , + * + * skinning: , + * morphTargets: , + * + * map: new THREE.Texture( ), + * + * alphaMap: new THREE.Texture( ), + * + * displacementMap: new THREE.Texture( ), + * displacementScale: , + * displacementBias: + * + * } + */ + + function MeshDistanceMaterial( parameters ) { + + Material.call( this ); + + this.type = 'MeshDistanceMaterial'; + + this.referencePosition = new Vector3(); + this.nearDistance = 1; + this.farDistance = 1000; + + this.skinning = false; + this.morphTargets = false; + + this.map = null; + + this.alphaMap = null; + + this.displacementMap = null; + this.displacementScale = 1; + this.displacementBias = 0; + + this.fog = false; + this.lights = false; + + this.setValues( parameters ); + + } + + MeshDistanceMaterial.prototype = Object.create( Material.prototype ); + MeshDistanceMaterial.prototype.constructor = MeshDistanceMaterial; + + MeshDistanceMaterial.prototype.isMeshDistanceMaterial = true; + + MeshDistanceMaterial.prototype.copy = function ( source ) { + + Material.prototype.copy.call( this, source ); + + this.referencePosition.copy( source.referencePosition ); + this.nearDistance = source.nearDistance; + this.farDistance = source.farDistance; + + this.skinning = source.skinning; + this.morphTargets = source.morphTargets; + + this.map = source.map; + + this.alphaMap = source.alphaMap; + + this.displacementMap = source.displacementMap; + this.displacementScale = source.displacementScale; + this.displacementBias = source.displacementBias; + + return this; + + }; + /** * @author bhouston / http://clara.io * @author WestLangley / http://github.com/WestLangley @@ -8181,433 +8760,98 @@ this.center.copy( sphere.center ); this.radius = sphere.radius; - return this; - - }, - - empty: function () { - - return ( this.radius <= 0 ); - - }, - - containsPoint: function ( point ) { - - return ( point.distanceToSquared( this.center ) <= ( this.radius * this.radius ) ); - - }, - - distanceToPoint: function ( point ) { - - return ( point.distanceTo( this.center ) - this.radius ); - - }, - - intersectsSphere: function ( sphere ) { - - var radiusSum = this.radius + sphere.radius; - - return sphere.center.distanceToSquared( this.center ) <= ( radiusSum * radiusSum ); - - }, - - intersectsBox: function ( box ) { - - return box.intersectsSphere( this ); - - }, - - intersectsPlane: function ( plane ) { - - // We use the following equation to compute the signed distance from - // the center of the sphere to the plane. - // - // distance = q * n - d - // - // If this distance is greater than the radius of the sphere, - // then there is no intersection. - - return Math.abs( this.center.dot( plane.normal ) - plane.constant ) <= this.radius; - - }, - - clampPoint: function ( point, optionalTarget ) { - - var deltaLengthSq = this.center.distanceToSquared( point ); - - var result = optionalTarget || new Vector3(); - - result.copy( point ); - - if ( deltaLengthSq > ( this.radius * this.radius ) ) { - - result.sub( this.center ).normalize(); - result.multiplyScalar( this.radius ).add( this.center ); - - } - - return result; - - }, - - getBoundingBox: function ( optionalTarget ) { - - var box = optionalTarget || new Box3(); - - box.set( this.center, this.center ); - box.expandByScalar( this.radius ); - - return box; - - }, - - applyMatrix4: function ( matrix ) { - - this.center.applyMatrix4( matrix ); - this.radius = this.radius * matrix.getMaxScaleOnAxis(); - - return this; - - }, - - translate: function ( offset ) { - - this.center.add( offset ); - - return this; - - }, - - equals: function ( sphere ) { - - return sphere.center.equals( this.center ) && ( sphere.radius === this.radius ); - - } - - } ); - - /** - * @author alteredq / http://alteredqualia.com/ - * @author WestLangley / http://github.com/WestLangley - * @author bhouston / http://clara.io - * @author tschw - */ - - function Matrix3() { - - this.elements = [ - - 1, 0, 0, - 0, 1, 0, - 0, 0, 1 - - ]; - - if ( arguments.length > 0 ) { - - console.error( 'THREE.Matrix3: the constructor no longer reads arguments. use .set() instead.' ); - - } - - } - - Object.assign( Matrix3.prototype, { - - isMatrix3: true, - - set: function ( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) { - - 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; - - return this; - - }, - - identity: function () { - - this.set( - - 1, 0, 0, - 0, 1, 0, - 0, 0, 1 - - ); - - return this; - - }, - - clone: function () { - - return new this.constructor().fromArray( this.elements ); - - }, - - copy: function ( m ) { - - var te = this.elements; - var me = m.elements; - - 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; - - }, - - setFromMatrix4: function ( m ) { - - var me = m.elements; - - this.set( - - me[ 0 ], me[ 4 ], me[ 8 ], - me[ 1 ], me[ 5 ], me[ 9 ], - me[ 2 ], me[ 6 ], me[ 10 ] - - ); - - return this; - - }, - - applyToBufferAttribute: function () { - - var v1 = new Vector3(); - - return function applyToBufferAttribute( attribute ) { - - for ( var i = 0, l = attribute.count; i < l; i ++ ) { - - v1.x = attribute.getX( i ); - v1.y = attribute.getY( i ); - v1.z = attribute.getZ( i ); - - v1.applyMatrix3( this ); - - attribute.setXYZ( i, v1.x, v1.y, v1.z ); - - } - - return attribute; - - }; - - }(), - - multiply: function ( m ) { - - return this.multiplyMatrices( this, m ); - - }, - - premultiply: function ( m ) { - - return this.multiplyMatrices( m, this ); - - }, - - multiplyMatrices: function ( a, b ) { - - var ae = a.elements; - var be = b.elements; - var te = this.elements; - - 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 ]; - - 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 ]; - - te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31; - te[ 3 ] = a11 * b12 + a12 * b22 + a13 * b32; - te[ 6 ] = a11 * b13 + a12 * b23 + a13 * b33; - - te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31; - te[ 4 ] = a21 * b12 + a22 * b22 + a23 * b32; - te[ 7 ] = a21 * b13 + a22 * b23 + a23 * b33; - - 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; - - }, - - multiplyScalar: function ( s ) { - - var te = this.elements; - - 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; - - return this; - - }, - - determinant: function () { - - var te = this.elements; - - 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 ]; - - return a * e * i - a * f * h - b * d * i + b * f * g + c * d * h - c * e * g; - - }, - - getInverse: function ( matrix, throwOnDegenerate ) { - - if ( matrix && matrix.isMatrix4 ) { - - console.error( "THREE.Matrix3.getInverse no longer takes a Matrix4 argument." ); - - } - - 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 ], - - t11 = n33 * n22 - n32 * n23, - t12 = n32 * n13 - n33 * n12, - t13 = n23 * n12 - n22 * n13, - - det = n11 * t11 + n21 * t12 + n31 * t13; - - if ( det === 0 ) { - - var msg = "THREE.Matrix3.getInverse(): can't invert matrix, determinant is 0"; - - if ( throwOnDegenerate === true ) { - - throw new Error( msg ); - - } else { + return this; - console.warn( msg ); + }, - } + empty: function () { - return this.identity(); + return ( this.radius <= 0 ); - } + }, - var detInv = 1 / det; + containsPoint: function ( point ) { - te[ 0 ] = t11 * detInv; - te[ 1 ] = ( n31 * n23 - n33 * n21 ) * detInv; - te[ 2 ] = ( n32 * n21 - n31 * n22 ) * detInv; + return ( point.distanceToSquared( this.center ) <= ( this.radius * this.radius ) ); - te[ 3 ] = t12 * detInv; - te[ 4 ] = ( n33 * n11 - n31 * n13 ) * detInv; - te[ 5 ] = ( n31 * n12 - n32 * n11 ) * detInv; + }, - te[ 6 ] = t13 * detInv; - te[ 7 ] = ( n21 * n13 - n23 * n11 ) * detInv; - te[ 8 ] = ( n22 * n11 - n21 * n12 ) * detInv; + distanceToPoint: function ( point ) { - return this; + return ( point.distanceTo( this.center ) - this.radius ); }, - transpose: function () { - - var tmp, m = this.elements; + intersectsSphere: function ( sphere ) { - 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; + var radiusSum = this.radius + sphere.radius; - return this; + return sphere.center.distanceToSquared( this.center ) <= ( radiusSum * radiusSum ); }, - getNormalMatrix: function ( matrix4 ) { + intersectsBox: function ( box ) { - return this.setFromMatrix4( matrix4 ).getInverse( this ).transpose(); + return box.intersectsSphere( this ); }, - transposeIntoArray: function ( r ) { + intersectsPlane: function ( plane ) { - var m = this.elements; + return Math.abs( plane.distanceToPoint( this.center ) ) <= this.radius; - 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 ]; + }, - return this; + clampPoint: function ( point, optionalTarget ) { - }, + var deltaLengthSq = this.center.distanceToSquared( point ); - equals: function ( matrix ) { + var result = optionalTarget || new Vector3(); - var te = this.elements; - var me = matrix.elements; + result.copy( point ); - for ( var i = 0; i < 9; i ++ ) { + if ( deltaLengthSq > ( this.radius * this.radius ) ) { - if ( te[ i ] !== me[ i ] ) return false; + result.sub( this.center ).normalize(); + result.multiplyScalar( this.radius ).add( this.center ); } - return true; + return result; }, - fromArray: function ( array, offset ) { + getBoundingBox: function ( optionalTarget ) { - if ( offset === undefined ) offset = 0; + var box = optionalTarget || new Box3(); - for ( var i = 0; i < 9; i ++ ) { + box.set( this.center, this.center ); + box.expandByScalar( this.radius ); - this.elements[ i ] = array[ i + offset ]; + return box; - } + }, + + applyMatrix4: function ( matrix ) { + + this.center.applyMatrix4( matrix ); + this.radius = this.radius * matrix.getMaxScaleOnAxis(); return this; }, - toArray: function ( array, offset ) { - - if ( array === undefined ) array = []; - if ( offset === undefined ) offset = 0; + translate: function ( offset ) { - var te = this.elements; + this.center.add( offset ); - 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 ]; + equals: function ( sphere ) { - return array; + return sphere.center.equals( this.center ) && ( sphere.radius === this.radius ); } @@ -8619,6 +8863,8 @@ function Plane( normal, constant ) { + // normal is assumed to be normalized + this.normal = ( normal !== undefined ) ? normal : new Vector3( 1, 0, 0 ); this.constant = ( constant !== undefined ) ? constant : 0; @@ -8647,7 +8893,7 @@ setFromNormalAndCoplanarPoint: function ( normal, point ) { this.normal.copy( normal ); - this.constant = - point.dot( this.normal ); // must be this.normal, not normal, as this.normal is normalized + this.constant = - point.dot( this.normal ); return this; @@ -8722,16 +8968,9 @@ projectPoint: function ( point, optionalTarget ) { - return this.orthoPoint( point, optionalTarget ).sub( point ).negate(); - - }, - - orthoPoint: function ( point, optionalTarget ) { - - var perpendicularMagnitude = this.distanceToPoint( point ); - var result = optionalTarget || new Vector3(); - return result.copy( this.normal ).multiplyScalar( perpendicularMagnitude ); + + return result.copy( this.normal ).multiplyScalar( - this.distanceToPoint( point ) ).add( point ); }, @@ -8801,6 +9040,7 @@ coplanarPoint: function ( optionalTarget ) { var result = optionalTarget || new Vector3(); + return result.copy( this.normal ).multiplyScalar( - this.constant ); }, @@ -8812,14 +9052,12 @@ return function applyMatrix4( matrix, optionalNormalMatrix ) { + var normalMatrix = optionalNormalMatrix || m1.getNormalMatrix( matrix ); + var referencePoint = this.coplanarPoint( v1 ).applyMatrix4( matrix ); - // transform normal based on theory here: - // http://www.songho.ca/opengl/gl_normaltransform.html - var normalMatrix = optionalNormalMatrix || m1.getNormalMatrix( matrix ); var normal = this.normal.applyMatrix3( normalMatrix ).normalize(); - // recalculate constant (like in setFromNormalAndCoplanarPoint) this.constant = - referencePoint.dot( normal ); return this; @@ -8830,7 +9068,7 @@ translate: function ( offset ) { - this.constant = this.constant - offset.dot( this.normal ); + this.constant -= offset.dot( this.normal ); return this; @@ -9044,17 +9282,13 @@ * @author mrdoob / http://mrdoob.com/ */ - function WebGLShadowMap( _renderer, _lights, _objects, capabilities ) { + function WebGLShadowMap( _renderer, _objects, maxTextureSize ) { - var _gl = _renderer.context, - _state = _renderer.state, - _frustum = new Frustum(), + var _frustum = new Frustum(), _projScreenMatrix = new Matrix4(), - _lightShadows = _lights.shadows, - _shadowMapSize = new Vector2(), - _maxShadowMapSize = new Vector2( capabilities.maxTextureSize, capabilities.maxTextureSize ), + _maxShadowMapSize = new Vector2( maxTextureSize, maxTextureSize ), _lookTarget = new Vector3(), _lightPositionWorld = new Vector3(), @@ -9086,34 +9320,29 @@ // init - var depthMaterialTemplate = new MeshDepthMaterial(); - depthMaterialTemplate.depthPacking = RGBADepthPacking; - depthMaterialTemplate.clipping = true; - - var distanceShader = ShaderLib[ "distanceRGBA" ]; - var distanceUniforms = UniformsUtils.clone( distanceShader.uniforms ); - for ( var i = 0; i !== _NumberOfMaterialVariants; ++ i ) { var useMorphing = ( i & _MorphingFlag ) !== 0; var useSkinning = ( i & _SkinningFlag ) !== 0; - var depthMaterial = depthMaterialTemplate.clone(); - depthMaterial.morphTargets = useMorphing; - depthMaterial.skinning = useSkinning; + var depthMaterial = new MeshDepthMaterial( { + + depthPacking: RGBADepthPacking, + + morphTargets: useMorphing, + skinning: useSkinning + + } ); _depthMaterials[ i ] = depthMaterial; - var distanceMaterial = new ShaderMaterial( { - defines: { - 'USE_SHADOWMAP': '' - }, - uniforms: distanceUniforms, - vertexShader: distanceShader.vertexShader, - fragmentShader: distanceShader.fragmentShader, + // + + var distanceMaterial = new MeshDistanceMaterial( { + morphTargets: useMorphing, - skinning: useSkinning, - clipping: true + skinning: useSkinning + } ); _distanceMaterials[ i ] = distanceMaterial; @@ -9134,12 +9363,16 @@ this.renderReverseSided = true; this.renderSingleSided = true; - this.render = function ( scene, camera ) { + this.render = function ( lights, scene, camera ) { if ( scope.enabled === false ) return; if ( scope.autoUpdate === false && scope.needsUpdate === false ) return; - if ( _lightShadows.length === 0 ) return; + if ( lights.length === 0 ) return; + + // TODO Clean up (needed in case of contextlost) + var _gl = _renderer.context; + var _state = _renderer.state; // Set GL state for depth map. _state.disable( _gl.BLEND ); @@ -9151,9 +9384,9 @@ var faceCount; - for ( var i = 0, il = _lightShadows.length; i < il; i ++ ) { + for ( var i = 0, il = lights.length; i < il; i ++ ) { - var light = _lightShadows[ i ]; + var light = lights[ i ]; var shadow = light.shadow; var isPointLight = light && light.isPointLight; @@ -9169,850 +9402,467 @@ _shadowMapSize.copy( shadow.mapSize ); _shadowMapSize.min( _maxShadowMapSize ); - if ( isPointLight ) { - - var vpWidth = _shadowMapSize.x; - var vpHeight = _shadowMapSize.y; - - // These viewports map a cube-map onto a 2D texture with the - // following orientation: - // - // xzXZ - // y Y - // - // X - Positive x direction - // x - Negative x direction - // Y - Positive y direction - // y - Negative y direction - // Z - Positive z direction - // z - Negative z direction - - // positive X - cube2DViewPorts[ 0 ].set( vpWidth * 2, vpHeight, vpWidth, vpHeight ); - // negative X - cube2DViewPorts[ 1 ].set( 0, vpHeight, vpWidth, vpHeight ); - // positive Z - cube2DViewPorts[ 2 ].set( vpWidth * 3, vpHeight, vpWidth, vpHeight ); - // negative Z - cube2DViewPorts[ 3 ].set( vpWidth, vpHeight, vpWidth, vpHeight ); - // positive Y - cube2DViewPorts[ 4 ].set( vpWidth * 3, 0, vpWidth, vpHeight ); - // negative Y - cube2DViewPorts[ 5 ].set( vpWidth, 0, vpWidth, vpHeight ); - - _shadowMapSize.x *= 4.0; - _shadowMapSize.y *= 2.0; - - } - - if ( shadow.map === null ) { - - var pars = { minFilter: NearestFilter, magFilter: NearestFilter, format: RGBAFormat }; - - shadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars ); - shadow.map.texture.name = light.name + ".shadowMap"; - - shadowCamera.updateProjectionMatrix(); - - } - - if ( shadow.isSpotLightShadow ) { - - shadow.update( light ); - - } - - var shadowMap = shadow.map; - var shadowMatrix = shadow.matrix; - - _lightPositionWorld.setFromMatrixPosition( light.matrixWorld ); - shadowCamera.position.copy( _lightPositionWorld ); - - if ( isPointLight ) { - - faceCount = 6; - - // for point lights we set the shadow matrix to be a translation-only matrix - // equal to inverse of the light's position - - shadowMatrix.makeTranslation( - _lightPositionWorld.x, - _lightPositionWorld.y, - _lightPositionWorld.z ); - - } else { - - faceCount = 1; - - _lookTarget.setFromMatrixPosition( light.target.matrixWorld ); - shadowCamera.lookAt( _lookTarget ); - shadowCamera.updateMatrixWorld(); - shadowCamera.matrixWorldInverse.getInverse( shadowCamera.matrixWorld ); - - // compute shadow matrix - - shadowMatrix.set( - 0.5, 0.0, 0.0, 0.5, - 0.0, 0.5, 0.0, 0.5, - 0.0, 0.0, 0.5, 0.5, - 0.0, 0.0, 0.0, 1.0 - ); - - shadowMatrix.multiply( shadowCamera.projectionMatrix ); - shadowMatrix.multiply( shadowCamera.matrixWorldInverse ); - - } - - _renderer.setRenderTarget( shadowMap ); - _renderer.clear(); - - // render shadow map for each cube face (if omni-directional) or - // run a single pass if not - - for ( var face = 0; face < faceCount; face ++ ) { - - if ( isPointLight ) { - - _lookTarget.copy( shadowCamera.position ); - _lookTarget.add( cubeDirections[ face ] ); - shadowCamera.up.copy( cubeUps[ face ] ); - shadowCamera.lookAt( _lookTarget ); - shadowCamera.updateMatrixWorld(); - shadowCamera.matrixWorldInverse.getInverse( shadowCamera.matrixWorld ); - - var vpDimensions = cube2DViewPorts[ face ]; - _state.viewport( vpDimensions ); - - } - - // update camera matrices and frustum - - _projScreenMatrix.multiplyMatrices( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse ); - _frustum.setFromMatrix( _projScreenMatrix ); - - // set object matrices & frustum culling - - renderObject( scene, camera, shadowCamera, isPointLight ); - - } - - } - - // Restore GL state. - var clearColor = _renderer.getClearColor(); - var clearAlpha = _renderer.getClearAlpha(); - _renderer.setClearColor( clearColor, clearAlpha ); - - scope.needsUpdate = false; - - }; - - function getDepthMaterial( object, material, isPointLight, lightPositionWorld ) { - - var geometry = object.geometry; - - var result = null; - - var materialVariants = _depthMaterials; - var customMaterial = object.customDepthMaterial; - - if ( isPointLight ) { - - materialVariants = _distanceMaterials; - customMaterial = object.customDistanceMaterial; - - } - - if ( ! customMaterial ) { - - var useMorphing = false; - - if ( material.morphTargets ) { - - if ( geometry && geometry.isBufferGeometry ) { - - useMorphing = geometry.morphAttributes && geometry.morphAttributes.position && geometry.morphAttributes.position.length > 0; - - } else if ( geometry && geometry.isGeometry ) { - - useMorphing = geometry.morphTargets && geometry.morphTargets.length > 0; - - } - - } - - if ( object.isSkinnedMesh && material.skinning === false ) { - - console.warn( 'THREE.WebGLShadowMap: THREE.SkinnedMesh with material.skinning set to false:', object ); - - } - - var useSkinning = object.isSkinnedMesh && material.skinning; - - var variantIndex = 0; - - if ( useMorphing ) variantIndex |= _MorphingFlag; - if ( useSkinning ) variantIndex |= _SkinningFlag; - - result = materialVariants[ variantIndex ]; - - } else { - - result = customMaterial; - - } - - if ( _renderer.localClippingEnabled && - material.clipShadows === true && - material.clippingPlanes.length !== 0 ) { - - // in this case we need a unique material instance reflecting the - // appropriate state - - var keyA = result.uuid, keyB = material.uuid; - - var materialsForVariant = _materialCache[ keyA ]; - - if ( materialsForVariant === undefined ) { - - materialsForVariant = {}; - _materialCache[ keyA ] = materialsForVariant; - - } - - var cachedMaterial = materialsForVariant[ keyB ]; - - if ( cachedMaterial === undefined ) { - - cachedMaterial = result.clone(); - materialsForVariant[ keyB ] = cachedMaterial; - - } - - result = cachedMaterial; - - } - - result.visible = material.visible; - result.wireframe = material.wireframe; - - var side = material.side; - - if ( scope.renderSingleSided && side == DoubleSide ) { - - side = FrontSide; - - } - - if ( scope.renderReverseSided ) { - - if ( side === FrontSide ) side = BackSide; - else if ( side === BackSide ) side = FrontSide; - - } - - result.side = side; - - result.clipShadows = material.clipShadows; - result.clippingPlanes = material.clippingPlanes; - - result.wireframeLinewidth = material.wireframeLinewidth; - result.linewidth = material.linewidth; - - if ( isPointLight && result.uniforms.lightPos !== undefined ) { - - result.uniforms.lightPos.value.copy( lightPositionWorld ); - - } - - return result; - - } - - function renderObject( object, camera, shadowCamera, isPointLight ) { - - if ( object.visible === false ) return; - - var visible = object.layers.test( camera.layers ); - - if ( visible && ( object.isMesh || object.isLine || object.isPoints ) ) { - - if ( object.castShadow && ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) ) { - - object.modelViewMatrix.multiplyMatrices( shadowCamera.matrixWorldInverse, object.matrixWorld ); - - var geometry = _objects.update( object ); - var material = object.material; - - if ( Array.isArray( material ) ) { - - var groups = geometry.groups; - - for ( var k = 0, kl = groups.length; k < kl; k ++ ) { - - var group = groups[ k ]; - var groupMaterial = material[ group.materialIndex ]; - - if ( groupMaterial && groupMaterial.visible ) { - - var depthMaterial = getDepthMaterial( object, groupMaterial, isPointLight, _lightPositionWorld ); - _renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, group ); - - } - - } - - } else if ( material.visible ) { - - var depthMaterial = getDepthMaterial( object, material, isPointLight, _lightPositionWorld ); - _renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, null ); - - } - - } - - } - - var children = object.children; - - for ( var i = 0, l = children.length; i < l; i ++ ) { - - renderObject( children[ i ], camera, shadowCamera, isPointLight ); - - } - - } - - } - - /** - * @author bhouston / http://clara.io - */ - - function Ray( origin, direction ) { - - this.origin = ( origin !== undefined ) ? origin : new Vector3(); - this.direction = ( direction !== undefined ) ? direction : new Vector3(); - - } - - Object.assign( Ray.prototype, { - - set: function ( origin, direction ) { - - this.origin.copy( origin ); - this.direction.copy( direction ); - - return this; - - }, - - clone: function () { - - return new this.constructor().copy( this ); - - }, - - copy: function ( ray ) { - - this.origin.copy( ray.origin ); - this.direction.copy( ray.direction ); - - return this; - - }, - - at: function ( t, optionalTarget ) { - - var result = optionalTarget || new Vector3(); - - return result.copy( this.direction ).multiplyScalar( t ).add( this.origin ); - - }, - - lookAt: function ( v ) { - - this.direction.copy( v ).sub( this.origin ).normalize(); - - return this; - - }, - - recast: function () { - - var v1 = new Vector3(); - - return function recast( t ) { - - this.origin.copy( this.at( t, v1 ) ); - - return this; - - }; - - }(), - - closestPointToPoint: function ( point, optionalTarget ) { - - var result = optionalTarget || new Vector3(); - result.subVectors( point, this.origin ); - var directionDistance = result.dot( this.direction ); - - if ( directionDistance < 0 ) { - - return result.copy( this.origin ); - - } + if ( isPointLight ) { - return result.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin ); + var vpWidth = _shadowMapSize.x; + var vpHeight = _shadowMapSize.y; - }, + // These viewports map a cube-map onto a 2D texture with the + // following orientation: + // + // xzXZ + // y Y + // + // X - Positive x direction + // x - Negative x direction + // Y - Positive y direction + // y - Negative y direction + // Z - Positive z direction + // z - Negative z direction - distanceToPoint: function ( point ) { + // positive X + cube2DViewPorts[ 0 ].set( vpWidth * 2, vpHeight, vpWidth, vpHeight ); + // negative X + cube2DViewPorts[ 1 ].set( 0, vpHeight, vpWidth, vpHeight ); + // positive Z + cube2DViewPorts[ 2 ].set( vpWidth * 3, vpHeight, vpWidth, vpHeight ); + // negative Z + cube2DViewPorts[ 3 ].set( vpWidth, vpHeight, vpWidth, vpHeight ); + // positive Y + cube2DViewPorts[ 4 ].set( vpWidth * 3, 0, vpWidth, vpHeight ); + // negative Y + cube2DViewPorts[ 5 ].set( vpWidth, 0, vpWidth, vpHeight ); - return Math.sqrt( this.distanceSqToPoint( point ) ); + _shadowMapSize.x *= 4.0; + _shadowMapSize.y *= 2.0; - }, + } - distanceSqToPoint: function () { + if ( shadow.map === null ) { - var v1 = new Vector3(); + var pars = { minFilter: NearestFilter, magFilter: NearestFilter, format: RGBAFormat }; - return function distanceSqToPoint( point ) { + shadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars ); + shadow.map.texture.name = light.name + ".shadowMap"; - var directionDistance = v1.subVectors( point, this.origin ).dot( this.direction ); + shadowCamera.updateProjectionMatrix(); - // point behind the ray + } - if ( directionDistance < 0 ) { + if ( shadow.isSpotLightShadow ) { - return this.origin.distanceToSquared( point ); + shadow.update( light ); } - v1.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin ); - - return v1.distanceToSquared( point ); + var shadowMap = shadow.map; + var shadowMatrix = shadow.matrix; - }; + _lightPositionWorld.setFromMatrixPosition( light.matrixWorld ); + shadowCamera.position.copy( _lightPositionWorld ); - }(), + if ( isPointLight ) { - distanceSqToSegment: function () { + faceCount = 6; - var segCenter = new Vector3(); - var segDir = new Vector3(); - var diff = new Vector3(); + // for point lights we set the shadow matrix to be a translation-only matrix + // equal to inverse of the light's position - return function distanceSqToSegment( v0, v1, optionalPointOnRay, optionalPointOnSegment ) { + shadowMatrix.makeTranslation( - _lightPositionWorld.x, - _lightPositionWorld.y, - _lightPositionWorld.z ); - // 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 + } else { - segCenter.copy( v0 ).add( v1 ).multiplyScalar( 0.5 ); - segDir.copy( v1 ).sub( v0 ).normalize(); - diff.copy( this.origin ).sub( segCenter ); + faceCount = 1; - 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; + _lookTarget.setFromMatrixPosition( light.target.matrixWorld ); + shadowCamera.lookAt( _lookTarget ); + shadowCamera.updateMatrixWorld(); - if ( det > 0 ) { + // compute shadow matrix - // The ray and segment are not parallel. + shadowMatrix.set( + 0.5, 0.0, 0.0, 0.5, + 0.0, 0.5, 0.0, 0.5, + 0.0, 0.0, 0.5, 0.5, + 0.0, 0.0, 0.0, 1.0 + ); - s0 = a01 * b1 - b0; - s1 = a01 * b0 - b1; - extDet = segExtent * det; + shadowMatrix.multiply( shadowCamera.projectionMatrix ); + shadowMatrix.multiply( shadowCamera.matrixWorldInverse ); - if ( s0 >= 0 ) { + } - if ( s1 >= - extDet ) { + _renderer.setRenderTarget( shadowMap ); + _renderer.clear(); - if ( s1 <= extDet ) { + // render shadow map for each cube face (if omni-directional) or + // run a single pass if not - // region 0 - // Minimum at interior points of ray and segment. + for ( var face = 0; face < faceCount; face ++ ) { - var invDet = 1 / det; - s0 *= invDet; - s1 *= invDet; - sqrDist = s0 * ( s0 + a01 * s1 + 2 * b0 ) + s1 * ( a01 * s0 + s1 + 2 * b1 ) + c; + if ( isPointLight ) { - } else { + _lookTarget.copy( shadowCamera.position ); + _lookTarget.add( cubeDirections[ face ] ); + shadowCamera.up.copy( cubeUps[ face ] ); + shadowCamera.lookAt( _lookTarget ); + shadowCamera.updateMatrixWorld(); - // region 1 + var vpDimensions = cube2DViewPorts[ face ]; + _state.viewport( vpDimensions ); - s1 = segExtent; - s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); - sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; + } - } + // update camera matrices and frustum - } else { + _projScreenMatrix.multiplyMatrices( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse ); + _frustum.setFromMatrix( _projScreenMatrix ); - // region 5 + // set object matrices & frustum culling - s1 = - segExtent; - s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); - sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; + renderObject( scene, camera, shadowCamera, isPointLight ); - } + } - } else { + } - if ( s1 <= - extDet ) { + scope.needsUpdate = false; - // region 4 + }; - 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; + function getDepthMaterial( object, material, isPointLight, lightPositionWorld, shadowCameraNear, shadowCameraFar ) { - } else if ( s1 <= extDet ) { + var geometry = object.geometry; - // region 3 + var result = null; - s0 = 0; - s1 = Math.min( Math.max( - segExtent, - b1 ), segExtent ); - sqrDist = s1 * ( s1 + 2 * b1 ) + c; + var materialVariants = _depthMaterials; + var customMaterial = object.customDepthMaterial; - } else { + if ( isPointLight ) { - // region 2 + materialVariants = _distanceMaterials; + customMaterial = object.customDistanceMaterial; - 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; + } - } + if ( ! customMaterial ) { - } + var useMorphing = false; - } else { + if ( material.morphTargets ) { - // Ray and segment are parallel. + if ( geometry && geometry.isBufferGeometry ) { - s1 = ( a01 > 0 ) ? - segExtent : segExtent; - s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); - sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; + useMorphing = geometry.morphAttributes && geometry.morphAttributes.position && geometry.morphAttributes.position.length > 0; - } + } else if ( geometry && geometry.isGeometry ) { - if ( optionalPointOnRay ) { + useMorphing = geometry.morphTargets && geometry.morphTargets.length > 0; - optionalPointOnRay.copy( this.direction ).multiplyScalar( s0 ).add( this.origin ); + } } - if ( optionalPointOnSegment ) { + if ( object.isSkinnedMesh && material.skinning === false ) { - optionalPointOnSegment.copy( segDir ).multiplyScalar( s1 ).add( segCenter ); + console.warn( 'THREE.WebGLShadowMap: THREE.SkinnedMesh with material.skinning set to false:', object ); } - return sqrDist; + var useSkinning = object.isSkinnedMesh && material.skinning; - }; + var variantIndex = 0; - }(), + if ( useMorphing ) variantIndex |= _MorphingFlag; + if ( useSkinning ) variantIndex |= _SkinningFlag; - intersectSphere: function () { + result = materialVariants[ variantIndex ]; - var v1 = new Vector3(); + } else { - return function intersectSphere( sphere, optionalTarget ) { + result = customMaterial; - v1.subVectors( sphere.center, this.origin ); - var tca = v1.dot( this.direction ); - var d2 = v1.dot( v1 ) - tca * tca; - var radius2 = sphere.radius * sphere.radius; + } - if ( d2 > radius2 ) return null; + if ( _renderer.localClippingEnabled && + material.clipShadows === true && + material.clippingPlanes.length !== 0 ) { - var thc = Math.sqrt( radius2 - d2 ); + // in this case we need a unique material instance reflecting the + // appropriate state - // t0 = first intersect point - entrance on front of sphere - var t0 = tca - thc; + var keyA = result.uuid, keyB = material.uuid; - // t1 = second intersect point - exit point on back of sphere - var t1 = tca + thc; + var materialsForVariant = _materialCache[ keyA ]; - // test to see if both t0 and t1 are behind the ray - if so, return null - if ( t0 < 0 && t1 < 0 ) return null; + if ( materialsForVariant === undefined ) { - // 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, optionalTarget ); + materialsForVariant = {}; + _materialCache[ keyA ] = materialsForVariant; - // else t0 is in front of the ray, so return the first collision point scaled by t0 - return this.at( t0, optionalTarget ); + } - }; + var cachedMaterial = materialsForVariant[ keyB ]; - }(), + if ( cachedMaterial === undefined ) { - intersectsSphere: function ( sphere ) { + cachedMaterial = result.clone(); + materialsForVariant[ keyB ] = cachedMaterial; - return this.distanceToPoint( sphere.center ) <= sphere.radius; + } - }, + result = cachedMaterial; - distanceToPlane: function ( plane ) { + } - var denominator = plane.normal.dot( this.direction ); + result.visible = material.visible; + result.wireframe = material.wireframe; - if ( denominator === 0 ) { + var side = material.side; - // line is coplanar, return origin - if ( plane.distanceToPoint( this.origin ) === 0 ) { + if ( scope.renderSingleSided && side == DoubleSide ) { - return 0; + side = FrontSide; - } + } - // Null is preferable to undefined since undefined means.... it is undefined + if ( scope.renderReverseSided ) { - return null; + if ( side === FrontSide ) side = BackSide; + else if ( side === BackSide ) side = FrontSide; } - var t = - ( this.origin.dot( plane.normal ) + plane.constant ) / denominator; - - // Return if the ray never intersects the plane + result.side = side; - return t >= 0 ? t : null; + result.clipShadows = material.clipShadows; + result.clippingPlanes = material.clippingPlanes; + result.clipIntersection = material.clipIntersection; - }, + result.wireframeLinewidth = material.wireframeLinewidth; + result.linewidth = material.linewidth; - intersectPlane: function ( plane, optionalTarget ) { + if ( isPointLight && result.isMeshDistanceMaterial ) { - var t = this.distanceToPlane( plane ); + result.referencePosition.copy( lightPositionWorld ); + result.nearDistance = shadowCameraNear; + result.farDistance = shadowCameraFar; - if ( t === null ) { + } - return null; + return result; - } + } - return this.at( t, optionalTarget ); + function renderObject( object, camera, shadowCamera, isPointLight ) { - }, + if ( object.visible === false ) return; - intersectsPlane: function ( plane ) { + var visible = object.layers.test( camera.layers ); - // check if the ray lies on the plane first + if ( visible && ( object.isMesh || object.isLine || object.isPoints ) ) { - var distToPoint = plane.distanceToPoint( this.origin ); + if ( object.castShadow && ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) ) { - if ( distToPoint === 0 ) { + object.modelViewMatrix.multiplyMatrices( shadowCamera.matrixWorldInverse, object.matrixWorld ); - return true; + var geometry = _objects.update( object ); + var material = object.material; - } + if ( Array.isArray( material ) ) { - var denominator = plane.normal.dot( this.direction ); + var groups = geometry.groups; - if ( denominator * distToPoint < 0 ) { + for ( var k = 0, kl = groups.length; k < kl; k ++ ) { - return true; + var group = groups[ k ]; + var groupMaterial = material[ group.materialIndex ]; - } + if ( groupMaterial && groupMaterial.visible ) { - // ray origin is behind the plane (and is pointing behind it) + var depthMaterial = getDepthMaterial( object, groupMaterial, isPointLight, _lightPositionWorld, shadowCamera.near, shadowCamera.far ); + _renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, group ); - return false; + } - }, + } - intersectBox: function ( box, optionalTarget ) { + } else if ( material.visible ) { - var tmin, tmax, tymin, tymax, tzmin, tzmax; + var depthMaterial = getDepthMaterial( object, material, isPointLight, _lightPositionWorld, shadowCamera.near, shadowCamera.far ); + _renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, null ); - var invdirx = 1 / this.direction.x, - invdiry = 1 / this.direction.y, - invdirz = 1 / this.direction.z; + } - var origin = this.origin; + } - if ( invdirx >= 0 ) { + } - tmin = ( box.min.x - origin.x ) * invdirx; - tmax = ( box.max.x - origin.x ) * invdirx; + var children = object.children; - } else { + for ( var i = 0, l = children.length; i < l; i ++ ) { - tmin = ( box.max.x - origin.x ) * invdirx; - tmax = ( box.min.x - origin.x ) * invdirx; + renderObject( children[ i ], camera, shadowCamera, isPointLight ); } - if ( invdiry >= 0 ) { + } - tymin = ( box.min.y - origin.y ) * invdiry; - tymax = ( box.max.y - origin.y ) * invdiry; + } - } else { + /** + * @author mrdoob / http://mrdoob.com/ + */ - tymin = ( box.max.y - origin.y ) * invdiry; - tymax = ( box.min.y - origin.y ) * invdiry; + function WebGLAttributes( gl ) { - } + var buffers = {}; - if ( ( tmin > tymax ) || ( tymin > tmax ) ) return null; + function createBuffer( attribute, bufferType ) { - // These lines also handle the case where tmin or tmax is NaN - // (result of 0 * Infinity). x !== x returns true if x is NaN + var array = attribute.array; + var usage = attribute.dynamic ? gl.DYNAMIC_DRAW : gl.STATIC_DRAW; - if ( tymin > tmin || tmin !== tmin ) tmin = tymin; + var buffer = gl.createBuffer(); - if ( tymax < tmax || tmax !== tmax ) tmax = tymax; + gl.bindBuffer( bufferType, buffer ); + gl.bufferData( bufferType, array, usage ); - if ( invdirz >= 0 ) { + attribute.onUploadCallback(); - tzmin = ( box.min.z - origin.z ) * invdirz; - tzmax = ( box.max.z - origin.z ) * invdirz; + var type = gl.FLOAT; - } else { + if ( array instanceof Float32Array ) { - tzmin = ( box.max.z - origin.z ) * invdirz; - tzmax = ( box.min.z - origin.z ) * invdirz; + type = gl.FLOAT; - } + } else if ( array instanceof Float64Array ) { - if ( ( tmin > tzmax ) || ( tzmin > tmax ) ) return null; + console.warn( 'THREE.WebGLAttributes: Unsupported data buffer format: Float64Array.' ); - if ( tzmin > tmin || tmin !== tmin ) tmin = tzmin; + } else if ( array instanceof Uint16Array ) { - if ( tzmax < tmax || tmax !== tmax ) tmax = tzmax; + type = gl.UNSIGNED_SHORT; - //return point closest to the ray (positive side) + } else if ( array instanceof Int16Array ) { - if ( tmax < 0 ) return null; + type = gl.SHORT; - return this.at( tmin >= 0 ? tmin : tmax, optionalTarget ); + } else if ( array instanceof Uint32Array ) { - }, + type = gl.UNSIGNED_INT; - intersectsBox: ( function () { + } else if ( array instanceof Int32Array ) { - var v = new Vector3(); + type = gl.INT; - return function intersectsBox( box ) { + } else if ( array instanceof Int8Array ) { - return this.intersectBox( box, v ) !== null; + type = gl.BYTE; + + } else if ( array instanceof Uint8Array ) { + + type = gl.UNSIGNED_BYTE; + + } + return { + buffer: buffer, + type: type, + bytesPerElement: array.BYTES_PER_ELEMENT, + version: attribute.version }; - } )(), + } - intersectTriangle: function () { + function updateBuffer( buffer, attribute, bufferType ) { - // Compute the offset origin, edges, and normal. - var diff = new Vector3(); - var edge1 = new Vector3(); - var edge2 = new Vector3(); - var normal = new Vector3(); + var array = attribute.array; + var updateRange = attribute.updateRange; - return function intersectTriangle( a, b, c, backfaceCulling, optionalTarget ) { + gl.bindBuffer( bufferType, buffer ); - // from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteIntrRay3Triangle3.h + if ( attribute.dynamic === false ) { - edge1.subVectors( b, a ); - edge2.subVectors( c, a ); - normal.crossVectors( edge1, edge2 ); + gl.bufferData( bufferType, array, gl.STATIC_DRAW ); - // 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; + } else if ( updateRange.count === - 1 ) { - if ( DdN > 0 ) { + // Not using update ranges - if ( backfaceCulling ) return null; - sign = 1; + gl.bufferSubData( bufferType, 0, array ); - } else if ( DdN < 0 ) { + } else if ( updateRange.count === 0 ) { - sign = - 1; - DdN = - DdN; + console.error( 'THREE.WebGLObjects.updateBuffer: dynamic THREE.BufferAttribute marked as needsUpdate but updateRange.count is 0, ensure you are using set methods or updating manually.' ); - } else { + } else { - return null; + gl.bufferSubData( bufferType, updateRange.offset * array.BYTES_PER_ELEMENT, + array.subarray( updateRange.offset, updateRange.offset + updateRange.count ) ); - } + updateRange.count = -1; // reset range - diff.subVectors( this.origin, a ); - var DdQxE2 = sign * this.direction.dot( edge2.crossVectors( diff, edge2 ) ); + } - // b1 < 0, no intersection - if ( DdQxE2 < 0 ) { + } - return null; + // - } + function get( attribute ) { - var DdE1xQ = sign * this.direction.dot( edge1.cross( diff ) ); + if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data; - // b2 < 0, no intersection - if ( DdE1xQ < 0 ) { + return buffers[ attribute.uuid ]; - return null; + } - } + function remove( attribute ) { - // b1+b2 > 1, no intersection - if ( DdQxE2 + DdE1xQ > DdN ) { + if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data; + + var data = buffers[ attribute.uuid ]; - return null; + if ( data ) { - } + gl.deleteBuffer( data.buffer ); - // Line intersects triangle, check if ray does. - var QdN = - sign * diff.dot( normal ); + delete buffers[ attribute.uuid ]; - // t < 0, no intersection - if ( QdN < 0 ) { + } - return null; + } - } + function update( attribute, bufferType ) { - // Ray intersects triangle. - return this.at( QdN / DdN, optionalTarget ); + if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data; - }; + var data = buffers[ attribute.uuid ]; - }(), + if ( data === undefined ) { - applyMatrix4: function ( matrix4 ) { + buffers[ attribute.uuid ] = createBuffer( attribute, bufferType ); - this.direction.add( this.origin ).applyMatrix4( matrix4 ); - this.origin.applyMatrix4( matrix4 ); - this.direction.sub( this.origin ); - this.direction.normalize(); + } else if ( data.version < attribute.version ) { - return this; + updateBuffer( data.buffer, attribute, bufferType ); - }, + data.version = attribute.version; - equals: function ( ray ) { + } - return ray.origin.equals( this.origin ) && ray.direction.equals( this.direction ); + } + + return { + + get: get, + remove: remove, + update: update - } + }; - } ); + } /** * @author mrdoob / http://mrdoob.com/ @@ -10679,8 +10529,19 @@ // This method does not support objects with rotated and/or translated parent(s) var m1 = new Matrix4(); + var vector = new Vector3(); - return function lookAt( vector ) { + return function lookAt( x, y, z ) { + + if ( x.isVector3 ) { + + vector.copy( x ); + + } else { + + vector.set( x, y, z ); + + } if ( this.isCamera ) { @@ -10704,3286 +10565,3852 @@ for ( var i = 0; i < arguments.length; i ++ ) { - this.add( arguments[ i ] ); + this.add( arguments[ i ] ); + + } + + return this; + + } + + if ( object === this ) { + + console.error( "THREE.Object3D.add: object can't be added as a child of itself.", object ); + return this; + + } + + if ( ( object && object.isObject3D ) ) { + + if ( object.parent !== null ) { + + object.parent.remove( object ); + + } + + object.parent = this; + object.dispatchEvent( { type: 'added' } ); + + this.children.push( object ); + + } else { + + console.error( "THREE.Object3D.add: object not an instance of THREE.Object3D.", object ); + + } + + return this; + + }, + + remove: function ( object ) { + + if ( arguments.length > 1 ) { + + for ( var i = 0; i < arguments.length; i ++ ) { + + this.remove( arguments[ i ] ); + + } + + return this; + + } + + var index = this.children.indexOf( object ); + + if ( index !== - 1 ) { + + object.parent = null; + + object.dispatchEvent( { type: 'removed' } ); + + this.children.splice( index, 1 ); + + } + + return this; + + }, + + getObjectById: function ( id ) { + + return this.getObjectByProperty( 'id', id ); + + }, + + getObjectByName: function ( name ) { + + return this.getObjectByProperty( 'name', name ); + + }, + + getObjectByProperty: function ( name, value ) { + + if ( this[ name ] === value ) return this; + + for ( var i = 0, l = this.children.length; i < l; i ++ ) { + + var child = this.children[ i ]; + var object = child.getObjectByProperty( name, value ); + + if ( object !== undefined ) { + + return object; + + } + + } + + return undefined; + + }, + + getWorldPosition: function ( optionalTarget ) { + + var result = optionalTarget || new Vector3(); + + this.updateMatrixWorld( true ); + + return result.setFromMatrixPosition( this.matrixWorld ); + + }, + + getWorldQuaternion: function () { + + var position = new Vector3(); + var scale = new Vector3(); + + return function getWorldQuaternion( optionalTarget ) { + + var result = optionalTarget || new Quaternion(); + + this.updateMatrixWorld( true ); + + this.matrixWorld.decompose( position, result, scale ); + + return result; + + }; + + }(), + + getWorldRotation: function () { + + var quaternion = new Quaternion(); + + return function getWorldRotation( optionalTarget ) { + + var result = optionalTarget || new Euler(); + + this.getWorldQuaternion( quaternion ); + + return result.setFromQuaternion( quaternion, this.rotation.order, false ); + + }; + + }(), + + getWorldScale: function () { + + var position = new Vector3(); + var quaternion = new Quaternion(); + + return function getWorldScale( optionalTarget ) { + + var result = optionalTarget || new Vector3(); + + this.updateMatrixWorld( true ); + + this.matrixWorld.decompose( position, quaternion, result ); + + return result; + + }; + + }(), + + getWorldDirection: function () { + + var quaternion = new Quaternion(); + + return function getWorldDirection( optionalTarget ) { + + var result = optionalTarget || new Vector3(); + + this.getWorldQuaternion( quaternion ); + + return result.set( 0, 0, 1 ).applyQuaternion( quaternion ); + + }; + + }(), + + raycast: function () {}, + + traverse: function ( callback ) { + + callback( this ); + + var children = this.children; + + for ( var i = 0, l = children.length; i < l; i ++ ) { + + children[ i ].traverse( callback ); + + } + + }, + + traverseVisible: function ( callback ) { + + if ( this.visible === false ) return; + + callback( this ); + + var children = this.children; + + for ( var i = 0, l = children.length; i < l; i ++ ) { + + children[ i ].traverseVisible( callback ); + + } + + }, + + traverseAncestors: function ( callback ) { + + var parent = this.parent; + + if ( parent !== null ) { + + callback( parent ); + + parent.traverseAncestors( callback ); + + } + + }, + + updateMatrix: function () { + + this.matrix.compose( this.position, this.quaternion, this.scale ); + + this.matrixWorldNeedsUpdate = true; + + }, + + updateMatrixWorld: function ( force ) { + + if ( this.matrixAutoUpdate ) this.updateMatrix(); + + if ( this.matrixWorldNeedsUpdate || force ) { + + if ( this.parent === null ) { + + this.matrixWorld.copy( this.matrix ); + + } else { + + this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix ); + + } + + this.matrixWorldNeedsUpdate = false; + + force = true; + + } + + // update children + + var children = this.children; + + for ( var i = 0, l = children.length; i < l; i ++ ) { + + children[ i ].updateMatrixWorld( force ); + + } + + }, + + toJSON: function ( meta ) { + + // meta is '' when called from JSON.stringify + var isRootObject = ( meta === undefined || meta === '' ); + + var output = {}; + + // meta is a hash used to collect geometries, materials. + // not providing it implies that this is the root object + // being serialized. + if ( isRootObject ) { + + // initialize meta obj + meta = { + geometries: {}, + materials: {}, + textures: {}, + images: {} + }; + + output.metadata = { + version: 4.5, + type: 'Object', + generator: 'Object3D.toJSON' + }; + + } + + // standard Object3D serialization + + var object = {}; + + object.uuid = this.uuid; + object.type = this.type; + + 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 ( JSON.stringify( this.userData ) !== '{}' ) object.userData = this.userData; + + object.matrix = this.matrix.toArray(); + + // + + function serialize( library, element ) { + + if ( library[ element.uuid ] === undefined ) { + + library[ element.uuid ] = element.toJSON( meta ); + + } + + return element.uuid; + + } + + if ( this.geometry !== undefined ) { + + object.geometry = serialize( meta.geometries, this.geometry ); + + } + + if ( this.material !== undefined ) { + + if ( Array.isArray( this.material ) ) { + + var uuids = []; + + for ( var i = 0, l = this.material.length; i < l; i ++ ) { + + uuids.push( serialize( meta.materials, this.material[ i ] ) ); + + } + + object.material = uuids; + + } else { + + object.material = serialize( meta.materials, this.material ); + + } + + } + + // + + if ( this.children.length > 0 ) { + + object.children = []; + + for ( var i = 0; i < this.children.length; i ++ ) { + + object.children.push( this.children[ i ].toJSON( meta ).object ); + + } + + } + + if ( isRootObject ) { + + var geometries = extractFromCache( meta.geometries ); + var materials = extractFromCache( meta.materials ); + var textures = extractFromCache( meta.textures ); + var images = extractFromCache( meta.images ); + + 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; + + } + + output.object = object; + + return output; + + // extract data from the cache hash + // remove metadata on each item + // and return as array + function extractFromCache( cache ) { + + var values = []; + for ( var key in cache ) { + + var data = cache[ key ]; + delete data.metadata; + values.push( data ); + + } + return values; + + } + + }, + + clone: function ( recursive ) { + + return new this.constructor().copy( this, recursive ); + + }, + + copy: function ( source, recursive ) { + + if ( recursive === undefined ) recursive = true; + + this.name = source.name; + + this.up.copy( source.up ); + + this.position.copy( source.position ); + 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.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; + + this.userData = JSON.parse( JSON.stringify( source.userData ) ); + + if ( recursive === true ) { + + for ( var i = 0; i < source.children.length; i ++ ) { + + var child = source.children[ i ]; + this.add( child.clone() ); + + } + + } + + return this; + + } + + } ); + + /** + * @author mrdoob / http://mrdoob.com/ + * @author mikael emtinger / http://gomo.se/ + * @author WestLangley / http://github.com/WestLangley + */ + + function Camera() { + + Object3D.call( this ); + + this.type = 'Camera'; + + this.matrixWorldInverse = new Matrix4(); + this.projectionMatrix = new Matrix4(); + + } + + Camera.prototype = Object.assign( Object.create( Object3D.prototype ), { + + constructor: Camera, + + isCamera: true, + + copy: function ( source, recursive ) { + + Object3D.prototype.copy.call( this, source, recursive ); + + this.matrixWorldInverse.copy( source.matrixWorldInverse ); + this.projectionMatrix.copy( source.projectionMatrix ); + + return this; + + }, + + getWorldDirection: function () { + + var quaternion = new Quaternion(); + + return function getWorldDirection( optionalTarget ) { + + var result = optionalTarget || new Vector3(); - } + this.getWorldQuaternion( quaternion ); - return this; + return result.set( 0, 0, - 1 ).applyQuaternion( quaternion ); - } + }; - if ( object === this ) { + }(), - console.error( "THREE.Object3D.add: object can't be added as a child of itself.", object ); - return this; + updateMatrixWorld: function ( force ) { - } + Object3D.prototype.updateMatrixWorld.call( this, force ); - if ( ( object && object.isObject3D ) ) { + this.matrixWorldInverse.getInverse( this.matrixWorld ); - if ( object.parent !== null ) { + }, - object.parent.remove( object ); + clone: function () { - } + return new this.constructor().copy( this ); - object.parent = this; - object.dispatchEvent( { type: 'added' } ); + } - this.children.push( object ); + } ); - } else { + /** + * @author alteredq / http://alteredqualia.com/ + * @author arose / http://github.com/arose + */ - console.error( "THREE.Object3D.add: object not an instance of THREE.Object3D.", object ); + function OrthographicCamera( left, right, top, bottom, near, far ) { - } + Camera.call( this ); - return this; + this.type = 'OrthographicCamera'; - }, + this.zoom = 1; + this.view = null; - remove: function ( object ) { + this.left = left; + this.right = right; + this.top = top; + this.bottom = bottom; - if ( arguments.length > 1 ) { + this.near = ( near !== undefined ) ? near : 0.1; + this.far = ( far !== undefined ) ? far : 2000; - for ( var i = 0; i < arguments.length; i ++ ) { + this.updateProjectionMatrix(); - this.remove( arguments[ i ] ); + } - } + OrthographicCamera.prototype = Object.assign( Object.create( Camera.prototype ), { - } + constructor: OrthographicCamera, - var index = this.children.indexOf( object ); + isOrthographicCamera: true, - if ( index !== - 1 ) { + copy: function ( source, recursive ) { - object.parent = null; + Camera.prototype.copy.call( this, source, recursive ); - object.dispatchEvent( { type: 'removed' } ); + this.left = source.left; + this.right = source.right; + this.top = source.top; + this.bottom = source.bottom; + this.near = source.near; + this.far = source.far; - this.children.splice( index, 1 ); + this.zoom = source.zoom; + this.view = source.view === null ? null : Object.assign( {}, source.view ); - } + return this; }, - getObjectById: function ( id ) { + setViewOffset: function( fullWidth, fullHeight, x, y, width, height ) { - return this.getObjectByProperty( 'id', id ); + this.view = { + fullWidth: fullWidth, + fullHeight: fullHeight, + offsetX: x, + offsetY: y, + width: width, + height: height + }; + + this.updateProjectionMatrix(); }, - getObjectByName: function ( name ) { + clearViewOffset: function() { - return this.getObjectByProperty( 'name', name ); + this.view = null; + this.updateProjectionMatrix(); }, - getObjectByProperty: function ( name, value ) { - - if ( this[ name ] === value ) return this; + updateProjectionMatrix: function () { - for ( var i = 0, l = this.children.length; i < l; i ++ ) { + var dx = ( this.right - this.left ) / ( 2 * this.zoom ); + var dy = ( this.top - this.bottom ) / ( 2 * this.zoom ); + var cx = ( this.right + this.left ) / 2; + var cy = ( this.top + this.bottom ) / 2; - var child = this.children[ i ]; - var object = child.getObjectByProperty( name, value ); + var left = cx - dx; + var right = cx + dx; + var top = cy + dy; + var bottom = cy - dy; - if ( object !== undefined ) { + if ( this.view !== null ) { - return object; + var zoomW = this.zoom / ( this.view.width / this.view.fullWidth ); + var zoomH = this.zoom / ( this.view.height / this.view.fullHeight ); + var scaleW = ( this.right - this.left ) / this.view.width; + var scaleH = ( this.top - this.bottom ) / this.view.height; - } + left += scaleW * ( this.view.offsetX / zoomW ); + right = left + scaleW * ( this.view.width / zoomW ); + top -= scaleH * ( this.view.offsetY / zoomH ); + bottom = top - scaleH * ( this.view.height / zoomH ); } - return undefined; + this.projectionMatrix.makeOrthographic( left, right, top, bottom, this.near, this.far ); }, - getWorldPosition: function ( optionalTarget ) { - - var result = optionalTarget || new Vector3(); - - this.updateMatrixWorld( true ); + toJSON: function ( meta ) { - return result.setFromMatrixPosition( this.matrixWorld ); + var data = Object3D.prototype.toJSON.call( this, meta ); - }, + data.object.zoom = this.zoom; + data.object.left = this.left; + data.object.right = this.right; + data.object.top = this.top; + data.object.bottom = this.bottom; + data.object.near = this.near; + data.object.far = this.far; - getWorldQuaternion: function () { + if ( this.view !== null ) data.object.view = Object.assign( {}, this.view ); - var position = new Vector3(); - var scale = new Vector3(); + return data; - return function getWorldQuaternion( optionalTarget ) { + } - var result = optionalTarget || new Quaternion(); + } ); - this.updateMatrixWorld( true ); + /** + * @author mrdoob / http://mrdoob.com/ + * @author greggman / http://games.greggman.com/ + * @author zz85 / http://www.lab4games.net/zz85/blog + * @author tschw + */ - this.matrixWorld.decompose( position, result, scale ); + function PerspectiveCamera( fov, aspect, near, far ) { - return result; + Camera.call( this ); - }; + this.type = 'PerspectiveCamera'; - }(), + this.fov = fov !== undefined ? fov : 50; + this.zoom = 1; - getWorldRotation: function () { + this.near = near !== undefined ? near : 0.1; + this.far = far !== undefined ? far : 2000; + this.focus = 10; - var quaternion = new Quaternion(); + this.aspect = aspect !== undefined ? aspect : 1; + this.view = null; - return function getWorldRotation( optionalTarget ) { + this.filmGauge = 35; // width of the film (default in millimeters) + this.filmOffset = 0; // horizontal film offset (same unit as gauge) - var result = optionalTarget || new Euler(); + this.updateProjectionMatrix(); - this.getWorldQuaternion( quaternion ); + } - return result.setFromQuaternion( quaternion, this.rotation.order, false ); + PerspectiveCamera.prototype = Object.assign( Object.create( Camera.prototype ), { - }; + constructor: PerspectiveCamera, - }(), + isPerspectiveCamera: true, - getWorldScale: function () { + copy: function ( source, recursive ) { - var position = new Vector3(); - var quaternion = new Quaternion(); + Camera.prototype.copy.call( this, source, recursive ); - return function getWorldScale( optionalTarget ) { + this.fov = source.fov; + this.zoom = source.zoom; - var result = optionalTarget || new Vector3(); + this.near = source.near; + this.far = source.far; + this.focus = source.focus; - this.updateMatrixWorld( true ); + this.aspect = source.aspect; + this.view = source.view === null ? null : Object.assign( {}, source.view ); - this.matrixWorld.decompose( position, quaternion, result ); + this.filmGauge = source.filmGauge; + this.filmOffset = source.filmOffset; - return result; + return this; - }; + }, - }(), + /** + * 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 ) { - getWorldDirection: function () { + // see http://www.bobatkins.com/photography/technical/field_of_view.html + var vExtentSlope = 0.5 * this.getFilmHeight() / focalLength; - var quaternion = new Quaternion(); + this.fov = _Math.RAD2DEG * 2 * Math.atan( vExtentSlope ); + this.updateProjectionMatrix(); - return function getWorldDirection( optionalTarget ) { + }, - var result = optionalTarget || new Vector3(); + /** + * Calculates the focal length from the current .fov and .filmGauge. + */ + getFocalLength: function () { - this.getWorldQuaternion( quaternion ); + var vExtentSlope = Math.tan( _Math.DEG2RAD * 0.5 * this.fov ); - return result.set( 0, 0, 1 ).applyQuaternion( quaternion ); + return 0.5 * this.getFilmHeight() / vExtentSlope; - }; + }, - }(), + getEffectiveFOV: function () { - raycast: function () {}, + return _Math.RAD2DEG * 2 * Math.atan( + Math.tan( _Math.DEG2RAD * 0.5 * this.fov ) / this.zoom ); - traverse: function ( callback ) { + }, - callback( this ); + getFilmWidth: function () { - var children = this.children; + // film not completely covered in portrait format (aspect < 1) + return this.filmGauge * Math.min( this.aspect, 1 ); - for ( var i = 0, l = children.length; i < l; i ++ ) { + }, - children[ i ].traverse( callback ); + getFilmHeight: function () { - } + // film not completely covered in landscape format (aspect > 1) + return this.filmGauge / Math.max( this.aspect, 1 ); }, - traverseVisible: function ( callback ) { + /** + * 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.setOffset( fullWidth, fullHeight, w * 0, h * 0, w, h ); + * --B-- + * camera.setOffset( fullWidth, fullHeight, w * 1, h * 0, w, h ); + * --C-- + * camera.setOffset( fullWidth, fullHeight, w * 2, h * 0, w, h ); + * --D-- + * camera.setOffset( fullWidth, fullHeight, w * 0, h * 1, w, h ); + * --E-- + * camera.setOffset( fullWidth, fullHeight, w * 1, h * 1, w, h ); + * --F-- + * camera.setOffset( 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 ) { - if ( this.visible === false ) return; + this.aspect = fullWidth / fullHeight; - callback( this ); + this.view = { + fullWidth: fullWidth, + fullHeight: fullHeight, + offsetX: x, + offsetY: y, + width: width, + height: height + }; - var children = this.children; + this.updateProjectionMatrix(); - for ( var i = 0, l = children.length; i < l; i ++ ) { + }, - children[ i ].traverseVisible( callback ); + clearViewOffset: function () { - } + this.view = null; + this.updateProjectionMatrix(); }, - traverseAncestors: function ( callback ) { + updateProjectionMatrix: function () { - var parent = this.parent; + 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; - if ( parent !== null ) { + if ( view !== null ) { - callback( parent ); + var fullWidth = view.fullWidth, + fullHeight = view.fullHeight; - parent.traverseAncestors( callback ); + left += view.offsetX * width / fullWidth; + top -= view.offsetY * height / fullHeight; + width *= view.width / fullWidth; + height *= view.height / fullHeight; } + var skew = this.filmOffset; + if ( skew !== 0 ) left += near * skew / this.getFilmWidth(); + + this.projectionMatrix.makePerspective( left, left + width, top, top - height, near, this.far ); + }, - updateMatrix: function () { + toJSON: function ( meta ) { - this.matrix.compose( this.position, this.quaternion, this.scale ); + var data = Object3D.prototype.toJSON.call( this, meta ); - this.matrixWorldNeedsUpdate = true; + data.object.fov = this.fov; + data.object.zoom = this.zoom; - }, + data.object.near = this.near; + data.object.far = this.far; + data.object.focus = this.focus; - updateMatrixWorld: function ( force ) { + data.object.aspect = this.aspect; - if ( this.matrixAutoUpdate ) this.updateMatrix(); + if ( this.view !== null ) data.object.view = Object.assign( {}, this.view ); - if ( this.matrixWorldNeedsUpdate || force ) { + data.object.filmGauge = this.filmGauge; + data.object.filmOffset = this.filmOffset; - if ( this.parent === null ) { + return data; - this.matrixWorld.copy( this.matrix ); + } - } else { + } ); - this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix ); + /** + * @author mrdoob / http://mrdoob.com/ + * @author alteredq / http://alteredqualia.com/ + */ - } + function Face3( a, b, c, normal, color, materialIndex ) { - this.matrixWorldNeedsUpdate = false; + this.a = a; + this.b = b; + this.c = c; - force = true; + 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 : []; - // update children + this.materialIndex = materialIndex !== undefined ? materialIndex : 0; - var children = this.children; + } - for ( var i = 0, l = children.length; i < l; i ++ ) { + Object.assign( Face3.prototype, { - children[ i ].updateMatrixWorld( force ); + clone: function () { - } + return new this.constructor().copy( this ); }, - toJSON: function ( meta ) { + copy: function ( source ) { - // meta is '' when called from JSON.stringify - var isRootObject = ( meta === undefined || meta === '' ); + this.a = source.a; + this.b = source.b; + this.c = source.c; - var output = {}; + this.normal.copy( source.normal ); + this.color.copy( source.color ); - // meta is a hash used to collect geometries, materials. - // not providing it implies that this is the root object - // being serialized. - if ( isRootObject ) { + this.materialIndex = source.materialIndex; - // initialize meta obj - meta = { - geometries: {}, - materials: {}, - textures: {}, - images: {} - }; + for ( var i = 0, il = source.vertexNormals.length; i < il; i ++ ) { - output.metadata = { - version: 4.5, - type: 'Object', - generator: 'Object3D.toJSON' - }; + this.vertexNormals[ i ] = source.vertexNormals[ i ].clone(); } - // standard Object3D serialization + for ( var i = 0, il = source.vertexColors.length; i < il; i ++ ) { - var object = {}; + this.vertexColors[ i ] = source.vertexColors[ i ].clone(); - object.uuid = this.uuid; - object.type = this.type; + } - if ( this.name !== '' ) object.name = this.name; - if ( JSON.stringify( this.userData ) !== '{}' ) object.userData = this.userData; - if ( this.castShadow === true ) object.castShadow = true; - if ( this.receiveShadow === true ) object.receiveShadow = true; - if ( this.visible === false ) object.visible = false; + return this; - object.matrix = this.matrix.toArray(); + } - // + } ); - function serialize( library, element ) { + /** + * @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 + */ - if ( library[ element.uuid ] === undefined ) { + var count = 0; + function GeometryIdCount() { return count++; } - library[ element.uuid ] = element.toJSON( meta ); + function Geometry() { - } + Object.defineProperty( this, 'id', { value: GeometryIdCount() } ); - return element.uuid; + this.uuid = _Math.generateUUID(); - } + this.name = ''; + this.type = 'Geometry'; - if ( this.geometry !== undefined ) { + this.vertices = []; + this.colors = []; + this.faces = []; + this.faceVertexUvs = [[]]; - object.geometry = serialize( meta.geometries, this.geometry ); + this.morphTargets = []; + this.morphNormals = []; - } + this.skinWeights = []; + this.skinIndices = []; - if ( this.material !== undefined ) { + this.lineDistances = []; - if ( Array.isArray( this.material ) ) { + this.boundingBox = null; + this.boundingSphere = null; - var uuids = []; + // update flags - for ( var i = 0, l = this.material.length; i < l; i ++ ) { + this.elementsNeedUpdate = false; + this.verticesNeedUpdate = false; + this.uvsNeedUpdate = false; + this.normalsNeedUpdate = false; + this.colorsNeedUpdate = false; + this.lineDistancesNeedUpdate = false; + this.groupsNeedUpdate = false; - uuids.push( serialize( meta.materials, this.material[ i ] ) ); + } - } + Object.assign( Geometry.prototype, EventDispatcher.prototype, { - object.material = uuids; + isGeometry: true, - } else { + applyMatrix: function ( matrix ) { - object.material = serialize( meta.materials, this.material ); + var normalMatrix = new Matrix3().getNormalMatrix( matrix ); - } + for ( var i = 0, il = this.vertices.length; i < il; i ++ ) { + + var vertex = this.vertices[ i ]; + vertex.applyMatrix4( matrix ); } - // + for ( var i = 0, il = this.faces.length; i < il; i ++ ) { - if ( this.children.length > 0 ) { + var face = this.faces[ i ]; + face.normal.applyMatrix3( normalMatrix ).normalize(); - object.children = []; + for ( var j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) { - for ( var i = 0; i < this.children.length; i ++ ) { + face.vertexNormals[ j ].applyMatrix3( normalMatrix ).normalize(); - object.children.push( this.children[ i ].toJSON( meta ).object ); + } + + } + + if ( this.boundingBox !== null ) { + + this.computeBoundingBox(); + + } + + if ( this.boundingSphere !== null ) { - } + this.computeBoundingSphere(); } - if ( isRootObject ) { + this.verticesNeedUpdate = true; + this.normalsNeedUpdate = true; - var geometries = extractFromCache( meta.geometries ); - var materials = extractFromCache( meta.materials ); - var textures = extractFromCache( meta.textures ); - var images = extractFromCache( meta.images ); + return this; - 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; + }, - } + rotateX: function () { - output.object = object; + // rotate geometry around world x-axis - return output; + var m1 = new Matrix4(); - // extract data from the cache hash - // remove metadata on each item - // and return as array - function extractFromCache( cache ) { + return function rotateX( angle ) { - var values = []; - for ( var key in cache ) { + m1.makeRotationX( angle ); - var data = cache[ key ]; - delete data.metadata; - values.push( data ); + this.applyMatrix( m1 ); - } - return values; + return this; - } + }; - }, + }(), - clone: function ( recursive ) { + rotateY: function () { - return new this.constructor().copy( this, recursive ); + // rotate geometry around world y-axis - }, + var m1 = new Matrix4(); - copy: function ( source, recursive ) { + return function rotateY( angle ) { - if ( recursive === undefined ) recursive = true; + m1.makeRotationY( angle ); - this.name = source.name; + this.applyMatrix( m1 ); - this.up.copy( source.up ); + return this; - this.position.copy( source.position ); - 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; + rotateZ: function () { - this.layers.mask = source.layers.mask; - this.visible = source.visible; + // rotate geometry around world z-axis - this.castShadow = source.castShadow; - this.receiveShadow = source.receiveShadow; + var m1 = new Matrix4(); - this.frustumCulled = source.frustumCulled; - this.renderOrder = source.renderOrder; + return function rotateZ( angle ) { - this.userData = JSON.parse( JSON.stringify( source.userData ) ); + m1.makeRotationZ( angle ); - if ( recursive === true ) { + this.applyMatrix( m1 ); - for ( var i = 0; i < source.children.length; i ++ ) { + return this; - var child = source.children[ i ]; - this.add( child.clone() ); + }; - } + }(), - } + translate: function () { - return this; + // translate geometry - } + var m1 = new Matrix4(); - } ); + return function translate( x, y, z ) { - /** - * @author bhouston / http://clara.io - */ + m1.makeTranslation( x, y, z ); - function Line3( start, end ) { + this.applyMatrix( m1 ); - this.start = ( start !== undefined ) ? start : new Vector3(); - this.end = ( end !== undefined ) ? end : new Vector3(); + return this; - } + }; - Object.assign( Line3.prototype, { + }(), - set: function ( start, end ) { + scale: function () { - this.start.copy( start ); - this.end.copy( end ); + // scale geometry - return this; + var m1 = new Matrix4(); - }, + return function scale( x, y, z ) { - clone: function () { + m1.makeScale( x, y, z ); - return new this.constructor().copy( this ); + this.applyMatrix( m1 ); - }, + return this; - copy: function ( line ) { + }; - this.start.copy( line.start ); - this.end.copy( line.end ); + }(), - return this; + lookAt: function () { - }, + var obj = new Object3D(); - getCenter: function ( optionalTarget ) { + return function lookAt( vector ) { - var result = optionalTarget || new Vector3(); - return result.addVectors( this.start, this.end ).multiplyScalar( 0.5 ); + obj.lookAt( vector ); - }, + obj.updateMatrix(); - delta: function ( optionalTarget ) { + this.applyMatrix( obj.matrix ); - var result = optionalTarget || new Vector3(); - return result.subVectors( this.end, this.start ); + }; - }, + }(), - distanceSq: function () { + fromBufferGeometry: function ( geometry ) { - return this.start.distanceToSquared( this.end ); + var scope = this; - }, + var indices = geometry.index !== null ? geometry.index.array : undefined; + var attributes = geometry.attributes; - distance: function () { + 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; - return this.start.distanceTo( this.end ); + if ( uvs2 !== undefined ) this.faceVertexUvs[ 1 ] = []; - }, + var tempNormals = []; + var tempUVs = []; + var tempUVs2 = []; - at: function ( t, optionalTarget ) { + for ( var i = 0, j = 0; i < positions.length; i += 3, j += 2 ) { - var result = optionalTarget || new Vector3(); + scope.vertices.push( new Vector3( positions[ i ], positions[ i + 1 ], positions[ i + 2 ] ) ); - return this.delta( result ).multiplyScalar( t ).add( this.start ); + if ( normals !== undefined ) { - }, + tempNormals.push( new Vector3( normals[ i ], normals[ i + 1 ], normals[ i + 2 ] ) ); - closestPointToPointParameter: function () { + } - var startP = new Vector3(); - var startEnd = new Vector3(); + if ( colors !== undefined ) { - return function closestPointToPointParameter( point, clampToLine ) { + scope.colors.push( new Color( colors[ i ], colors[ i + 1 ], colors[ i + 2 ] ) ); - startP.subVectors( point, this.start ); - startEnd.subVectors( this.end, this.start ); + } - var startEnd2 = startEnd.dot( startEnd ); - var startEnd_startP = startEnd.dot( startP ); + if ( uvs !== undefined ) { - var t = startEnd_startP / startEnd2; + tempUVs.push( new Vector2( uvs[ j ], uvs[ j + 1 ] ) ); - if ( clampToLine ) { + } - t = _Math.clamp( t, 0, 1 ); + if ( uvs2 !== undefined ) { + + tempUVs2.push( new Vector2( uvs2[ j ], uvs2[ j + 1 ] ) ); } - return t; + } - }; + function addFace( a, b, c, materialIndex ) { - }(), + var vertexNormals = normals !== undefined ? [ tempNormals[ a ].clone(), tempNormals[ b ].clone(), tempNormals[ c ].clone() ] : []; + var vertexColors = colors !== undefined ? [ scope.colors[ a ].clone(), scope.colors[ b ].clone(), scope.colors[ c ].clone() ] : []; - closestPointToPoint: function ( point, clampToLine, optionalTarget ) { + var face = new Face3( a, b, c, vertexNormals, vertexColors, materialIndex ); - var t = this.closestPointToPointParameter( point, clampToLine ); + scope.faces.push( face ); - var result = optionalTarget || new Vector3(); + if ( uvs !== undefined ) { - return this.delta( result ).multiplyScalar( t ).add( this.start ); + scope.faceVertexUvs[ 0 ].push( [ tempUVs[ a ].clone(), tempUVs[ b ].clone(), tempUVs[ c ].clone() ] ); - }, + } - applyMatrix4: function ( matrix ) { + if ( uvs2 !== undefined ) { - this.start.applyMatrix4( matrix ); - this.end.applyMatrix4( matrix ); + scope.faceVertexUvs[ 1 ].push( [ tempUVs2[ a ].clone(), tempUVs2[ b ].clone(), tempUVs2[ c ].clone() ] ); - return this; + } - }, + } - equals: function ( line ) { + var groups = geometry.groups; - return line.start.equals( this.start ) && line.end.equals( this.end ); + if ( groups.length > 0 ) { - } + for ( var i = 0; i < groups.length; i ++ ) { - } ); + var group = groups[ i ]; - /** - * @author bhouston / http://clara.io - * @author mrdoob / http://mrdoob.com/ - */ + var start = group.start; + var count = group.count; - function Triangle( a, b, c ) { + for ( var j = start, jl = start + count; j < jl; j += 3 ) { - this.a = ( a !== undefined ) ? a : new Vector3(); - this.b = ( b !== undefined ) ? b : new Vector3(); - this.c = ( c !== undefined ) ? c : new Vector3(); + if ( indices !== undefined ) { - } + addFace( indices[ j ], indices[ j + 1 ], indices[ j + 2 ], group.materialIndex ); - Object.assign( Triangle, { + } else { - normal: function () { + addFace( j, j + 1, j + 2, group.materialIndex ); - var v0 = new Vector3(); + } - return function normal( a, b, c, optionalTarget ) { + } - var result = optionalTarget || new Vector3(); + } - result.subVectors( c, b ); - v0.subVectors( a, b ); - result.cross( v0 ); + } else { - var resultLengthSq = result.lengthSq(); - if ( resultLengthSq > 0 ) { + if ( indices !== undefined ) { - return result.multiplyScalar( 1 / Math.sqrt( resultLengthSq ) ); + for ( var i = 0; i < indices.length; i += 3 ) { - } + addFace( indices[ i ], indices[ i + 1 ], indices[ i + 2 ] ); - return result.set( 0, 0, 0 ); + } - }; + } else { - }(), + for ( var i = 0; i < positions.length / 3; i += 3 ) { - // static/instance method to calculate barycentric coordinates - // based on: http://www.blackpawn.com/texts/pointinpoly/default.html - barycoordFromPoint: function () { + addFace( i, i + 1, i + 2 ); - var v0 = new Vector3(); - var v1 = new Vector3(); - var v2 = new Vector3(); + } - return function barycoordFromPoint( point, a, b, c, optionalTarget ) { + } - v0.subVectors( c, a ); - v1.subVectors( b, a ); - v2.subVectors( point, a ); + } - var dot00 = v0.dot( v0 ); - var dot01 = v0.dot( v1 ); - var dot02 = v0.dot( v2 ); - var dot11 = v1.dot( v1 ); - var dot12 = v1.dot( v2 ); + this.computeFaceNormals(); - var denom = ( dot00 * dot11 - dot01 * dot01 ); + if ( geometry.boundingBox !== null ) { - var result = optionalTarget || new Vector3(); + this.boundingBox = geometry.boundingBox.clone(); - // 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 result.set( - 2, - 1, - 1 ); + if ( geometry.boundingSphere !== null ) { - } + this.boundingSphere = geometry.boundingSphere.clone(); - var invDenom = 1 / denom; - var u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom; - var v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom; + } - // barycentric coordinates must always sum to 1 - return result.set( 1 - u - v, v, u ); + return this; - }; + }, - }(), + center: function () { - containsPoint: function () { + this.computeBoundingBox(); - var v1 = new Vector3(); + var offset = this.boundingBox.getCenter().negate(); - return function containsPoint( point, a, b, c ) { + this.translate( offset.x, offset.y, offset.z ); - var result = Triangle.barycoordFromPoint( point, a, b, c, v1 ); + return offset; - return ( result.x >= 0 ) && ( result.y >= 0 ) && ( ( result.x + result.y ) <= 1 ); + }, - }; + normalize: function () { - }() + this.computeBoundingSphere(); - } ); + var center = this.boundingSphere.center; + var radius = this.boundingSphere.radius; - Object.assign( Triangle.prototype, { + var s = radius === 0 ? 1 : 1.0 / radius; - set: function ( a, b, c ) { + var matrix = new Matrix4(); + matrix.set( + s, 0, 0, - s * center.x, + 0, s, 0, - s * center.y, + 0, 0, s, - s * center.z, + 0, 0, 0, 1 + ); - this.a.copy( a ); - this.b.copy( b ); - this.c.copy( c ); + this.applyMatrix( matrix ); return this; }, - setFromPointsAndIndices: function ( points, i0, i1, i2 ) { + computeFaceNormals: function () { - this.a.copy( points[ i0 ] ); - this.b.copy( points[ i1 ] ); - this.c.copy( points[ i2 ] ); + var cb = new Vector3(), ab = new Vector3(); - return this; + for ( var f = 0, fl = this.faces.length; f < fl; f ++ ) { - }, + var face = this.faces[ f ]; - clone: function () { + var vA = this.vertices[ face.a ]; + var vB = this.vertices[ face.b ]; + var vC = this.vertices[ face.c ]; - return new this.constructor().copy( this ); + cb.subVectors( vC, vB ); + ab.subVectors( vA, vB ); + cb.cross( ab ); + + cb.normalize(); + + face.normal.copy( cb ); + + } }, - copy: function ( triangle ) { + computeVertexNormals: function ( areaWeighted ) { - this.a.copy( triangle.a ); - this.b.copy( triangle.b ); - this.c.copy( triangle.c ); + if ( areaWeighted === undefined ) areaWeighted = true; - return this; + var v, vl, f, fl, face, vertices; - }, + vertices = new Array( this.vertices.length ); - area: function () { + for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) { - var v0 = new Vector3(); - var v1 = new Vector3(); + vertices[ v ] = new Vector3(); - return function area() { + } - v0.subVectors( this.c, this.b ); - v1.subVectors( this.a, this.b ); + if ( areaWeighted ) { - return v0.cross( v1 ).length() * 0.5; + // 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 ++ ) { - midpoint: function ( optionalTarget ) { + face = this.faces[ f ]; - var result = optionalTarget || new Vector3(); - return result.addVectors( this.a, this.b ).add( this.c ).multiplyScalar( 1 / 3 ); + vA = this.vertices[ face.a ]; + vB = this.vertices[ face.b ]; + vC = this.vertices[ face.c ]; - }, + cb.subVectors( vC, vB ); + ab.subVectors( vA, vB ); + cb.cross( ab ); - normal: function ( optionalTarget ) { + vertices[ face.a ].add( cb ); + vertices[ face.b ].add( cb ); + vertices[ face.c ].add( cb ); - return Triangle.normal( this.a, this.b, this.c, optionalTarget ); + } - }, + } else { - plane: function ( optionalTarget ) { + this.computeFaceNormals(); - var result = optionalTarget || new Plane(); + for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { - return result.setFromCoplanarPoints( this.a, this.b, this.c ); + face = this.faces[ f ]; - }, + vertices[ face.a ].add( face.normal ); + vertices[ face.b ].add( face.normal ); + vertices[ face.c ].add( face.normal ); - barycoordFromPoint: function ( point, optionalTarget ) { + } - return Triangle.barycoordFromPoint( point, this.a, this.b, this.c, optionalTarget ); + } - }, + for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) { - containsPoint: function ( point ) { + vertices[ v ].normalize(); - return Triangle.containsPoint( point, this.a, this.b, this.c ); + } - }, + for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { - closestPointToPoint: function () { + face = this.faces[ f ]; - var plane = new Plane(); - var edgeList = [ new Line3(), new Line3(), new Line3() ]; - var projectedPoint = new Vector3(); - var closestPoint = new Vector3(); + var vertexNormals = face.vertexNormals; - return function closestPointToPoint( point, optionalTarget ) { + if ( vertexNormals.length === 3 ) { - var result = optionalTarget || new Vector3(); - var minDistance = Infinity; + vertexNormals[ 0 ].copy( vertices[ face.a ] ); + vertexNormals[ 1 ].copy( vertices[ face.b ] ); + vertexNormals[ 2 ].copy( vertices[ face.c ] ); - // project the point onto the plane of the triangle + } else { - plane.setFromCoplanarPoints( this.a, this.b, this.c ); - plane.projectPoint( point, projectedPoint ); + vertexNormals[ 0 ] = vertices[ face.a ].clone(); + vertexNormals[ 1 ] = vertices[ face.b ].clone(); + vertexNormals[ 2 ] = vertices[ face.c ].clone(); - // check if the projection lies within the triangle + } - if( this.containsPoint( projectedPoint ) === true ) { + } - // if so, this is the closest point + if ( this.faces.length > 0 ) { - result.copy( projectedPoint ); + this.normalsNeedUpdate = true; - } else { + } - // if not, the point falls outside the triangle. the result is the closest point to the triangle's edges or vertices + }, - edgeList[ 0 ].set( this.a, this.b ); - edgeList[ 1 ].set( this.b, this.c ); - edgeList[ 2 ].set( this.c, this.a ); + computeFlatVertexNormals: function () { - for( var i = 0; i < edgeList.length; i ++ ) { + var f, fl, face; - edgeList[ i ].closestPointToPoint( projectedPoint, true, closestPoint ); + this.computeFaceNormals(); - var distance = projectedPoint.distanceToSquared( closestPoint ); + for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { - if( distance < minDistance ) { + face = this.faces[ f ]; - minDistance = distance; + var vertexNormals = face.vertexNormals; - result.copy( closestPoint ); + if ( vertexNormals.length === 3 ) { - } + vertexNormals[ 0 ].copy( face.normal ); + vertexNormals[ 1 ].copy( face.normal ); + vertexNormals[ 2 ].copy( face.normal ); - } + } else { + + vertexNormals[ 0 ] = face.normal.clone(); + vertexNormals[ 1 ] = face.normal.clone(); + vertexNormals[ 2 ] = face.normal.clone(); } - return result; + } - }; + if ( this.faces.length > 0 ) { - }(), + this.normalsNeedUpdate = true; - equals: function ( triangle ) { + } - return triangle.a.equals( this.a ) && triangle.b.equals( this.b ) && triangle.c.equals( this.c ); + }, - } + computeMorphNormals: function () { + + var i, il, f, fl, face; + + // save original normals + // - create temp variables on first access + // otherwise just copy (for faster repeated calls) + + for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { - } ); + face = this.faces[ f ]; - /** - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - */ + if ( ! face.__originalFaceNormal ) { - function Face3( a, b, c, normal, color, materialIndex ) { + face.__originalFaceNormal = face.normal.clone(); - this.a = a; - this.b = b; - this.c = c; + } else { - this.normal = ( normal && normal.isVector3 ) ? normal : new Vector3(); - this.vertexNormals = Array.isArray( normal ) ? normal : []; + face.__originalFaceNormal.copy( face.normal ); - this.color = ( color && color.isColor ) ? color : new Color(); - this.vertexColors = Array.isArray( color ) ? color : []; + } - this.materialIndex = materialIndex !== undefined ? materialIndex : 0; + if ( ! face.__originalVertexNormals ) face.__originalVertexNormals = []; - } + for ( i = 0, il = face.vertexNormals.length; i < il; i ++ ) { - Object.assign( Face3.prototype, { + if ( ! face.__originalVertexNormals[ i ] ) { - clone: function () { + face.__originalVertexNormals[ i ] = face.vertexNormals[ i ].clone(); - return new this.constructor().copy( this ); + } else { - }, + face.__originalVertexNormals[ i ].copy( face.vertexNormals[ i ] ); - copy: function ( source ) { + } - this.a = source.a; - this.b = source.b; - this.c = source.c; + } - this.normal.copy( source.normal ); - this.color.copy( source.color ); + } - this.materialIndex = source.materialIndex; + // use temp geometry to compute face and vertex normals for each morph - for ( var i = 0, il = source.vertexNormals.length; i < il; i ++ ) { + var tmpGeo = new Geometry(); + tmpGeo.faces = this.faces; - this.vertexNormals[ i ] = source.vertexNormals[ i ].clone(); + for ( i = 0, il = this.morphTargets.length; i < il; i ++ ) { - } + // create on first access - for ( var i = 0, il = source.vertexColors.length; i < il; i ++ ) { + if ( ! this.morphNormals[ i ] ) { - this.vertexColors[ i ] = source.vertexColors[ i ].clone(); + this.morphNormals[ i ] = {}; + this.morphNormals[ i ].faceNormals = []; + this.morphNormals[ i ].vertexNormals = []; - } + var dstNormalsFace = this.morphNormals[ i ].faceNormals; + var dstNormalsVertex = this.morphNormals[ i ].vertexNormals; - return this; + var faceNormal, vertexNormals; - } + for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { - } ); + faceNormal = new Vector3(); + vertexNormals = { a: new Vector3(), b: new Vector3(), c: new Vector3() }; - /** - * @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.TextureCube( [posx, negx, posy, negy, posz, negz] ), - * combine: THREE.Multiply, - * reflectivity: , - * refractionRatio: , - * - * shading: THREE.SmoothShading, - * depthTest: , - * depthWrite: , - * - * wireframe: , - * wireframeLinewidth: , - * - * skinning: , - * morphTargets: - * } - */ + dstNormalsFace.push( faceNormal ); + dstNormalsVertex.push( vertexNormals ); - function MeshBasicMaterial( parameters ) { + } - Material.call( this ); + } - this.type = 'MeshBasicMaterial'; + var morphNormals = this.morphNormals[ i ]; - this.color = new Color( 0xffffff ); // emissive + // set vertices to morph target - this.map = null; + tmpGeo.vertices = this.morphTargets[ i ].vertices; - this.lightMap = null; - this.lightMapIntensity = 1.0; + // compute morph normals - this.aoMap = null; - this.aoMapIntensity = 1.0; + tmpGeo.computeFaceNormals(); + tmpGeo.computeVertexNormals(); - this.specularMap = null; + // store morph normals - this.alphaMap = null; + var faceNormal, vertexNormals; - this.envMap = null; - this.combine = MultiplyOperation; - this.reflectivity = 1; - this.refractionRatio = 0.98; + for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { - this.wireframe = false; - this.wireframeLinewidth = 1; - this.wireframeLinecap = 'round'; - this.wireframeLinejoin = 'round'; + face = this.faces[ f ]; - this.skinning = false; - this.morphTargets = false; + faceNormal = morphNormals.faceNormals[ f ]; + vertexNormals = morphNormals.vertexNormals[ f ]; - this.lights = false; + faceNormal.copy( face.normal ); - this.setValues( parameters ); + vertexNormals.a.copy( face.vertexNormals[ 0 ] ); + vertexNormals.b.copy( face.vertexNormals[ 1 ] ); + vertexNormals.c.copy( face.vertexNormals[ 2 ] ); - } + } - MeshBasicMaterial.prototype = Object.create( Material.prototype ); - MeshBasicMaterial.prototype.constructor = MeshBasicMaterial; + } - MeshBasicMaterial.prototype.isMeshBasicMaterial = true; + // restore original normals - MeshBasicMaterial.prototype.copy = function ( source ) { + for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { - Material.prototype.copy.call( this, source ); + face = this.faces[ f ]; - this.color.copy( source.color ); + face.normal = face.__originalFaceNormal; + face.vertexNormals = face.__originalVertexNormals; - this.map = source.map; + } - this.lightMap = source.lightMap; - this.lightMapIntensity = source.lightMapIntensity; + }, - this.aoMap = source.aoMap; - this.aoMapIntensity = source.aoMapIntensity; + computeLineDistances: function () { - this.specularMap = source.specularMap; + var d = 0; + var vertices = this.vertices; - this.alphaMap = source.alphaMap; + for ( var i = 0, il = vertices.length; i < il; i ++ ) { - this.envMap = source.envMap; - this.combine = source.combine; - this.reflectivity = source.reflectivity; - this.refractionRatio = source.refractionRatio; + if ( i > 0 ) { - this.wireframe = source.wireframe; - this.wireframeLinewidth = source.wireframeLinewidth; - this.wireframeLinecap = source.wireframeLinecap; - this.wireframeLinejoin = source.wireframeLinejoin; + d += vertices[ i ].distanceTo( vertices[ i - 1 ] ); - this.skinning = source.skinning; - this.morphTargets = source.morphTargets; + } - return this; + this.lineDistances[ i ] = d; - }; + } - /** - * @author mrdoob / http://mrdoob.com/ - */ + }, - function BufferAttribute( array, itemSize, normalized ) { + computeBoundingBox: function () { - if ( Array.isArray( array ) ) { + if ( this.boundingBox === null ) { - throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' ); + this.boundingBox = new Box3(); - } + } - this.uuid = _Math.generateUUID(); - this.name = ''; + this.boundingBox.setFromPoints( this.vertices ); - 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 }; + computeBoundingSphere: function () { - this.onUploadCallback = function () {}; + if ( this.boundingSphere === null ) { - this.version = 0; + this.boundingSphere = new Sphere(); - } + } - Object.defineProperty( BufferAttribute.prototype, 'needsUpdate', { + this.boundingSphere.setFromPoints( this.vertices ); - set: function ( value ) { + }, - if ( value === true ) this.version ++; + merge: function ( geometry, matrix, materialIndexOffset ) { - } + if ( ! ( geometry && geometry.isGeometry ) ) { - } ); + console.error( 'THREE.Geometry.merge(): geometry not an instance of THREE.Geometry.', geometry ); + return; - Object.assign( BufferAttribute.prototype, { + } - isBufferAttribute: true, + var normalMatrix, + vertexOffset = this.vertices.length, + vertices1 = this.vertices, + vertices2 = geometry.vertices, + faces1 = this.faces, + faces2 = geometry.faces, + uvs1 = this.faceVertexUvs[ 0 ], + uvs2 = geometry.faceVertexUvs[ 0 ], + colors1 = this.colors, + colors2 = geometry.colors; - setArray: function ( array ) { + if ( materialIndexOffset === undefined ) materialIndexOffset = 0; - if ( Array.isArray( array ) ) { + if ( matrix !== undefined ) { - throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' ); + normalMatrix = new Matrix3().getNormalMatrix( matrix ); } - this.count = array !== undefined ? array.length / this.itemSize : 0; - this.array = array; + // vertices - }, + for ( var i = 0, il = vertices2.length; i < il; i ++ ) { - setDynamic: function ( value ) { + var vertex = vertices2[ i ]; - this.dynamic = value; + var vertexCopy = vertex.clone(); - return this; + if ( matrix !== undefined ) vertexCopy.applyMatrix4( matrix ); - }, + vertices1.push( vertexCopy ); - copy: function ( source ) { + } - this.array = new source.array.constructor( source.array ); - this.itemSize = source.itemSize; - this.count = source.count; - this.normalized = source.normalized; + // colors - this.dynamic = source.dynamic; + for ( var i = 0, il = colors2.length; i < il; i ++ ) { - return this; + colors1.push( colors2[ i ].clone() ); - }, + } - copyAt: function ( index1, attribute, index2 ) { + // faces - index1 *= this.itemSize; - index2 *= attribute.itemSize; + for ( i = 0, il = faces2.length; i < il; i ++ ) { - for ( var i = 0, l = this.itemSize; i < l; i ++ ) { + var face = faces2[ i ], faceCopy, normal, color, + faceVertexNormals = face.vertexNormals, + faceVertexColors = face.vertexColors; - this.array[ index1 + i ] = attribute.array[ index2 + i ]; + faceCopy = new Face3( face.a + vertexOffset, face.b + vertexOffset, face.c + vertexOffset ); + faceCopy.normal.copy( face.normal ); - } + if ( normalMatrix !== undefined ) { - return this; + faceCopy.normal.applyMatrix3( normalMatrix ).normalize(); - }, + } - copyArray: function ( array ) { + for ( var j = 0, jl = faceVertexNormals.length; j < jl; j ++ ) { - this.array.set( array ); + normal = faceVertexNormals[ j ].clone(); - return this; + if ( normalMatrix !== undefined ) { - }, + normal.applyMatrix3( normalMatrix ).normalize(); - copyColorsArray: function ( colors ) { + } - var array = this.array, offset = 0; + faceCopy.vertexNormals.push( normal ); - for ( var i = 0, l = colors.length; i < l; i ++ ) { + } - var color = colors[ i ]; + faceCopy.color.copy( face.color ); - if ( color === undefined ) { + for ( var j = 0, jl = faceVertexColors.length; j < jl; j ++ ) { - console.warn( 'THREE.BufferAttribute.copyColorsArray(): color is undefined', i ); - color = new Color(); + color = faceVertexColors[ j ]; + faceCopy.vertexColors.push( color.clone() ); } - array[ offset ++ ] = color.r; - array[ offset ++ ] = color.g; - array[ offset ++ ] = color.b; + faceCopy.materialIndex = face.materialIndex + materialIndexOffset; + + faces1.push( faceCopy ); } - return this; + // uvs - }, + for ( i = 0, il = uvs2.length; i < il; i ++ ) { - copyIndicesArray: function ( indices ) { + var uv = uvs2[ i ], uvCopy = []; - var array = this.array, offset = 0; + if ( uv === undefined ) { - for ( var i = 0, l = indices.length; i < l; i ++ ) { + continue; - var index = indices[ i ]; + } - array[ offset ++ ] = index.a; - array[ offset ++ ] = index.b; - array[ offset ++ ] = index.c; + for ( var j = 0, jl = uv.length; j < jl; j ++ ) { - } + uvCopy.push( uv[ j ].clone() ); - return this; + } + + uvs1.push( uvCopy ); + + } }, - copyVector2sArray: function ( vectors ) { + mergeMesh: function ( mesh ) { - var array = this.array, offset = 0; + if ( ! ( mesh && mesh.isMesh ) ) { - for ( var i = 0, l = vectors.length; i < l; i ++ ) { + console.error( 'THREE.Geometry.mergeMesh(): mesh not an instance of THREE.Mesh.', mesh ); + return; - var vector = vectors[ i ]; + } - if ( vector === undefined ) { + mesh.matrixAutoUpdate && mesh.updateMatrix(); - console.warn( 'THREE.BufferAttribute.copyVector2sArray(): vector is undefined', i ); - vector = new Vector2(); + this.merge( mesh.geometry, mesh.matrix ); - } + }, - array[ offset ++ ] = vector.x; - array[ offset ++ ] = vector.y; + /* + * Checks for duplicate vertices with hashmap. + * Duplicated vertices are removed + * and faces' vertices are updated. + */ - } + mergeVertices: function () { - return this; + 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; - copyVector3sArray: function ( vectors ) { + for ( i = 0, il = this.vertices.length; i < il; i ++ ) { - var array = this.array, offset = 0; + v = this.vertices[ i ]; + key = Math.round( v.x * precision ) + '_' + Math.round( v.y * precision ) + '_' + Math.round( v.z * precision ); - for ( var i = 0, l = vectors.length; i < l; i ++ ) { + if ( verticesMap[ key ] === undefined ) { - var vector = vectors[ i ]; + verticesMap[ key ] = i; + unique.push( this.vertices[ i ] ); + changes[ i ] = unique.length - 1; - if ( vector === undefined ) { + } else { - console.warn( 'THREE.BufferAttribute.copyVector3sArray(): vector is undefined', i ); - vector = new Vector3(); + //console.log('Duplicate vertex found. ', i, ' could be using ', verticesMap[key]); + changes[ i ] = changes[ verticesMap[ key ] ]; } - array[ offset ++ ] = vector.x; - array[ offset ++ ] = vector.y; - array[ offset ++ ] = vector.z; - } - return this; - }, + // if faces are completely degenerate after merging vertices, we + // have to remove them from the geometry. + var faceIndicesToRemove = []; - copyVector4sArray: function ( vectors ) { + for ( i = 0, il = this.faces.length; i < il; i ++ ) { - var array = this.array, offset = 0; + face = this.faces[ i ]; - for ( var i = 0, l = vectors.length; i < l; i ++ ) { + face.a = changes[ face.a ]; + face.b = changes[ face.b ]; + face.c = changes[ face.c ]; - var vector = vectors[ i ]; + indices = [ face.a, face.b, face.c ]; - if ( vector === undefined ) { + // 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 ++ ) { - console.warn( 'THREE.BufferAttribute.copyVector4sArray(): vector is undefined', i ); - vector = new Vector4(); + if ( indices[ n ] === indices[ ( n + 1 ) % 3 ] ) { - } + faceIndicesToRemove.push( i ); + break; - array[ offset ++ ] = vector.x; - array[ offset ++ ] = vector.y; - array[ offset ++ ] = vector.z; - array[ offset ++ ] = vector.w; + } + + } } - return this; + for ( i = faceIndicesToRemove.length - 1; i >= 0; i -- ) { - }, + var idx = faceIndicesToRemove[ i ]; - set: function ( value, offset ) { + this.faces.splice( idx, 1 ); - if ( offset === undefined ) offset = 0; + for ( j = 0, jl = this.faceVertexUvs.length; j < jl; j ++ ) { - this.array.set( value, offset ); + this.faceVertexUvs[ j ].splice( idx, 1 ); - return this; + } - }, + } - getX: function ( index ) { + // Use unique set of vertices - return this.array[ index * this.itemSize ]; + var diff = this.vertices.length - unique.length; + this.vertices = unique; + return diff; }, - setX: function ( index, x ) { + sortFacesByMaterialIndex: function () { - this.array[ index * this.itemSize ] = x; + var faces = this.faces; + var length = faces.length; - return this; + // tag faces - }, + for ( var i = 0; i < length; i ++ ) { - getY: function ( index ) { + faces[ i ]._id = i; - return this.array[ index * this.itemSize + 1 ]; + } - }, + // sort faces - setY: function ( index, y ) { + function materialIndexSort( a, b ) { - this.array[ index * this.itemSize + 1 ] = y; + return a.materialIndex - b.materialIndex; - return this; + } - }, + faces.sort( materialIndexSort ); - getZ: function ( index ) { + // sort uvs - return this.array[ index * this.itemSize + 2 ]; + var uvs1 = this.faceVertexUvs[ 0 ]; + var uvs2 = this.faceVertexUvs[ 1 ]; - }, + var newUvs1, newUvs2; - setZ: function ( index, z ) { + if ( uvs1 && uvs1.length === length ) newUvs1 = []; + if ( uvs2 && uvs2.length === length ) newUvs2 = []; - this.array[ index * this.itemSize + 2 ] = z; + for ( var i = 0; i < length; i ++ ) { - return this; + var id = faces[ i ]._id; - }, + if ( newUvs1 ) newUvs1.push( uvs1[ id ] ); + if ( newUvs2 ) newUvs2.push( uvs2[ id ] ); - getW: function ( index ) { + } - return this.array[ index * this.itemSize + 3 ]; + if ( newUvs1 ) this.faceVertexUvs[ 0 ] = newUvs1; + if ( newUvs2 ) this.faceVertexUvs[ 1 ] = newUvs2; }, - setW: function ( index, w ) { - - this.array[ index * this.itemSize + 3 ] = w; - - return this; + toJSON: function () { - }, + var data = { + metadata: { + version: 4.5, + type: 'Geometry', + generator: 'Geometry.toJSON' + } + }; - setXY: function ( index, x, y ) { + // standard Geometry serialization - index *= this.itemSize; + data.uuid = this.uuid; + data.type = this.type; + if ( this.name !== '' ) data.name = this.name; - this.array[ index + 0 ] = x; - this.array[ index + 1 ] = y; + if ( this.parameters !== undefined ) { - return this; + var parameters = this.parameters; - }, + for ( var key in parameters ) { - setXYZ: function ( index, x, y, z ) { + if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ]; - index *= this.itemSize; + } - this.array[ index + 0 ] = x; - this.array[ index + 1 ] = y; - this.array[ index + 2 ] = z; + return data; - return this; + } - }, + var vertices = []; - setXYZW: function ( index, x, y, z, w ) { + for ( var i = 0; i < this.vertices.length; i ++ ) { - index *= this.itemSize; + var vertex = this.vertices[ i ]; + vertices.push( vertex.x, vertex.y, vertex.z ); - this.array[ index + 0 ] = x; - this.array[ index + 1 ] = y; - this.array[ index + 2 ] = z; - this.array[ index + 3 ] = w; + } - return this; + var faces = []; + var normals = []; + var normalsHash = {}; + var colors = []; + var colorsHash = {}; + var uvs = []; + var uvsHash = {}; - }, + for ( var i = 0; i < this.faces.length; i ++ ) { - onUpload: function ( callback ) { + var face = this.faces[ i ]; - this.onUploadCallback = callback; + 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; - return this; + var faceType = 0; - }, + faceType = setBit( faceType, 0, 0 ); // isQuad + faceType = setBit( faceType, 1, hasMaterial ); + faceType = setBit( faceType, 2, hasFaceUv ); + faceType = setBit( faceType, 3, hasFaceVertexUv ); + faceType = setBit( faceType, 4, hasFaceNormal ); + faceType = setBit( faceType, 5, hasFaceVertexNormal ); + faceType = setBit( faceType, 6, hasFaceColor ); + faceType = setBit( faceType, 7, hasFaceVertexColor ); - clone: function () { + faces.push( faceType ); + faces.push( face.a, face.b, face.c ); + faces.push( face.materialIndex ); - return new this.constructor( this.array, this.itemSize ).copy( this ); + if ( hasFaceVertexUv ) { - } + var faceVertexUvs = this.faceVertexUvs[ 0 ][ i ]; - } ); + faces.push( + getUvIndex( faceVertexUvs[ 0 ] ), + getUvIndex( faceVertexUvs[ 1 ] ), + getUvIndex( faceVertexUvs[ 2 ] ) + ); - // + } - function Int8BufferAttribute( array, itemSize ) { + if ( hasFaceNormal ) { - BufferAttribute.call( this, new Int8Array( array ), itemSize ); + faces.push( getNormalIndex( face.normal ) ); - } + } - Int8BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); - Int8BufferAttribute.prototype.constructor = Int8BufferAttribute; + if ( hasFaceVertexNormal ) { + var vertexNormals = face.vertexNormals; - function Uint8BufferAttribute( array, itemSize ) { + faces.push( + getNormalIndex( vertexNormals[ 0 ] ), + getNormalIndex( vertexNormals[ 1 ] ), + getNormalIndex( vertexNormals[ 2 ] ) + ); - BufferAttribute.call( this, new Uint8Array( array ), itemSize ); + } - } + if ( hasFaceColor ) { - Uint8BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); - Uint8BufferAttribute.prototype.constructor = Uint8BufferAttribute; + faces.push( getColorIndex( face.color ) ); + } - function Uint8ClampedBufferAttribute( array, itemSize ) { + if ( hasFaceVertexColor ) { - BufferAttribute.call( this, new Uint8ClampedArray( array ), itemSize ); + var vertexColors = face.vertexColors; - } + faces.push( + getColorIndex( vertexColors[ 0 ] ), + getColorIndex( vertexColors[ 1 ] ), + getColorIndex( vertexColors[ 2 ] ) + ); - Uint8ClampedBufferAttribute.prototype = Object.create( BufferAttribute.prototype ); - Uint8ClampedBufferAttribute.prototype.constructor = Uint8ClampedBufferAttribute; + } + } - function Int16BufferAttribute( array, itemSize ) { + function setBit( value, position, enabled ) { - BufferAttribute.call( this, new Int16Array( array ), itemSize ); + return enabled ? value | ( 1 << position ) : value & ( ~ ( 1 << position ) ); - } + } - Int16BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); - Int16BufferAttribute.prototype.constructor = Int16BufferAttribute; + function getNormalIndex( normal ) { + var hash = normal.x.toString() + normal.y.toString() + normal.z.toString(); - function Uint16BufferAttribute( array, itemSize ) { + if ( normalsHash[ hash ] !== undefined ) { - BufferAttribute.call( this, new Uint16Array( array ), itemSize ); + return normalsHash[ hash ]; - } + } - Uint16BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); - Uint16BufferAttribute.prototype.constructor = Uint16BufferAttribute; + normalsHash[ hash ] = normals.length / 3; + normals.push( normal.x, normal.y, normal.z ); + return normalsHash[ hash ]; - function Int32BufferAttribute( array, itemSize ) { + } - BufferAttribute.call( this, new Int32Array( array ), itemSize ); + function getColorIndex( color ) { - } + var hash = color.r.toString() + color.g.toString() + color.b.toString(); - Int32BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); - Int32BufferAttribute.prototype.constructor = Int32BufferAttribute; + if ( colorsHash[ hash ] !== undefined ) { + return colorsHash[ hash ]; - function Uint32BufferAttribute( array, itemSize ) { + } - BufferAttribute.call( this, new Uint32Array( array ), itemSize ); + colorsHash[ hash ] = colors.length; + colors.push( color.getHex() ); - } + return colorsHash[ hash ]; - Uint32BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); - Uint32BufferAttribute.prototype.constructor = Uint32BufferAttribute; + } + function getUvIndex( uv ) { - function Float32BufferAttribute( array, itemSize ) { + var hash = uv.x.toString() + uv.y.toString(); - BufferAttribute.call( this, new Float32Array( array ), itemSize ); + if ( uvsHash[ hash ] !== undefined ) { - } + return uvsHash[ hash ]; - Float32BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); - Float32BufferAttribute.prototype.constructor = Float32BufferAttribute; + } + uvsHash[ hash ] = uvs.length / 2; + uvs.push( uv.x, uv.y ); - function Float64BufferAttribute( array, itemSize ) { + return uvsHash[ hash ]; - BufferAttribute.call( this, new Float64Array( array ), itemSize ); + } - } + data.data = {}; - Float64BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); - Float64BufferAttribute.prototype.constructor = Float64BufferAttribute; + 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; - /** - * @author mrdoob / http://mrdoob.com/ - */ + return data; - function DirectGeometry() { + }, - this.indices = []; - this.vertices = []; - this.normals = []; - this.colors = []; - this.uvs = []; - this.uvs2 = []; + clone: function () { - this.groups = []; + /* + // Handle primitives - this.morphTargets = {}; + var parameters = this.parameters; - this.skinWeights = []; - this.skinIndices = []; + if ( parameters !== undefined ) { - // this.lineDistances = []; + var values = []; - this.boundingBox = null; - this.boundingSphere = null; + for ( var key in parameters ) { - // update flags + values.push( parameters[ key ] ); - this.verticesNeedUpdate = false; - this.normalsNeedUpdate = false; - this.colorsNeedUpdate = false; - this.uvsNeedUpdate = false; - this.groupsNeedUpdate = false; + } - } + var geometry = Object.create( this.constructor.prototype ); + this.constructor.apply( geometry, values ); + return geometry; - Object.assign( DirectGeometry.prototype, { + } - computeGroups: function ( geometry ) { + return new this.constructor().copy( this ); + */ - var group; - var groups = []; - var materialIndex = undefined; + return new Geometry().copy( this ); - var faces = geometry.faces; + }, - for ( var i = 0; i < faces.length; i ++ ) { + copy: function ( source ) { - var face = faces[ i ]; + var i, il, j, jl, k, kl; - // materials + // reset - if ( face.materialIndex !== materialIndex ) { + this.vertices = []; + this.colors = []; + this.faces = []; + this.faceVertexUvs = [[]]; + this.morphTargets = []; + this.morphNormals = []; + this.skinWeights = []; + this.skinIndices = []; + this.lineDistances = []; + this.boundingBox = null; + this.boundingSphere = null; - materialIndex = face.materialIndex; + // name - if ( group !== undefined ) { + this.name = source.name; - group.count = ( i * 3 ) - group.start; - groups.push( group ); + // vertices - } + var vertices = source.vertices; - group = { - start: i * 3, - materialIndex: materialIndex - }; + for ( i = 0, il = vertices.length; i < il; i ++ ) { - } + this.vertices.push( vertices[ i ].clone() ); } - if ( group !== undefined ) { + // colors - group.count = ( i * 3 ) - group.start; - groups.push( group ); + var colors = source.colors; - } + for ( i = 0, il = colors.length; i < il; i ++ ) { - this.groups = groups; + this.colors.push( colors[ i ].clone() ); - }, + } - fromGeometry: function ( geometry ) { + // faces - var faces = geometry.faces; - var vertices = geometry.vertices; - var faceVertexUvs = geometry.faceVertexUvs; + var faces = source.faces; - var hasFaceVertexUv = faceVertexUvs[ 0 ] && faceVertexUvs[ 0 ].length > 0; - var hasFaceVertexUv2 = faceVertexUvs[ 1 ] && faceVertexUvs[ 1 ].length > 0; + for ( i = 0, il = faces.length; i < il; i ++ ) { - // morphs + this.faces.push( faces[ i ].clone() ); - var morphTargets = geometry.morphTargets; - var morphTargetsLength = morphTargets.length; + } - var morphTargetsPosition; + // face vertex uvs - if ( morphTargetsLength > 0 ) { + for ( i = 0, il = source.faceVertexUvs.length; i < il; i ++ ) { - morphTargetsPosition = []; + var faceVertexUvs = source.faceVertexUvs[ i ]; - for ( var i = 0; i < morphTargetsLength; i ++ ) { + if ( this.faceVertexUvs[ i ] === undefined ) { - morphTargetsPosition[ i ] = []; + this.faceVertexUvs[ i ] = []; } - this.morphTargets.position = morphTargetsPosition; - - } + for ( j = 0, jl = faceVertexUvs.length; j < jl; j ++ ) { - var morphNormals = geometry.morphNormals; - var morphNormalsLength = morphNormals.length; + var uvs = faceVertexUvs[ j ], uvsCopy = []; - var morphTargetsNormal; + for ( k = 0, kl = uvs.length; k < kl; k ++ ) { - if ( morphNormalsLength > 0 ) { + var uv = uvs[ k ]; - morphTargetsNormal = []; + uvsCopy.push( uv.clone() ); - for ( var i = 0; i < morphNormalsLength; i ++ ) { + } - morphTargetsNormal[ i ] = []; + this.faceVertexUvs[ i ].push( uvsCopy ); } - this.morphTargets.normal = morphTargetsNormal; - } - // skins - - var skinIndices = geometry.skinIndices; - var skinWeights = geometry.skinWeights; - - var hasSkinIndices = skinIndices.length === vertices.length; - var hasSkinWeights = skinWeights.length === vertices.length; - - // + // morph targets - for ( var i = 0; i < faces.length; i ++ ) { + var morphTargets = source.morphTargets; - var face = faces[ i ]; + for ( i = 0, il = morphTargets.length; i < il; i ++ ) { - this.vertices.push( vertices[ face.a ], vertices[ face.b ], vertices[ face.c ] ); + var morphTarget = {}; + morphTarget.name = morphTargets[ i ].name; - var vertexNormals = face.vertexNormals; + // vertices - if ( vertexNormals.length === 3 ) { + if ( morphTargets[ i ].vertices !== undefined ) { - this.normals.push( vertexNormals[ 0 ], vertexNormals[ 1 ], vertexNormals[ 2 ] ); + morphTarget.vertices = []; - } else { + for ( j = 0, jl = morphTargets[ i ].vertices.length; j < jl; j ++ ) { - var normal = face.normal; + morphTarget.vertices.push( morphTargets[ i ].vertices[ j ].clone() ); - this.normals.push( normal, normal, normal ); + } } - var vertexColors = face.vertexColors; + // normals - if ( vertexColors.length === 3 ) { + if ( morphTargets[ i ].normals !== undefined ) { - this.colors.push( vertexColors[ 0 ], vertexColors[ 1 ], vertexColors[ 2 ] ); + morphTarget.normals = []; - } else { + for ( j = 0, jl = morphTargets[ i ].normals.length; j < jl; j ++ ) { - var color = face.color; + morphTarget.normals.push( morphTargets[ i ].normals[ j ].clone() ); - this.colors.push( color, color, color ); + } } - if ( hasFaceVertexUv === true ) { - - var vertexUvs = faceVertexUvs[ 0 ][ i ]; - - if ( vertexUvs !== undefined ) { - - this.uvs.push( vertexUvs[ 0 ], vertexUvs[ 1 ], vertexUvs[ 2 ] ); + this.morphTargets.push( morphTarget ); - } else { + } - console.warn( 'THREE.DirectGeometry.fromGeometry(): Undefined vertexUv ', i ); + // morph normals - this.uvs.push( new Vector2(), new Vector2(), new Vector2() ); + var morphNormals = source.morphNormals; - } + for ( i = 0, il = morphNormals.length; i < il; i ++ ) { - } + var morphNormal = {}; - if ( hasFaceVertexUv2 === true ) { + // vertex normals - var vertexUvs = faceVertexUvs[ 1 ][ i ]; + if ( morphNormals[ i ].vertexNormals !== undefined ) { - if ( vertexUvs !== undefined ) { + morphNormal.vertexNormals = []; - this.uvs2.push( vertexUvs[ 0 ], vertexUvs[ 1 ], vertexUvs[ 2 ] ); + for ( j = 0, jl = morphNormals[ i ].vertexNormals.length; j < jl; j ++ ) { - } else { + var srcVertexNormal = morphNormals[ i ].vertexNormals[ j ]; + var destVertexNormal = {}; - console.warn( 'THREE.DirectGeometry.fromGeometry(): Undefined vertexUv2 ', i ); + destVertexNormal.a = srcVertexNormal.a.clone(); + destVertexNormal.b = srcVertexNormal.b.clone(); + destVertexNormal.c = srcVertexNormal.c.clone(); - this.uvs2.push( new Vector2(), new Vector2(), new Vector2() ); + morphNormal.vertexNormals.push( destVertexNormal ); } } - // morphs + // face normals - for ( var j = 0; j < morphTargetsLength; j ++ ) { + if ( morphNormals[ i ].faceNormals !== undefined ) { - var morphTarget = morphTargets[ j ].vertices; + morphNormal.faceNormals = []; - morphTargetsPosition[ j ].push( morphTarget[ face.a ], morphTarget[ face.b ], morphTarget[ face.c ] ); + for ( j = 0, jl = morphNormals[ i ].faceNormals.length; j < jl; j ++ ) { + + morphNormal.faceNormals.push( morphNormals[ i ].faceNormals[ j ].clone() ); + + } } - for ( var j = 0; j < morphNormalsLength; j ++ ) { + this.morphNormals.push( morphNormal ); - var morphNormal = morphNormals[ j ].vertexNormals[ i ]; + } - morphTargetsNormal[ j ].push( morphNormal.a, morphNormal.b, morphNormal.c ); + // skin weights - } + var skinWeights = source.skinWeights; - // skins + for ( i = 0, il = skinWeights.length; i < il; i ++ ) { - if ( hasSkinIndices ) { + this.skinWeights.push( skinWeights[ i ].clone() ); - this.skinIndices.push( skinIndices[ face.a ], skinIndices[ face.b ], skinIndices[ face.c ] ); + } - } + // skin indices - if ( hasSkinWeights ) { + var skinIndices = source.skinIndices; - this.skinWeights.push( skinWeights[ face.a ], skinWeights[ face.b ], skinWeights[ face.c ] ); + for ( i = 0, il = skinIndices.length; i < il; i ++ ) { - } + this.skinIndices.push( skinIndices[ i ].clone() ); } - this.computeGroups( geometry ); + // line distances - this.verticesNeedUpdate = geometry.verticesNeedUpdate; - this.normalsNeedUpdate = geometry.normalsNeedUpdate; - this.colorsNeedUpdate = geometry.colorsNeedUpdate; - this.uvsNeedUpdate = geometry.uvsNeedUpdate; - this.groupsNeedUpdate = geometry.groupsNeedUpdate; + var lineDistances = source.lineDistances; - return this; + for ( i = 0, il = lineDistances.length; i < il; i ++ ) { - } + this.lineDistances.push( lineDistances[ i ] ); - } ); + } - function arrayMax( array ) { + // bounding box - if ( array.length === 0 ) return - Infinity; + var boundingBox = source.boundingBox; - var max = array[ 0 ]; + if ( boundingBox !== null ) { - for ( var i = 1, l = array.length; i < l; ++ i ) { + this.boundingBox = boundingBox.clone(); - if ( array[ i ] > max ) max = array[ i ]; + } - } + // bounding sphere - return max; + var boundingSphere = source.boundingSphere; - } + if ( boundingSphere !== null ) { - /** - * @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 - */ + this.boundingSphere = boundingSphere.clone(); - var count = 0; - function GeometryIdCount() { return count++; } + } - function Geometry() { + // update flags - Object.defineProperty( this, 'id', { value: GeometryIdCount() } ); + 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; - this.uuid = _Math.generateUUID(); + return this; - this.name = ''; - this.type = 'Geometry'; + }, - this.vertices = []; - this.colors = []; - this.faces = []; - this.faceVertexUvs = [[]]; + dispose: function () { - this.morphTargets = []; - this.morphNormals = []; + this.dispatchEvent( { type: 'dispose' } ); - this.skinWeights = []; - this.skinIndices = []; + } - this.lineDistances = []; + } ); - this.boundingBox = null; - this.boundingSphere = null; + /** + * @author mrdoob / http://mrdoob.com/ + */ - // update flags + function BufferAttribute( array, itemSize, normalized ) { - this.elementsNeedUpdate = false; - this.verticesNeedUpdate = false; - this.uvsNeedUpdate = false; - this.normalsNeedUpdate = false; - this.colorsNeedUpdate = false; - this.lineDistancesNeedUpdate = false; - this.groupsNeedUpdate = false; + if ( Array.isArray( array ) ) { - } + throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' ); - Object.assign( Geometry.prototype, EventDispatcher.prototype, { + } - isGeometry: true, + this.uuid = _Math.generateUUID(); + this.name = ''; - applyMatrix: function ( matrix ) { + this.array = array; + this.itemSize = itemSize; + this.count = array !== undefined ? array.length / itemSize : 0; + this.normalized = normalized === true; - var normalMatrix = new Matrix3().getNormalMatrix( matrix ); + this.dynamic = false; + this.updateRange = { offset: 0, count: - 1 }; - for ( var i = 0, il = this.vertices.length; i < il; i ++ ) { + this.onUploadCallback = function () {}; - var vertex = this.vertices[ i ]; - vertex.applyMatrix4( matrix ); + this.version = 0; - } + } - for ( var i = 0, il = this.faces.length; i < il; i ++ ) { + Object.defineProperty( BufferAttribute.prototype, 'needsUpdate', { - var face = this.faces[ i ]; - face.normal.applyMatrix3( normalMatrix ).normalize(); + set: function ( value ) { - for ( var j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) { + if ( value === true ) this.version ++; - face.vertexNormals[ j ].applyMatrix3( normalMatrix ).normalize(); + } - } + } ); - } + Object.assign( BufferAttribute.prototype, { - if ( this.boundingBox !== null ) { + isBufferAttribute: true, - this.computeBoundingBox(); + setArray: function ( array ) { + + if ( Array.isArray( array ) ) { + + throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' ); } - if ( this.boundingSphere !== null ) { + this.count = array !== undefined ? array.length / this.itemSize : 0; + this.array = array; - this.computeBoundingSphere(); + }, - } + setDynamic: function ( value ) { - this.verticesNeedUpdate = true; - this.normalsNeedUpdate = true; + this.dynamic = value; return this; }, - rotateX: function () { + copy: function ( source ) { - // rotate geometry around world x-axis + this.array = new source.array.constructor( source.array ); + this.itemSize = source.itemSize; + this.count = source.count; + this.normalized = source.normalized; - var m1 = new Matrix4(); + this.dynamic = source.dynamic; - return function rotateX( angle ) { + return this; - m1.makeRotationX( angle ); + }, - this.applyMatrix( m1 ); + copyAt: function ( index1, attribute, index2 ) { - return this; + index1 *= this.itemSize; + index2 *= attribute.itemSize; - }; + for ( var i = 0, l = this.itemSize; i < l; i ++ ) { - }(), + this.array[ index1 + i ] = attribute.array[ index2 + i ]; - rotateY: function () { + } - // rotate geometry around world y-axis + return this; - var m1 = new Matrix4(); + }, - return function rotateY( angle ) { + copyArray: function ( array ) { - m1.makeRotationY( angle ); + this.array.set( array ); - this.applyMatrix( m1 ); + return this; - return this; + }, - }; + copyColorsArray: function ( colors ) { - }(), + var array = this.array, offset = 0; - rotateZ: function () { + for ( var i = 0, l = colors.length; i < l; i ++ ) { - // rotate geometry around world z-axis + var color = colors[ i ]; - var m1 = new Matrix4(); + if ( color === undefined ) { - return function rotateZ( angle ) { + console.warn( 'THREE.BufferAttribute.copyColorsArray(): color is undefined', i ); + color = new Color(); - m1.makeRotationZ( angle ); + } - this.applyMatrix( m1 ); + array[ offset ++ ] = color.r; + array[ offset ++ ] = color.g; + array[ offset ++ ] = color.b; - return this; + } - }; + return this; - }(), + }, - translate: function () { + copyIndicesArray: function ( indices ) { - // translate geometry + var array = this.array, offset = 0; - var m1 = new Matrix4(); + for ( var i = 0, l = indices.length; i < l; i ++ ) { - return function translate( x, y, z ) { + var index = indices[ i ]; - m1.makeTranslation( x, y, z ); + array[ offset ++ ] = index.a; + array[ offset ++ ] = index.b; + array[ offset ++ ] = index.c; - this.applyMatrix( m1 ); + } - return this; + return this; - }; + }, - }(), + copyVector2sArray: function ( vectors ) { - scale: function () { + var array = this.array, offset = 0; - // scale geometry + for ( var i = 0, l = vectors.length; i < l; i ++ ) { - var m1 = new Matrix4(); + var vector = vectors[ i ]; - return function scale( x, y, z ) { + if ( vector === undefined ) { - m1.makeScale( x, y, z ); + console.warn( 'THREE.BufferAttribute.copyVector2sArray(): vector is undefined', i ); + vector = new Vector2(); - this.applyMatrix( m1 ); + } - return this; + array[ offset ++ ] = vector.x; + array[ offset ++ ] = vector.y; - }; + } - }(), + return this; - lookAt: function () { + }, - var obj = new Object3D(); + copyVector3sArray: function ( vectors ) { - return function lookAt( vector ) { + var array = this.array, offset = 0; - obj.lookAt( vector ); + for ( var i = 0, l = vectors.length; i < l; i ++ ) { - obj.updateMatrix(); + var vector = vectors[ i ]; - this.applyMatrix( obj.matrix ); + if ( vector === undefined ) { - }; + console.warn( 'THREE.BufferAttribute.copyVector3sArray(): vector is undefined', i ); + vector = new Vector3(); - }(), + } - fromBufferGeometry: function ( geometry ) { + array[ offset ++ ] = vector.x; + array[ offset ++ ] = vector.y; + array[ offset ++ ] = vector.z; - var scope = this; + } - var indices = geometry.index !== null ? geometry.index.array : undefined; - var attributes = geometry.attributes; + return this; - 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; + }, - if ( uvs2 !== undefined ) this.faceVertexUvs[ 1 ] = []; + copyVector4sArray: function ( vectors ) { - var tempNormals = []; - var tempUVs = []; - var tempUVs2 = []; + var array = this.array, offset = 0; - for ( var i = 0, j = 0; i < positions.length; i += 3, j += 2 ) { + for ( var i = 0, l = vectors.length; i < l; i ++ ) { - scope.vertices.push( new Vector3( positions[ i ], positions[ i + 1 ], positions[ i + 2 ] ) ); + var vector = vectors[ i ]; - if ( normals !== undefined ) { + if ( vector === undefined ) { - tempNormals.push( new Vector3( normals[ i ], normals[ i + 1 ], normals[ i + 2 ] ) ); + console.warn( 'THREE.BufferAttribute.copyVector4sArray(): vector is undefined', i ); + vector = new Vector4(); } - if ( colors !== undefined ) { + array[ offset ++ ] = vector.x; + array[ offset ++ ] = vector.y; + array[ offset ++ ] = vector.z; + array[ offset ++ ] = vector.w; - scope.colors.push( new Color( colors[ i ], colors[ i + 1 ], colors[ i + 2 ] ) ); + } - } + return this; - if ( uvs !== undefined ) { + }, - tempUVs.push( new Vector2( uvs[ j ], uvs[ j + 1 ] ) ); + set: function ( value, offset ) { - } + if ( offset === undefined ) offset = 0; - if ( uvs2 !== undefined ) { + this.array.set( value, offset ); - tempUVs2.push( new Vector2( uvs2[ j ], uvs2[ j + 1 ] ) ); + return this; - } + }, - } + getX: function ( index ) { - function addFace( a, b, c, materialIndex ) { + return this.array[ index * this.itemSize ]; - var vertexNormals = normals !== undefined ? [ tempNormals[ a ].clone(), tempNormals[ b ].clone(), tempNormals[ c ].clone() ] : []; - var vertexColors = colors !== undefined ? [ scope.colors[ a ].clone(), scope.colors[ b ].clone(), scope.colors[ c ].clone() ] : []; + }, - var face = new Face3( a, b, c, vertexNormals, vertexColors, materialIndex ); + setX: function ( index, x ) { - scope.faces.push( face ); + this.array[ index * this.itemSize ] = x; - if ( uvs !== undefined ) { + return this; - scope.faceVertexUvs[ 0 ].push( [ tempUVs[ a ].clone(), tempUVs[ b ].clone(), tempUVs[ c ].clone() ] ); + }, - } + getY: function ( index ) { - if ( uvs2 !== undefined ) { + return this.array[ index * this.itemSize + 1 ]; - scope.faceVertexUvs[ 1 ].push( [ tempUVs2[ a ].clone(), tempUVs2[ b ].clone(), tempUVs2[ c ].clone() ] ); + }, - } + setY: function ( index, y ) { - } + this.array[ index * this.itemSize + 1 ] = y; - var groups = geometry.groups; + return this; - if ( groups.length > 0 ) { + }, - for ( var i = 0; i < groups.length; i ++ ) { + getZ: function ( index ) { - var group = groups[ i ]; + return this.array[ index * this.itemSize + 2 ]; - var start = group.start; - var count = group.count; + }, - for ( var j = start, jl = start + count; j < jl; j += 3 ) { + setZ: function ( index, z ) { - if ( indices !== undefined ) { + this.array[ index * this.itemSize + 2 ] = z; - addFace( indices[ j ], indices[ j + 1 ], indices[ j + 2 ], group.materialIndex ); + return this; - } else { + }, - addFace( j, j + 1, j + 2, group.materialIndex ); + getW: function ( index ) { - } + return this.array[ index * this.itemSize + 3 ]; - } + }, - } + setW: function ( index, w ) { - } else { + this.array[ index * this.itemSize + 3 ] = w; - if ( indices !== undefined ) { + return this; - for ( var i = 0; i < indices.length; i += 3 ) { + }, - addFace( indices[ i ], indices[ i + 1 ], indices[ i + 2 ] ); + setXY: function ( index, x, y ) { - } + index *= this.itemSize; - } else { + this.array[ index + 0 ] = x; + this.array[ index + 1 ] = y; - for ( var i = 0; i < positions.length / 3; i += 3 ) { + return this; - addFace( i, i + 1, i + 2 ); + }, - } + setXYZ: function ( index, x, y, z ) { - } + index *= this.itemSize; - } + this.array[ index + 0 ] = x; + this.array[ index + 1 ] = y; + this.array[ index + 2 ] = z; - this.computeFaceNormals(); + return this; - if ( geometry.boundingBox !== null ) { + }, - this.boundingBox = geometry.boundingBox.clone(); + setXYZW: function ( index, x, y, z, w ) { - } + index *= this.itemSize; - if ( geometry.boundingSphere !== null ) { + this.array[ index + 0 ] = x; + this.array[ index + 1 ] = y; + this.array[ index + 2 ] = z; + this.array[ index + 3 ] = w; - this.boundingSphere = geometry.boundingSphere.clone(); + return this; - } + }, + + onUpload: function ( callback ) { + + this.onUploadCallback = callback; return this; }, - center: function () { - - this.computeBoundingBox(); + clone: function () { - var offset = this.boundingBox.getCenter().negate(); + return new this.constructor( this.array, this.itemSize ).copy( this ); - this.translate( offset.x, offset.y, offset.z ); + } - return offset; + } ); - }, + // - normalize: function () { + function Int8BufferAttribute( array, itemSize ) { - this.computeBoundingSphere(); + BufferAttribute.call( this, new Int8Array( array ), itemSize ); - var center = this.boundingSphere.center; - var radius = this.boundingSphere.radius; + } - var s = radius === 0 ? 1 : 1.0 / radius; + Int8BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); + Int8BufferAttribute.prototype.constructor = Int8BufferAttribute; - var matrix = new Matrix4(); - matrix.set( - s, 0, 0, - s * center.x, - 0, s, 0, - s * center.y, - 0, 0, s, - s * center.z, - 0, 0, 0, 1 - ); - this.applyMatrix( matrix ); + function Uint8BufferAttribute( array, itemSize ) { - return this; + BufferAttribute.call( this, new Uint8Array( array ), itemSize ); - }, + } - computeFaceNormals: function () { + Uint8BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); + Uint8BufferAttribute.prototype.constructor = Uint8BufferAttribute; - var cb = new Vector3(), ab = new Vector3(); - for ( var f = 0, fl = this.faces.length; f < fl; f ++ ) { + function Uint8ClampedBufferAttribute( array, itemSize ) { - var face = this.faces[ f ]; + BufferAttribute.call( this, new Uint8ClampedArray( array ), itemSize ); - var vA = this.vertices[ face.a ]; - var vB = this.vertices[ face.b ]; - var vC = this.vertices[ face.c ]; + } - cb.subVectors( vC, vB ); - ab.subVectors( vA, vB ); - cb.cross( ab ); + Uint8ClampedBufferAttribute.prototype = Object.create( BufferAttribute.prototype ); + Uint8ClampedBufferAttribute.prototype.constructor = Uint8ClampedBufferAttribute; - cb.normalize(); - face.normal.copy( cb ); + function Int16BufferAttribute( array, itemSize ) { - } + BufferAttribute.call( this, new Int16Array( array ), itemSize ); - }, + } - computeVertexNormals: function ( areaWeighted ) { + Int16BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); + Int16BufferAttribute.prototype.constructor = Int16BufferAttribute; - if ( areaWeighted === undefined ) areaWeighted = true; - var v, vl, f, fl, face, vertices; + function Uint16BufferAttribute( array, itemSize ) { - vertices = new Array( this.vertices.length ); + BufferAttribute.call( this, new Uint16Array( array ), itemSize ); - for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) { + } - vertices[ v ] = new Vector3(); + Uint16BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); + Uint16BufferAttribute.prototype.constructor = Uint16BufferAttribute; - } - if ( areaWeighted ) { + function Int32BufferAttribute( array, itemSize ) { - // vertex normals weighted by triangle areas - // http://www.iquilezles.org/www/articles/normals/normals.htm + BufferAttribute.call( this, new Int32Array( array ), itemSize ); - var vA, vB, vC; - var cb = new Vector3(), ab = new Vector3(); + } - for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { + Int32BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); + Int32BufferAttribute.prototype.constructor = Int32BufferAttribute; - face = this.faces[ f ]; - vA = this.vertices[ face.a ]; - vB = this.vertices[ face.b ]; - vC = this.vertices[ face.c ]; + function Uint32BufferAttribute( array, itemSize ) { - cb.subVectors( vC, vB ); - ab.subVectors( vA, vB ); - cb.cross( ab ); + BufferAttribute.call( this, new Uint32Array( array ), itemSize ); - vertices[ face.a ].add( cb ); - vertices[ face.b ].add( cb ); - vertices[ face.c ].add( cb ); + } - } + Uint32BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); + Uint32BufferAttribute.prototype.constructor = Uint32BufferAttribute; - } else { - this.computeFaceNormals(); + function Float32BufferAttribute( array, itemSize ) { - for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { + BufferAttribute.call( this, new Float32Array( array ), itemSize ); - face = this.faces[ f ]; + } - vertices[ face.a ].add( face.normal ); - vertices[ face.b ].add( face.normal ); - vertices[ face.c ].add( face.normal ); + Float32BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); + Float32BufferAttribute.prototype.constructor = Float32BufferAttribute; - } - } + function Float64BufferAttribute( array, itemSize ) { - for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) { + BufferAttribute.call( this, new Float64Array( array ), itemSize ); - vertices[ v ].normalize(); + } - } + Float64BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); + Float64BufferAttribute.prototype.constructor = Float64BufferAttribute; - for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { + /** + * @author mrdoob / http://mrdoob.com/ + */ - face = this.faces[ f ]; + function DirectGeometry() { - var vertexNormals = face.vertexNormals; + this.indices = []; + this.vertices = []; + this.normals = []; + this.colors = []; + this.uvs = []; + this.uvs2 = []; - if ( vertexNormals.length === 3 ) { + this.groups = []; - vertexNormals[ 0 ].copy( vertices[ face.a ] ); - vertexNormals[ 1 ].copy( vertices[ face.b ] ); - vertexNormals[ 2 ].copy( vertices[ face.c ] ); + this.morphTargets = {}; - } else { + this.skinWeights = []; + this.skinIndices = []; - vertexNormals[ 0 ] = vertices[ face.a ].clone(); - vertexNormals[ 1 ] = vertices[ face.b ].clone(); - vertexNormals[ 2 ] = vertices[ face.c ].clone(); + // this.lineDistances = []; - } + this.boundingBox = null; + this.boundingSphere = null; - } + // update flags - if ( this.faces.length > 0 ) { + this.verticesNeedUpdate = false; + this.normalsNeedUpdate = false; + this.colorsNeedUpdate = false; + this.uvsNeedUpdate = false; + this.groupsNeedUpdate = false; - this.normalsNeedUpdate = true; + } - } + Object.assign( DirectGeometry.prototype, { - }, + computeGroups: function ( geometry ) { - computeFlatVertexNormals: function () { + var group; + var groups = []; + var materialIndex = undefined; - var f, fl, face; + var faces = geometry.faces; - this.computeFaceNormals(); + for ( var i = 0; i < faces.length; i ++ ) { - for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { + var face = faces[ i ]; - face = this.faces[ f ]; + // materials - var vertexNormals = face.vertexNormals; + if ( face.materialIndex !== materialIndex ) { - if ( vertexNormals.length === 3 ) { + materialIndex = face.materialIndex; - vertexNormals[ 0 ].copy( face.normal ); - vertexNormals[ 1 ].copy( face.normal ); - vertexNormals[ 2 ].copy( face.normal ); + if ( group !== undefined ) { - } else { + group.count = ( i * 3 ) - group.start; + groups.push( group ); - vertexNormals[ 0 ] = face.normal.clone(); - vertexNormals[ 1 ] = face.normal.clone(); - vertexNormals[ 2 ] = face.normal.clone(); + } + + group = { + start: i * 3, + materialIndex: materialIndex + }; } } - if ( this.faces.length > 0 ) { + if ( group !== undefined ) { - this.normalsNeedUpdate = true; + group.count = ( i * 3 ) - group.start; + groups.push( group ); } + this.groups = groups; + }, - computeMorphNormals: function () { + fromGeometry: function ( geometry ) { - var i, il, f, fl, face; + var faces = geometry.faces; + var vertices = geometry.vertices; + var faceVertexUvs = geometry.faceVertexUvs; - // save original normals - // - create temp variables on first access - // otherwise just copy (for faster repeated calls) + var hasFaceVertexUv = faceVertexUvs[ 0 ] && faceVertexUvs[ 0 ].length > 0; + var hasFaceVertexUv2 = faceVertexUvs[ 1 ] && faceVertexUvs[ 1 ].length > 0; - for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { + // morphs - face = this.faces[ f ]; + var morphTargets = geometry.morphTargets; + var morphTargetsLength = morphTargets.length; - if ( ! face.__originalFaceNormal ) { + var morphTargetsPosition; - face.__originalFaceNormal = face.normal.clone(); + if ( morphTargetsLength > 0 ) { - } else { + morphTargetsPosition = []; - face.__originalFaceNormal.copy( face.normal ); + for ( var i = 0; i < morphTargetsLength; i ++ ) { + + morphTargetsPosition[ i ] = []; } - if ( ! face.__originalVertexNormals ) face.__originalVertexNormals = []; + this.morphTargets.position = morphTargetsPosition; - for ( i = 0, il = face.vertexNormals.length; i < il; i ++ ) { + } - if ( ! face.__originalVertexNormals[ i ] ) { + var morphNormals = geometry.morphNormals; + var morphNormalsLength = morphNormals.length; - face.__originalVertexNormals[ i ] = face.vertexNormals[ i ].clone(); + var morphTargetsNormal; - } else { + if ( morphNormalsLength > 0 ) { - face.__originalVertexNormals[ i ].copy( face.vertexNormals[ i ] ); + morphTargetsNormal = []; - } + for ( var i = 0; i < morphNormalsLength; i ++ ) { + + morphTargetsNormal[ i ] = []; } + this.morphTargets.normal = morphTargetsNormal; + } - // use temp geometry to compute face and vertex normals for each morph + // skins - var tmpGeo = new Geometry(); - tmpGeo.faces = this.faces; + var skinIndices = geometry.skinIndices; + var skinWeights = geometry.skinWeights; - for ( i = 0, il = this.morphTargets.length; i < il; i ++ ) { + var hasSkinIndices = skinIndices.length === vertices.length; + var hasSkinWeights = skinWeights.length === vertices.length; - // create on first access + // - if ( ! this.morphNormals[ i ] ) { + for ( var i = 0; i < faces.length; i ++ ) { - this.morphNormals[ i ] = {}; - this.morphNormals[ i ].faceNormals = []; - this.morphNormals[ i ].vertexNormals = []; + var face = faces[ i ]; - var dstNormalsFace = this.morphNormals[ i ].faceNormals; - var dstNormalsVertex = this.morphNormals[ i ].vertexNormals; + this.vertices.push( vertices[ face.a ], vertices[ face.b ], vertices[ face.c ] ); - var faceNormal, vertexNormals; + var vertexNormals = face.vertexNormals; - for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { + if ( vertexNormals.length === 3 ) { - faceNormal = new Vector3(); - vertexNormals = { a: new Vector3(), b: new Vector3(), c: new Vector3() }; + this.normals.push( vertexNormals[ 0 ], vertexNormals[ 1 ], vertexNormals[ 2 ] ); - dstNormalsFace.push( faceNormal ); - dstNormalsVertex.push( vertexNormals ); + } else { - } + var normal = face.normal; - } + this.normals.push( normal, normal, normal ); - var morphNormals = this.morphNormals[ i ]; + } - // set vertices to morph target + var vertexColors = face.vertexColors; - tmpGeo.vertices = this.morphTargets[ i ].vertices; + if ( vertexColors.length === 3 ) { - // compute morph normals + this.colors.push( vertexColors[ 0 ], vertexColors[ 1 ], vertexColors[ 2 ] ); - tmpGeo.computeFaceNormals(); - tmpGeo.computeVertexNormals(); + } else { - // store morph normals + var color = face.color; - var faceNormal, vertexNormals; + this.colors.push( color, color, color ); - for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { + } - face = this.faces[ f ]; + if ( hasFaceVertexUv === true ) { - faceNormal = morphNormals.faceNormals[ f ]; - vertexNormals = morphNormals.vertexNormals[ f ]; + var vertexUvs = faceVertexUvs[ 0 ][ i ]; - faceNormal.copy( face.normal ); + if ( vertexUvs !== undefined ) { - vertexNormals.a.copy( face.vertexNormals[ 0 ] ); - vertexNormals.b.copy( face.vertexNormals[ 1 ] ); - vertexNormals.c.copy( face.vertexNormals[ 2 ] ); + this.uvs.push( vertexUvs[ 0 ], vertexUvs[ 1 ], vertexUvs[ 2 ] ); - } + } else { - } + console.warn( 'THREE.DirectGeometry.fromGeometry(): Undefined vertexUv ', i ); - // restore original normals + this.uvs.push( new Vector2(), new Vector2(), new Vector2() ); - for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { + } - face = this.faces[ f ]; + } - face.normal = face.__originalFaceNormal; - face.vertexNormals = face.__originalVertexNormals; + if ( hasFaceVertexUv2 === true ) { - } + var vertexUvs = faceVertexUvs[ 1 ][ i ]; - }, + if ( vertexUvs !== undefined ) { - computeLineDistances: function () { + this.uvs2.push( vertexUvs[ 0 ], vertexUvs[ 1 ], vertexUvs[ 2 ] ); - var d = 0; - var vertices = this.vertices; + } else { - for ( var i = 0, il = vertices.length; i < il; i ++ ) { + console.warn( 'THREE.DirectGeometry.fromGeometry(): Undefined vertexUv2 ', i ); - if ( i > 0 ) { + this.uvs2.push( new Vector2(), new Vector2(), new Vector2() ); - d += vertices[ i ].distanceTo( vertices[ i - 1 ] ); + } } - this.lineDistances[ i ] = d; - - } - - }, + // morphs - computeBoundingBox: function () { + for ( var j = 0; j < morphTargetsLength; j ++ ) { - if ( this.boundingBox === null ) { + var morphTarget = morphTargets[ j ].vertices; - this.boundingBox = new Box3(); + morphTargetsPosition[ j ].push( morphTarget[ face.a ], morphTarget[ face.b ], morphTarget[ face.c ] ); - } + } - this.boundingBox.setFromPoints( this.vertices ); + for ( var j = 0; j < morphNormalsLength; j ++ ) { - }, + var morphNormal = morphNormals[ j ].vertexNormals[ i ]; - computeBoundingSphere: function () { + morphTargetsNormal[ j ].push( morphNormal.a, morphNormal.b, morphNormal.c ); - if ( this.boundingSphere === null ) { + } - this.boundingSphere = new Sphere(); + // skins - } + if ( hasSkinIndices ) { - this.boundingSphere.setFromPoints( this.vertices ); + this.skinIndices.push( skinIndices[ face.a ], skinIndices[ face.b ], skinIndices[ face.c ] ); - }, + } - merge: function ( geometry, matrix, materialIndexOffset ) { + if ( hasSkinWeights ) { - if ( ( geometry && geometry.isGeometry ) === false ) { + this.skinWeights.push( skinWeights[ face.a ], skinWeights[ face.b ], skinWeights[ face.c ] ); - console.error( 'THREE.Geometry.merge(): geometry not an instance of THREE.Geometry.', geometry ); - return; + } } - var normalMatrix, - vertexOffset = this.vertices.length, - vertices1 = this.vertices, - vertices2 = geometry.vertices, - faces1 = this.faces, - faces2 = geometry.faces, - uvs1 = this.faceVertexUvs[ 0 ], - uvs2 = geometry.faceVertexUvs[ 0 ], - colors1 = this.colors, - colors2 = geometry.colors; + this.computeGroups( geometry ); - if ( materialIndexOffset === undefined ) materialIndexOffset = 0; + this.verticesNeedUpdate = geometry.verticesNeedUpdate; + this.normalsNeedUpdate = geometry.normalsNeedUpdate; + this.colorsNeedUpdate = geometry.colorsNeedUpdate; + this.uvsNeedUpdate = geometry.uvsNeedUpdate; + this.groupsNeedUpdate = geometry.groupsNeedUpdate; - if ( matrix !== undefined ) { + return this; - normalMatrix = new Matrix3().getNormalMatrix( matrix ); + } - } + } ); - // vertices + /** + * @author mrdoob / http://mrdoob.com/ + */ - for ( var i = 0, il = vertices2.length; i < il; i ++ ) { + function arrayMax( array ) { - var vertex = vertices2[ i ]; + if ( array.length === 0 ) return - Infinity; - var vertexCopy = vertex.clone(); + var max = array[ 0 ]; - if ( matrix !== undefined ) vertexCopy.applyMatrix4( matrix ); + for ( var i = 1, l = array.length; i < l; ++ i ) { - vertices1.push( vertexCopy ); + if ( array[ i ] > max ) max = array[ i ]; - } + } - // colors + return max; - for ( var i = 0, il = colors2.length; i < il; i ++ ) { + } - colors1.push( colors2[ i ].clone() ); + /** + * @author alteredq / http://alteredqualia.com/ + * @author mrdoob / http://mrdoob.com/ + */ - } + function BufferGeometry() { - // faces + Object.defineProperty( this, 'id', { value: GeometryIdCount() } ); - for ( i = 0, il = faces2.length; i < il; i ++ ) { + this.uuid = _Math.generateUUID(); - var face = faces2[ i ], faceCopy, normal, color, - faceVertexNormals = face.vertexNormals, - faceVertexColors = face.vertexColors; + this.name = ''; + this.type = 'BufferGeometry'; - faceCopy = new Face3( face.a + vertexOffset, face.b + vertexOffset, face.c + vertexOffset ); - faceCopy.normal.copy( face.normal ); + this.index = null; + this.attributes = {}; - if ( normalMatrix !== undefined ) { + this.morphAttributes = {}; - faceCopy.normal.applyMatrix3( normalMatrix ).normalize(); + this.groups = []; - } + this.boundingBox = null; + this.boundingSphere = null; - for ( var j = 0, jl = faceVertexNormals.length; j < jl; j ++ ) { + this.drawRange = { start: 0, count: Infinity }; - normal = faceVertexNormals[ j ].clone(); + } - if ( normalMatrix !== undefined ) { + BufferGeometry.MaxIndex = 65535; - normal.applyMatrix3( normalMatrix ).normalize(); + Object.assign( BufferGeometry.prototype, EventDispatcher.prototype, { - } + isBufferGeometry: true, - faceCopy.vertexNormals.push( normal ); + getIndex: function () { - } + return this.index; - faceCopy.color.copy( face.color ); + }, - for ( var j = 0, jl = faceVertexColors.length; j < jl; j ++ ) { + setIndex: function ( index ) { - color = faceVertexColors[ j ]; - faceCopy.vertexColors.push( color.clone() ); + if ( Array.isArray( index ) ) { - } + this.index = new ( arrayMax( index ) > 65535 ? Uint32BufferAttribute : Uint16BufferAttribute )( index, 1 ); - faceCopy.materialIndex = face.materialIndex + materialIndexOffset; + } else { - faces1.push( faceCopy ); + this.index = index; } - // uvs - - for ( i = 0, il = uvs2.length; i < il; i ++ ) { - - var uv = uvs2[ i ], uvCopy = []; - - if ( uv === undefined ) { - - continue; + }, - } + addAttribute: function ( name, attribute ) { - for ( var j = 0, jl = uv.length; j < jl; j ++ ) { + if ( ! ( attribute && attribute.isBufferAttribute ) && ! ( attribute && attribute.isInterleavedBufferAttribute ) ) { - uvCopy.push( uv[ j ].clone() ); + console.warn( 'THREE.BufferGeometry: .addAttribute() now expects ( name, attribute ).' ); - } + this.addAttribute( name, new BufferAttribute( arguments[ 1 ], arguments[ 2 ] ) ); - uvs1.push( uvCopy ); + return; } - }, - - mergeMesh: function ( mesh ) { + if ( name === 'index' ) { - if ( ( mesh && mesh.isMesh ) === false ) { + console.warn( 'THREE.BufferGeometry.addAttribute: Use .setIndex() for index attribute.' ); + this.setIndex( attribute ); - console.error( 'THREE.Geometry.mergeMesh(): mesh not an instance of THREE.Mesh.', mesh ); return; } - mesh.matrixAutoUpdate && mesh.updateMatrix(); + this.attributes[ name ] = attribute; - this.merge( mesh.geometry, mesh.matrix ); + return this; }, - /* - * Checks for duplicate vertices with hashmap. - * Duplicated vertices are removed - * and faces' vertices are updated. - */ - - mergeVertices: function () { + getAttribute: function ( name ) { - var verticesMap = {}; // Hashmap for looking up vertices by position coordinates (and making sure they are unique) - var unique = [], changes = []; + return this.attributes[ name ]; - 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; + }, - for ( i = 0, il = this.vertices.length; i < il; i ++ ) { + removeAttribute: function ( name ) { - v = this.vertices[ i ]; - key = Math.round( v.x * precision ) + '_' + Math.round( v.y * precision ) + '_' + Math.round( v.z * precision ); + delete this.attributes[ name ]; - if ( verticesMap[ key ] === undefined ) { + return this; - verticesMap[ key ] = i; - unique.push( this.vertices[ i ] ); - changes[ i ] = unique.length - 1; + }, - } else { + addGroup: function ( start, count, materialIndex ) { - //console.log('Duplicate vertex found. ', i, ' could be using ', verticesMap[key]); - changes[ i ] = changes[ verticesMap[ key ] ]; + this.groups.push( { - } + start: start, + count: count, + materialIndex: materialIndex !== undefined ? materialIndex : 0 - } + } ); + }, - // if faces are completely degenerate after merging vertices, we - // have to remove them from the geometry. - var faceIndicesToRemove = []; + clearGroups: function () { - for ( i = 0, il = this.faces.length; i < il; i ++ ) { + this.groups = []; - face = this.faces[ i ]; + }, - face.a = changes[ face.a ]; - face.b = changes[ face.b ]; - face.c = changes[ face.c ]; + setDrawRange: function ( start, count ) { - indices = [ face.a, face.b, face.c ]; + this.drawRange.start = start; + this.drawRange.count = count; - // if any duplicate vertices are found in a Face3 - // we have to remove the face as nothing can be saved - for ( var n = 0; n < 3; n ++ ) { + }, - if ( indices[ n ] === indices[ ( n + 1 ) % 3 ] ) { + applyMatrix: function ( matrix ) { - faceIndicesToRemove.push( i ); - break; + var position = this.attributes.position; - } + if ( position !== undefined ) { - } + matrix.applyToBufferAttribute( position ); + position.needsUpdate = true; } - for ( i = faceIndicesToRemove.length - 1; i >= 0; i -- ) { - - var idx = faceIndicesToRemove[ i ]; - - this.faces.splice( idx, 1 ); + var normal = this.attributes.normal; - for ( j = 0, jl = this.faceVertexUvs.length; j < jl; j ++ ) { + if ( normal !== undefined ) { - this.faceVertexUvs[ j ].splice( idx, 1 ); + var normalMatrix = new Matrix3().getNormalMatrix( matrix ); - } + normalMatrix.applyToBufferAttribute( normal ); + normal.needsUpdate = true; } - // Use unique set of vertices - - var diff = this.vertices.length - unique.length; - this.vertices = unique; - return diff; - - }, - - sortFacesByMaterialIndex: function () { - - var faces = this.faces; - var length = faces.length; - - // tag faces - - for ( var i = 0; i < length; i ++ ) { + if ( this.boundingBox !== null ) { - faces[ i ]._id = i; + this.computeBoundingBox(); } - // sort faces - - function materialIndexSort( a, b ) { + if ( this.boundingSphere !== null ) { - return a.materialIndex - b.materialIndex; + this.computeBoundingSphere(); } - faces.sort( materialIndexSort ); + return this; - // sort uvs + }, - var uvs1 = this.faceVertexUvs[ 0 ]; - var uvs2 = this.faceVertexUvs[ 1 ]; + rotateX: function () { - var newUvs1, newUvs2; + // rotate geometry around world x-axis - if ( uvs1 && uvs1.length === length ) newUvs1 = []; - if ( uvs2 && uvs2.length === length ) newUvs2 = []; + var m1 = new Matrix4(); - for ( var i = 0; i < length; i ++ ) { + return function rotateX( angle ) { - var id = faces[ i ]._id; + m1.makeRotationX( angle ); - if ( newUvs1 ) newUvs1.push( uvs1[ id ] ); - if ( newUvs2 ) newUvs2.push( uvs2[ id ] ); + this.applyMatrix( m1 ); - } + return this; - if ( newUvs1 ) this.faceVertexUvs[ 0 ] = newUvs1; - if ( newUvs2 ) this.faceVertexUvs[ 1 ] = newUvs2; + }; - }, + }(), - toJSON: function () { + rotateY: function () { - var data = { - metadata: { - version: 4.5, - type: 'Geometry', - generator: 'Geometry.toJSON' - } - }; + // rotate geometry around world y-axis - // standard Geometry serialization + var m1 = new Matrix4(); - data.uuid = this.uuid; - data.type = this.type; - if ( this.name !== '' ) data.name = this.name; + return function rotateY( angle ) { - if ( this.parameters !== undefined ) { + m1.makeRotationY( angle ); - var parameters = this.parameters; + this.applyMatrix( m1 ); - for ( var key in parameters ) { + return this; - if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ]; + }; - } + }(), - return data; + rotateZ: function () { - } + // rotate geometry around world z-axis - var vertices = []; + var m1 = new Matrix4(); - for ( var i = 0; i < this.vertices.length; i ++ ) { + return function rotateZ( angle ) { - var vertex = this.vertices[ i ]; - vertices.push( vertex.x, vertex.y, vertex.z ); + m1.makeRotationZ( angle ); - } + this.applyMatrix( m1 ); - var faces = []; - var normals = []; - var normalsHash = {}; - var colors = []; - var colorsHash = {}; - var uvs = []; - var uvsHash = {}; + return this; - for ( var i = 0; i < this.faces.length; i ++ ) { + }; - var face = this.faces[ i ]; + }(), - 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; + translate: function () { - var faceType = 0; + // translate geometry - 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 ); + var m1 = new Matrix4(); - faces.push( faceType ); - faces.push( face.a, face.b, face.c ); - faces.push( face.materialIndex ); + return function translate( x, y, z ) { - if ( hasFaceVertexUv ) { + m1.makeTranslation( x, y, z ); - var faceVertexUvs = this.faceVertexUvs[ 0 ][ i ]; + this.applyMatrix( m1 ); - faces.push( - getUvIndex( faceVertexUvs[ 0 ] ), - getUvIndex( faceVertexUvs[ 1 ] ), - getUvIndex( faceVertexUvs[ 2 ] ) - ); + return this; - } + }; - if ( hasFaceNormal ) { + }(), - faces.push( getNormalIndex( face.normal ) ); + scale: function () { - } + // scale geometry - if ( hasFaceVertexNormal ) { + var m1 = new Matrix4(); - var vertexNormals = face.vertexNormals; + return function scale( x, y, z ) { - faces.push( - getNormalIndex( vertexNormals[ 0 ] ), - getNormalIndex( vertexNormals[ 1 ] ), - getNormalIndex( vertexNormals[ 2 ] ) - ); + m1.makeScale( x, y, z ); - } + this.applyMatrix( m1 ); - if ( hasFaceColor ) { + return this; - faces.push( getColorIndex( face.color ) ); + }; - } + }(), - if ( hasFaceVertexColor ) { + lookAt: function () { - var vertexColors = face.vertexColors; + var obj = new Object3D(); - faces.push( - getColorIndex( vertexColors[ 0 ] ), - getColorIndex( vertexColors[ 1 ] ), - getColorIndex( vertexColors[ 2 ] ) - ); + return function lookAt( vector ) { - } + obj.lookAt( vector ); - } + obj.updateMatrix(); - function setBit( value, position, enabled ) { + this.applyMatrix( obj.matrix ); - return enabled ? value | ( 1 << position ) : value & ( ~ ( 1 << position ) ); + }; - } + }(), - function getNormalIndex( normal ) { + center: function () { - var hash = normal.x.toString() + normal.y.toString() + normal.z.toString(); + this.computeBoundingBox(); - if ( normalsHash[ hash ] !== undefined ) { + var offset = this.boundingBox.getCenter().negate(); - return normalsHash[ hash ]; + this.translate( offset.x, offset.y, offset.z ); - } + return offset; - normalsHash[ hash ] = normals.length / 3; - normals.push( normal.x, normal.y, normal.z ); + }, - return normalsHash[ hash ]; + setFromObject: function ( object ) { - } + // console.log( 'THREE.BufferGeometry.setFromObject(). Converting', object, this ); - function getColorIndex( color ) { + var geometry = object.geometry; - var hash = color.r.toString() + color.g.toString() + color.b.toString(); + if ( object.isPoints || object.isLine ) { - if ( colorsHash[ hash ] !== undefined ) { + var positions = new Float32BufferAttribute( geometry.vertices.length * 3, 3 ); + var colors = new Float32BufferAttribute( geometry.colors.length * 3, 3 ); - return colorsHash[ hash ]; + this.addAttribute( 'position', positions.copyVector3sArray( geometry.vertices ) ); + this.addAttribute( 'color', colors.copyColorsArray( geometry.colors ) ); - } + if ( geometry.lineDistances && geometry.lineDistances.length === geometry.vertices.length ) { - colorsHash[ hash ] = colors.length; - colors.push( color.getHex() ); + var lineDistances = new Float32BufferAttribute( geometry.lineDistances.length, 1 ); - return colorsHash[ hash ]; + this.addAttribute( 'lineDistance', lineDistances.copyArray( geometry.lineDistances ) ); - } + } - function getUvIndex( uv ) { + if ( geometry.boundingSphere !== null ) { - var hash = uv.x.toString() + uv.y.toString(); + this.boundingSphere = geometry.boundingSphere.clone(); - if ( uvsHash[ hash ] !== undefined ) { + } - return uvsHash[ hash ]; + if ( geometry.boundingBox !== null ) { + + this.boundingBox = geometry.boundingBox.clone(); } - uvsHash[ hash ] = uvs.length / 2; - uvs.push( uv.x, uv.y ); + } else if ( object.isMesh ) { - return uvsHash[ hash ]; + if ( geometry && geometry.isGeometry ) { - } + this.fromGeometry( geometry ); - data.data = {}; + } - data.data.vertices = vertices; - data.data.normals = normals; - if ( colors.length > 0 ) data.data.colors = colors; - if ( uvs.length > 0 ) data.data.uvs = [ uvs ]; // temporal backward compatibility - data.data.faces = faces; + } - return data; + return this; }, - clone: function () { + updateFromObject: function ( object ) { - /* - // Handle primitives + var geometry = object.geometry; - var parameters = this.parameters; + if ( object.isMesh ) { - if ( parameters !== undefined ) { + var direct = geometry.__directGeometry; - var values = []; + if ( geometry.elementsNeedUpdate === true ) { - for ( var key in parameters ) { + direct = undefined; + geometry.elementsNeedUpdate = false; - values.push( parameters[ key ] ); + } - } + if ( direct === undefined ) { - var geometry = Object.create( this.constructor.prototype ); - this.constructor.apply( geometry, values ); - return geometry; + return this.fromGeometry( geometry ); - } + } - return new this.constructor().copy( this ); - */ + direct.verticesNeedUpdate = geometry.verticesNeedUpdate; + direct.normalsNeedUpdate = geometry.normalsNeedUpdate; + direct.colorsNeedUpdate = geometry.colorsNeedUpdate; + direct.uvsNeedUpdate = geometry.uvsNeedUpdate; + direct.groupsNeedUpdate = geometry.groupsNeedUpdate; - return new Geometry().copy( this ); + geometry.verticesNeedUpdate = false; + geometry.normalsNeedUpdate = false; + geometry.colorsNeedUpdate = false; + geometry.uvsNeedUpdate = false; + geometry.groupsNeedUpdate = false; - }, + geometry = direct; - copy: function ( source ) { + } - var i, il, j, jl, k, kl; + var attribute; - // reset + if ( geometry.verticesNeedUpdate === true ) { - this.vertices = []; - this.colors = []; - this.faces = []; - this.faceVertexUvs = [[]]; - this.morphTargets = []; - this.morphNormals = []; - this.skinWeights = []; - this.skinIndices = []; - this.lineDistances = []; - this.boundingBox = null; - this.boundingSphere = null; + attribute = this.attributes.position; - // name + if ( attribute !== undefined ) { - this.name = source.name; + attribute.copyVector3sArray( geometry.vertices ); + attribute.needsUpdate = true; - // vertices + } - var vertices = source.vertices; + geometry.verticesNeedUpdate = false; - for ( i = 0, il = vertices.length; i < il; i ++ ) { + } - this.vertices.push( vertices[ i ].clone() ); + if ( geometry.normalsNeedUpdate === true ) { - } + attribute = this.attributes.normal; - // colors + if ( attribute !== undefined ) { - var colors = source.colors; + attribute.copyVector3sArray( geometry.normals ); + attribute.needsUpdate = true; - for ( i = 0, il = colors.length; i < il; i ++ ) { + } - this.colors.push( colors[ i ].clone() ); + geometry.normalsNeedUpdate = false; } - // faces + if ( geometry.colorsNeedUpdate === true ) { - var faces = source.faces; + attribute = this.attributes.color; - for ( i = 0, il = faces.length; i < il; i ++ ) { + if ( attribute !== undefined ) { - this.faces.push( faces[ i ].clone() ); + attribute.copyColorsArray( geometry.colors ); + attribute.needsUpdate = true; - } + } - // face vertex uvs + geometry.colorsNeedUpdate = false; - for ( i = 0, il = source.faceVertexUvs.length; i < il; i ++ ) { + } - var faceVertexUvs = source.faceVertexUvs[ i ]; + if ( geometry.uvsNeedUpdate ) { - if ( this.faceVertexUvs[ i ] === undefined ) { + attribute = this.attributes.uv; - this.faceVertexUvs[ i ] = []; + if ( attribute !== undefined ) { - } + attribute.copyVector2sArray( geometry.uvs ); + attribute.needsUpdate = true; - for ( j = 0, jl = faceVertexUvs.length; j < jl; j ++ ) { + } - var uvs = faceVertexUvs[ j ], uvsCopy = []; + geometry.uvsNeedUpdate = false; - for ( k = 0, kl = uvs.length; k < kl; k ++ ) { + } - var uv = uvs[ k ]; + if ( geometry.lineDistancesNeedUpdate ) { - uvsCopy.push( uv.clone() ); + attribute = this.attributes.lineDistance; - } + if ( attribute !== undefined ) { - this.faceVertexUvs[ i ].push( uvsCopy ); + attribute.copyArray( geometry.lineDistances ); + attribute.needsUpdate = true; } + geometry.lineDistancesNeedUpdate = false; + } - // morph targets + if ( geometry.groupsNeedUpdate ) { - var morphTargets = source.morphTargets; + geometry.computeGroups( object.geometry ); + this.groups = geometry.groups; - for ( i = 0, il = morphTargets.length; i < il; i ++ ) { + geometry.groupsNeedUpdate = false; - var morphTarget = {}; - morphTarget.name = morphTargets[ i ].name; + } - // vertices + return this; - if ( morphTargets[ i ].vertices !== undefined ) { + }, - morphTarget.vertices = []; + fromGeometry: function ( geometry ) { - for ( j = 0, jl = morphTargets[ i ].vertices.length; j < jl; j ++ ) { + geometry.__directGeometry = new DirectGeometry().fromGeometry( geometry ); - morphTarget.vertices.push( morphTargets[ i ].vertices[ j ].clone() ); + return this.fromDirectGeometry( geometry.__directGeometry ); - } + }, - } + fromDirectGeometry: function ( geometry ) { - // normals + var positions = new Float32Array( geometry.vertices.length * 3 ); + this.addAttribute( 'position', new BufferAttribute( positions, 3 ).copyVector3sArray( geometry.vertices ) ); - if ( morphTargets[ i ].normals !== undefined ) { + if ( geometry.normals.length > 0 ) { - morphTarget.normals = []; + var normals = new Float32Array( geometry.normals.length * 3 ); + this.addAttribute( 'normal', new BufferAttribute( normals, 3 ).copyVector3sArray( geometry.normals ) ); - for ( j = 0, jl = morphTargets[ i ].normals.length; j < jl; j ++ ) { + } - morphTarget.normals.push( morphTargets[ i ].normals[ j ].clone() ); + if ( geometry.colors.length > 0 ) { - } + var colors = new Float32Array( geometry.colors.length * 3 ); + this.addAttribute( 'color', new BufferAttribute( colors, 3 ).copyColorsArray( geometry.colors ) ); - } + } - this.morphTargets.push( morphTarget ); + if ( geometry.uvs.length > 0 ) { + + var uvs = new Float32Array( geometry.uvs.length * 2 ); + this.addAttribute( 'uv', new BufferAttribute( uvs, 2 ).copyVector2sArray( geometry.uvs ) ); } - // morph normals + if ( geometry.uvs2.length > 0 ) { - var morphNormals = source.morphNormals; + var uvs2 = new Float32Array( geometry.uvs2.length * 2 ); + this.addAttribute( 'uv2', new BufferAttribute( uvs2, 2 ).copyVector2sArray( geometry.uvs2 ) ); - for ( i = 0, il = morphNormals.length; i < il; i ++ ) { + } - var morphNormal = {}; + if ( geometry.indices.length > 0 ) { - // vertex normals + var TypeArray = arrayMax( geometry.indices ) > 65535 ? Uint32Array : Uint16Array; + var indices = new TypeArray( geometry.indices.length * 3 ); + this.setIndex( new BufferAttribute( indices, 1 ).copyIndicesArray( geometry.indices ) ); - if ( morphNormals[ i ].vertexNormals !== undefined ) { + } - morphNormal.vertexNormals = []; + // groups - for ( j = 0, jl = morphNormals[ i ].vertexNormals.length; j < jl; j ++ ) { + this.groups = geometry.groups; - var srcVertexNormal = morphNormals[ i ].vertexNormals[ j ]; - var destVertexNormal = {}; + // morphs - destVertexNormal.a = srcVertexNormal.a.clone(); - destVertexNormal.b = srcVertexNormal.b.clone(); - destVertexNormal.c = srcVertexNormal.c.clone(); + for ( var name in geometry.morphTargets ) { - morphNormal.vertexNormals.push( destVertexNormal ); + var array = []; + var morphTargets = geometry.morphTargets[ name ]; - } + for ( var i = 0, l = morphTargets.length; i < l; i ++ ) { + + var morphTarget = morphTargets[ i ]; + + var attribute = new Float32BufferAttribute( morphTarget.length * 3, 3 ); + + array.push( attribute.copyVector3sArray( morphTarget ) ); } - // face normals + this.morphAttributes[ name ] = array; - if ( morphNormals[ i ].faceNormals !== undefined ) { + } - morphNormal.faceNormals = []; + // skinning - for ( j = 0, jl = morphNormals[ i ].faceNormals.length; j < jl; j ++ ) { + if ( geometry.skinIndices.length > 0 ) { - morphNormal.faceNormals.push( morphNormals[ i ].faceNormals[ j ].clone() ); + var skinIndices = new Float32BufferAttribute( geometry.skinIndices.length * 4, 4 ); + this.addAttribute( 'skinIndex', skinIndices.copyVector4sArray( geometry.skinIndices ) ); - } + } - } + if ( geometry.skinWeights.length > 0 ) { - this.morphNormals.push( morphNormal ); + var skinWeights = new Float32BufferAttribute( geometry.skinWeights.length * 4, 4 ); + this.addAttribute( 'skinWeight', skinWeights.copyVector4sArray( geometry.skinWeights ) ); } - // skin weights + // - var skinWeights = source.skinWeights; + if ( geometry.boundingSphere !== null ) { - for ( i = 0, il = skinWeights.length; i < il; i ++ ) { + this.boundingSphere = geometry.boundingSphere.clone(); - this.skinWeights.push( skinWeights[ i ].clone() ); + } + + if ( geometry.boundingBox !== null ) { + + this.boundingBox = geometry.boundingBox.clone(); } - // skin indices + return this; - var skinIndices = source.skinIndices; + }, - for ( i = 0, il = skinIndices.length; i < il; i ++ ) { + computeBoundingBox: function () { - this.skinIndices.push( skinIndices[ i ].clone() ); + if ( this.boundingBox === null ) { + + this.boundingBox = new Box3(); } - // line distances + var position = this.attributes.position; - var lineDistances = source.lineDistances; + if ( position !== undefined ) { - for ( i = 0, il = lineDistances.length; i < il; i ++ ) { + this.boundingBox.setFromBufferAttribute( position ); - this.lineDistances.push( lineDistances[ i ] ); + } else { + + this.boundingBox.makeEmpty(); } - // bounding box + if ( isNaN( this.boundingBox.min.x ) || isNaN( this.boundingBox.min.y ) || isNaN( this.boundingBox.min.z ) ) { - var boundingBox = source.boundingBox; + console.error( 'THREE.BufferGeometry.computeBoundingBox: Computed min/max have NaN values. The "position" attribute is likely to have NaN values.', this ); - if ( boundingBox !== null ) { + } - this.boundingBox = boundingBox.clone(); + }, - } + computeBoundingSphere: function () { - // bounding sphere + var box = new Box3(); + var vector = new Vector3(); - var boundingSphere = source.boundingSphere; + return function computeBoundingSphere() { - if ( boundingSphere !== null ) { + if ( this.boundingSphere === null ) { - this.boundingSphere = boundingSphere.clone(); + this.boundingSphere = new Sphere(); - } + } - // update flags + var position = this.attributes.position; - 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; + if ( position ) { - return this; + var center = this.boundingSphere.center; - }, + box.setFromBufferAttribute( position ); + box.getCenter( center ); - dispose: function () { + // hoping to find a boundingSphere with a radius smaller than the + // boundingSphere of the boundingBox: sqrt(3) smaller in the best case - this.dispatchEvent( { type: 'dispose' } ); + var maxRadiusSq = 0; - } + for ( var i = 0, il = position.count; i < il; i ++ ) { - } ); + vector.x = position.getX( i ); + vector.y = position.getY( i ); + vector.z = position.getZ( i ); + maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( vector ) ); - /** - * @author alteredq / http://alteredqualia.com/ - * @author mrdoob / http://mrdoob.com/ - */ + } - function BufferGeometry() { + this.boundingSphere.radius = Math.sqrt( maxRadiusSq ); - Object.defineProperty( this, 'id', { value: GeometryIdCount() } ); + if ( isNaN( this.boundingSphere.radius ) ) { - this.uuid = _Math.generateUUID(); + console.error( 'THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The "position" attribute is likely to have NaN values.', this ); - this.name = ''; - this.type = 'BufferGeometry'; + } - this.index = null; - this.attributes = {}; + } - this.morphAttributes = {}; + }; - this.groups = []; + }(), - this.boundingBox = null; - this.boundingSphere = null; + computeFaceNormals: function () { - this.drawRange = { start: 0, count: Infinity }; + // backwards compatibility - } + }, - BufferGeometry.MaxIndex = 65535; + computeVertexNormals: function () { - Object.assign( BufferGeometry.prototype, EventDispatcher.prototype, { + var index = this.index; + var attributes = this.attributes; + var groups = this.groups; - isBufferGeometry: true, + if ( attributes.position ) { - getIndex: function () { + var positions = attributes.position.array; - return this.index; + if ( attributes.normal === undefined ) { - }, + this.addAttribute( 'normal', new BufferAttribute( new Float32Array( positions.length ), 3 ) ); - setIndex: function ( index ) { + } else { - if ( Array.isArray( index ) ) { + // reset existing normals to zero - this.index = new ( arrayMax( index ) > 65535 ? Uint32BufferAttribute : Uint16BufferAttribute )( index, 1 ); + var array = attributes.normal.array; - } else { + for ( var i = 0, il = array.length; i < il; i ++ ) { - this.index = index; + array[ i ] = 0; - } + } - }, + } - addAttribute: function ( name, attribute ) { + var normals = attributes.normal.array; - if ( ( attribute && attribute.isBufferAttribute ) === false && ( attribute && attribute.isInterleavedBufferAttribute ) === false ) { + var vA, vB, vC; + var pA = new Vector3(), pB = new Vector3(), pC = new Vector3(); + var cb = new Vector3(), ab = new Vector3(); - console.warn( 'THREE.BufferGeometry: .addAttribute() now expects ( name, attribute ).' ); + // indexed elements - this.addAttribute( name, new BufferAttribute( arguments[ 1 ], arguments[ 2 ] ) ); + if ( index ) { - return; + var indices = index.array; - } + if ( groups.length === 0 ) { - if ( name === 'index' ) { + this.addGroup( 0, indices.length ); - console.warn( 'THREE.BufferGeometry.addAttribute: Use .setIndex() for index attribute.' ); - this.setIndex( attribute ); + } - return; + for ( var j = 0, jl = groups.length; j < jl; ++ j ) { - } + var group = groups[ j ]; + + var start = group.start; + var count = group.count; + + for ( var i = start, il = start + count; i < il; i += 3 ) { + + vA = indices[ i + 0 ] * 3; + vB = indices[ i + 1 ] * 3; + vC = indices[ i + 2 ] * 3; - this.attributes[ name ] = attribute; + pA.fromArray( positions, vA ); + pB.fromArray( positions, vB ); + pC.fromArray( positions, vC ); - return this; + cb.subVectors( pC, pB ); + ab.subVectors( pA, pB ); + cb.cross( ab ); - }, + normals[ vA ] += cb.x; + normals[ vA + 1 ] += cb.y; + normals[ vA + 2 ] += cb.z; - getAttribute: function ( name ) { + normals[ vB ] += cb.x; + normals[ vB + 1 ] += cb.y; + normals[ vB + 2 ] += cb.z; - return this.attributes[ name ]; + normals[ vC ] += cb.x; + normals[ vC + 1 ] += cb.y; + normals[ vC + 2 ] += cb.z; - }, + } - removeAttribute: function ( name ) { + } - delete this.attributes[ name ]; + } else { - return this; + // non-indexed elements (unconnected triangle soup) - }, + for ( var i = 0, il = positions.length; i < il; i += 9 ) { - addGroup: function ( start, count, materialIndex ) { + pA.fromArray( positions, i ); + pB.fromArray( positions, i + 3 ); + pC.fromArray( positions, i + 6 ); - this.groups.push( { + cb.subVectors( pC, pB ); + ab.subVectors( pA, pB ); + cb.cross( ab ); - start: start, - count: count, - materialIndex: materialIndex !== undefined ? materialIndex : 0 + normals[ i ] = cb.x; + normals[ i + 1 ] = cb.y; + normals[ i + 2 ] = cb.z; - } ); + normals[ i + 3 ] = cb.x; + normals[ i + 4 ] = cb.y; + normals[ i + 5 ] = cb.z; - }, + normals[ i + 6 ] = cb.x; + normals[ i + 7 ] = cb.y; + normals[ i + 8 ] = cb.z; - clearGroups: function () { + } - this.groups = []; + } - }, + this.normalizeNormals(); - setDrawRange: function ( start, count ) { + attributes.normal.needsUpdate = true; - this.drawRange.start = start; - this.drawRange.count = count; + } }, - applyMatrix: function ( matrix ) { - - var position = this.attributes.position; + merge: function ( geometry, offset ) { - if ( position !== undefined ) { + if ( ! ( geometry && geometry.isBufferGeometry ) ) { - matrix.applyToBufferAttribute( position ); - position.needsUpdate = true; + console.error( 'THREE.BufferGeometry.merge(): geometry not an instance of THREE.BufferGeometry.', geometry ); + return; } - var normal = this.attributes.normal; + if ( offset === undefined ) offset = 0; - if ( normal !== undefined ) { + var attributes = this.attributes; - var normalMatrix = new Matrix3().getNormalMatrix( matrix ); + for ( var key in attributes ) { - normalMatrix.applyToBufferAttribute( normal ); - normal.needsUpdate = true; + if ( geometry.attributes[ key ] === undefined ) continue; - } + var attribute1 = attributes[ key ]; + var attributeArray1 = attribute1.array; - if ( this.boundingBox !== null ) { + var attribute2 = geometry.attributes[ key ]; + var attributeArray2 = attribute2.array; - this.computeBoundingBox(); + var attributeSize = attribute2.itemSize; - } + for ( var i = 0, j = attributeSize * offset; i < attributeArray2.length; i ++, j ++ ) { - if ( this.boundingSphere !== null ) { + attributeArray1[ j ] = attributeArray2[ i ]; - this.computeBoundingSphere(); + } } @@ -13991,2163 +14418,2129 @@ }, - rotateX: function () { - - // rotate geometry around world x-axis - - var m1 = new Matrix4(); + normalizeNormals: function () { - return function rotateX( angle ) { + var vector = new Vector3(); - m1.makeRotationX( angle ); + return function normalizeNormals() { - this.applyMatrix( m1 ); + var normals = this.attributes.normal; - return this; + for ( var i = 0, il = normals.count; i < il; i ++ ) { - }; + vector.x = normals.getX( i ); + vector.y = normals.getY( i ); + vector.z = normals.getZ( i ); - }(), + vector.normalize(); - rotateY: function () { + normals.setXYZ( i, vector.x, vector.y, vector.z ); - // rotate geometry around world y-axis + } - var m1 = new Matrix4(); + }; - return function rotateY( angle ) { + }(), - m1.makeRotationY( angle ); + toNonIndexed: function () { - this.applyMatrix( m1 ); + if ( this.index === null ) { + console.warn( 'THREE.BufferGeometry.toNonIndexed(): Geometry is already non-indexed.' ); return this; - }; + } - }(), + var geometry2 = new BufferGeometry(); - rotateZ: function () { + var indices = this.index.array; + var attributes = this.attributes; - // rotate geometry around world z-axis + for ( var name in attributes ) { - var m1 = new Matrix4(); + var attribute = attributes[ name ]; - return function rotateZ( angle ) { + var array = attribute.array; + var itemSize = attribute.itemSize; - m1.makeRotationZ( angle ); + var array2 = new array.constructor( indices.length * itemSize ); - this.applyMatrix( m1 ); + var index = 0, index2 = 0; - return this; + for ( var i = 0, l = indices.length; i < l; i ++ ) { - }; + index = indices[ i ] * itemSize; - }(), + for ( var j = 0; j < itemSize; j ++ ) { - translate: function () { + array2[ index2 ++ ] = array[ index ++ ]; - // translate geometry + } - var m1 = new Matrix4(); + } - return function translate( x, y, z ) { + geometry2.addAttribute( name, new BufferAttribute( array2, itemSize ) ); - m1.makeTranslation( x, y, z ); + } - this.applyMatrix( m1 ); + return geometry2; - return this; + }, - }; + toJSON: function () { - }(), + var data = { + metadata: { + version: 4.5, + type: 'BufferGeometry', + generator: 'BufferGeometry.toJSON' + } + }; - scale: function () { + // standard BufferGeometry serialization - // scale geometry + data.uuid = this.uuid; + data.type = this.type; + if ( this.name !== '' ) data.name = this.name; - var m1 = new Matrix4(); + if ( this.parameters !== undefined ) { - return function scale( x, y, z ) { + var parameters = this.parameters; - m1.makeScale( x, y, z ); + for ( var key in parameters ) { - this.applyMatrix( m1 ); + if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ]; - return this; + } - }; + return data; - }(), + } - lookAt: function () { + data.data = { attributes: {} }; - var obj = new Object3D(); + var index = this.index; - return function lookAt( vector ) { + if ( index !== null ) { - obj.lookAt( vector ); + var array = Array.prototype.slice.call( index.array ); - obj.updateMatrix(); + data.data.index = { + type: index.array.constructor.name, + array: array + }; - this.applyMatrix( obj.matrix ); + } - }; + var attributes = this.attributes; - }(), + for ( var key in attributes ) { - center: function () { + var attribute = attributes[ key ]; - this.computeBoundingBox(); + var array = Array.prototype.slice.call( attribute.array ); - var offset = this.boundingBox.getCenter().negate(); + data.data.attributes[ key ] = { + itemSize: attribute.itemSize, + type: attribute.array.constructor.name, + array: array, + normalized: attribute.normalized + }; - this.translate( offset.x, offset.y, offset.z ); + } - return offset; + var groups = this.groups; - }, + if ( groups.length > 0 ) { - setFromObject: function ( object ) { + data.data.groups = JSON.parse( JSON.stringify( groups ) ); - // console.log( 'THREE.BufferGeometry.setFromObject(). Converting', object, this ); + } - var geometry = object.geometry; + var boundingSphere = this.boundingSphere; - if ( object.isPoints || object.isLine ) { + if ( boundingSphere !== null ) { - var positions = new Float32BufferAttribute( geometry.vertices.length * 3, 3 ); - var colors = new Float32BufferAttribute( geometry.colors.length * 3, 3 ); + data.data.boundingSphere = { + center: boundingSphere.center.toArray(), + radius: boundingSphere.radius + }; - this.addAttribute( 'position', positions.copyVector3sArray( geometry.vertices ) ); - this.addAttribute( 'color', colors.copyColorsArray( geometry.colors ) ); + } - if ( geometry.lineDistances && geometry.lineDistances.length === geometry.vertices.length ) { + return data; - var lineDistances = new Float32BufferAttribute( geometry.lineDistances.length, 1 ); + }, - this.addAttribute( 'lineDistance', lineDistances.copyArray( geometry.lineDistances ) ); + clone: function () { - } + /* + // Handle primitives - if ( geometry.boundingSphere !== null ) { + var parameters = this.parameters; - this.boundingSphere = geometry.boundingSphere.clone(); + if ( parameters !== undefined ) { - } + var values = []; - if ( geometry.boundingBox !== null ) { + for ( var key in parameters ) { - this.boundingBox = geometry.boundingBox.clone(); + values.push( parameters[ key ] ); - } + } - } else if ( object.isMesh ) { + var geometry = Object.create( this.constructor.prototype ); + this.constructor.apply( geometry, values ); + return geometry; - if ( geometry && geometry.isGeometry ) { + } - this.fromGeometry( geometry ); + return new this.constructor().copy( this ); + */ - } + return new BufferGeometry().copy( this ); - } + }, - return this; + copy: function ( source ) { - }, + var name, i, l; - updateFromObject: function ( object ) { + // reset - var geometry = object.geometry; + this.index = null; + this.attributes = {}; + this.morphAttributes = {}; + this.groups = []; + this.boundingBox = null; + this.boundingSphere = null; - if ( object.isMesh ) { + // name - var direct = geometry.__directGeometry; + this.name = source.name; - if ( geometry.elementsNeedUpdate === true ) { + // index - direct = undefined; - geometry.elementsNeedUpdate = false; + var index = source.index; - } + if ( index !== null ) { - if ( direct === undefined ) { + this.setIndex( index.clone() ); - return this.fromGeometry( geometry ); + } - } + // attributes - direct.verticesNeedUpdate = geometry.verticesNeedUpdate; - direct.normalsNeedUpdate = geometry.normalsNeedUpdate; - direct.colorsNeedUpdate = geometry.colorsNeedUpdate; - direct.uvsNeedUpdate = geometry.uvsNeedUpdate; - direct.groupsNeedUpdate = geometry.groupsNeedUpdate; + var attributes = source.attributes; - geometry.verticesNeedUpdate = false; - geometry.normalsNeedUpdate = false; - geometry.colorsNeedUpdate = false; - geometry.uvsNeedUpdate = false; - geometry.groupsNeedUpdate = false; + for ( name in attributes ) { - geometry = direct; + var attribute = attributes[ name ]; + this.addAttribute( name, attribute.clone() ); } - var attribute; + // morph attributes - if ( geometry.verticesNeedUpdate === true ) { + var morphAttributes = source.morphAttributes; - attribute = this.attributes.position; + for ( name in morphAttributes ) { - if ( attribute !== undefined ) { + var array = []; + var morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes - attribute.copyVector3sArray( geometry.vertices ); - attribute.needsUpdate = true; + for ( i = 0, l = morphAttribute.length; i < l; i ++ ) { + + array.push( morphAttribute[ i ].clone() ); } - geometry.verticesNeedUpdate = false; + this.morphAttributes[ name ] = array; } - if ( geometry.normalsNeedUpdate === true ) { - - attribute = this.attributes.normal; - - if ( attribute !== undefined ) { + // groups - attribute.copyVector3sArray( geometry.normals ); - attribute.needsUpdate = true; + var groups = source.groups; - } + for ( i = 0, l = groups.length; i < l; i ++ ) { - geometry.normalsNeedUpdate = false; + var group = groups[ i ]; + this.addGroup( group.start, group.count, group.materialIndex ); } - if ( geometry.colorsNeedUpdate === true ) { - - attribute = this.attributes.color; - - if ( attribute !== undefined ) { + // bounding box - attribute.copyColorsArray( geometry.colors ); - attribute.needsUpdate = true; + var boundingBox = source.boundingBox; - } + if ( boundingBox !== null ) { - geometry.colorsNeedUpdate = false; + this.boundingBox = boundingBox.clone(); } - if ( geometry.uvsNeedUpdate ) { - - attribute = this.attributes.uv; - - if ( attribute !== undefined ) { + // bounding sphere - attribute.copyVector2sArray( geometry.uvs ); - attribute.needsUpdate = true; + var boundingSphere = source.boundingSphere; - } + if ( boundingSphere !== null ) { - geometry.uvsNeedUpdate = false; + this.boundingSphere = boundingSphere.clone(); } - if ( geometry.lineDistancesNeedUpdate ) { - - attribute = this.attributes.lineDistance; + // draw range - if ( attribute !== undefined ) { + this.drawRange.start = source.drawRange.start; + this.drawRange.count = source.drawRange.count; - attribute.copyArray( geometry.lineDistances ); - attribute.needsUpdate = true; + return this; - } + }, - geometry.lineDistancesNeedUpdate = false; + dispose: function () { - } + this.dispatchEvent( { type: 'dispose' } ); - if ( geometry.groupsNeedUpdate ) { + } - geometry.computeGroups( object.geometry ); - this.groups = geometry.groups; + } ); - geometry.groupsNeedUpdate = false; + /** + * @author mrdoob / http://mrdoob.com/ + * @author Mugen87 / https://github.com/Mugen87 + */ - } + // BoxGeometry - return this; + function BoxGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) { - }, + Geometry.call( this ); - fromGeometry: function ( geometry ) { + this.type = 'BoxGeometry'; - geometry.__directGeometry = new DirectGeometry().fromGeometry( geometry ); + this.parameters = { + width: width, + height: height, + depth: depth, + widthSegments: widthSegments, + heightSegments: heightSegments, + depthSegments: depthSegments + }; - return this.fromDirectGeometry( geometry.__directGeometry ); + this.fromBufferGeometry( new BoxBufferGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) ); + this.mergeVertices(); - }, + } - fromDirectGeometry: function ( geometry ) { + BoxGeometry.prototype = Object.create( Geometry.prototype ); + BoxGeometry.prototype.constructor = BoxGeometry; - var positions = new Float32Array( geometry.vertices.length * 3 ); - this.addAttribute( 'position', new BufferAttribute( positions, 3 ).copyVector3sArray( geometry.vertices ) ); + // BoxBufferGeometry - if ( geometry.normals.length > 0 ) { + function BoxBufferGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) { - var normals = new Float32Array( geometry.normals.length * 3 ); - this.addAttribute( 'normal', new BufferAttribute( normals, 3 ).copyVector3sArray( geometry.normals ) ); + BufferGeometry.call( this ); - } + this.type = 'BoxBufferGeometry'; - if ( geometry.colors.length > 0 ) { + this.parameters = { + width: width, + height: height, + depth: depth, + widthSegments: widthSegments, + heightSegments: heightSegments, + depthSegments: depthSegments + }; - var colors = new Float32Array( geometry.colors.length * 3 ); - this.addAttribute( 'color', new BufferAttribute( colors, 3 ).copyColorsArray( geometry.colors ) ); + var scope = this; - } + // segments - if ( geometry.uvs.length > 0 ) { + widthSegments = Math.floor( widthSegments ) || 1; + heightSegments = Math.floor( heightSegments ) || 1; + depthSegments = Math.floor( depthSegments ) || 1; - var uvs = new Float32Array( geometry.uvs.length * 2 ); - this.addAttribute( 'uv', new BufferAttribute( uvs, 2 ).copyVector2sArray( geometry.uvs ) ); + // buffers - } + var indices = []; + var vertices = []; + var normals = []; + var uvs = []; - if ( geometry.uvs2.length > 0 ) { + // helper variables - var uvs2 = new Float32Array( geometry.uvs2.length * 2 ); - this.addAttribute( 'uv2', new BufferAttribute( uvs2, 2 ).copyVector2sArray( geometry.uvs2 ) ); + var numberOfVertices = 0; + var groupStart = 0; - } + // build each side of the box geometry - if ( geometry.indices.length > 0 ) { + 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 - var TypeArray = arrayMax( geometry.indices ) > 65535 ? Uint32Array : Uint16Array; - var indices = new TypeArray( geometry.indices.length * 3 ); - this.setIndex( new BufferAttribute( indices, 1 ).copyIndicesArray( geometry.indices ) ); + // 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 ) ); - // groups + function buildPlane( u, v, w, udir, vdir, width, height, depth, gridX, gridY, materialIndex ) { - this.groups = geometry.groups; + var segmentWidth = width / gridX; + var segmentHeight = height / gridY; - // morphs + var widthHalf = width / 2; + var heightHalf = height / 2; + var depthHalf = depth / 2; - for ( var name in geometry.morphTargets ) { + var gridX1 = gridX + 1; + var gridY1 = gridY + 1; - var array = []; - var morphTargets = geometry.morphTargets[ name ]; + var vertexCounter = 0; + var groupCount = 0; - for ( var i = 0, l = morphTargets.length; i < l; i ++ ) { + var ix, iy; - var morphTarget = morphTargets[ i ]; + var vector = new Vector3(); - var attribute = new Float32BufferAttribute( morphTarget.length * 3, 3 ); + // generate vertices, normals and uvs - array.push( attribute.copyVector3sArray( morphTarget ) ); + for ( iy = 0; iy < gridY1; iy ++ ) { - } + var y = iy * segmentHeight - heightHalf; - this.morphAttributes[ name ] = array; + for ( ix = 0; ix < gridX1; ix ++ ) { - } + var x = ix * segmentWidth - widthHalf; - // skinning + // set values to correct vector component - if ( geometry.skinIndices.length > 0 ) { + vector[ u ] = x * udir; + vector[ v ] = y * vdir; + vector[ w ] = depthHalf; - var skinIndices = new Float32BufferAttribute( geometry.skinIndices.length * 4, 4 ); - this.addAttribute( 'skinIndex', skinIndices.copyVector4sArray( geometry.skinIndices ) ); + // now apply vector to vertex buffer - } + vertices.push( vector.x, vector.y, vector.z ); - if ( geometry.skinWeights.length > 0 ) { + // set values to correct vector component - var skinWeights = new Float32BufferAttribute( geometry.skinWeights.length * 4, 4 ); - this.addAttribute( 'skinWeight', skinWeights.copyVector4sArray( geometry.skinWeights ) ); + vector[ u ] = 0; + vector[ v ] = 0; + vector[ w ] = depth > 0 ? 1 : - 1; - } + // now apply vector to normal buffer - // + normals.push( vector.x, vector.y, vector.z ); - if ( geometry.boundingSphere !== null ) { + // uvs - this.boundingSphere = geometry.boundingSphere.clone(); + uvs.push( ix / gridX ); + uvs.push( 1 - ( iy / gridY ) ); - } + // counters - if ( geometry.boundingBox !== null ) { + vertexCounter += 1; - this.boundingBox = geometry.boundingBox.clone(); + } } - return this; - - }, + // indices - computeBoundingBox: function () { + // 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 - if ( this.boundingBox === null ) { + for ( iy = 0; iy < gridY; iy ++ ) { - this.boundingBox = new Box3(); + for ( ix = 0; ix < gridX; ix ++ ) { - } + 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; - var position = this.attributes.position; + // faces - if ( position !== undefined ) { + indices.push( a, b, d ); + indices.push( b, c, d ); - this.boundingBox.setFromBufferAttribute( position ); + // increase counter - } else { + groupCount += 6; - this.boundingBox.makeEmpty(); + } } - if ( isNaN( this.boundingBox.min.x ) || isNaN( this.boundingBox.min.y ) || isNaN( this.boundingBox.min.z ) ) { - - console.error( 'THREE.BufferGeometry.computeBoundingBox: Computed min/max have NaN values. The "position" attribute is likely to have NaN values.', this ); + // add a group to the geometry. this will ensure multi material support - } + scope.addGroup( groupStart, groupCount, materialIndex ); - }, + // calculate new start value for groups - computeBoundingSphere: function () { + groupStart += groupCount; - var box = new Box3(); - var vector = new Vector3(); + // update total number of vertices - return function computeBoundingSphere() { + numberOfVertices += vertexCounter; - if ( this.boundingSphere === null ) { + } - this.boundingSphere = new Sphere(); + } - } + BoxBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); + BoxBufferGeometry.prototype.constructor = BoxBufferGeometry; - var position = this.attributes.position; + /** + * @author mrdoob / http://mrdoob.com/ + * @author Mugen87 / https://github.com/Mugen87 + */ - if ( position ) { + // PlaneGeometry - var center = this.boundingSphere.center; + function PlaneGeometry( width, height, widthSegments, heightSegments ) { - box.setFromBufferAttribute( position ); - box.getCenter( center ); + Geometry.call( this ); - // hoping to find a boundingSphere with a radius smaller than the - // boundingSphere of the boundingBox: sqrt(3) smaller in the best case + this.type = 'PlaneGeometry'; - var maxRadiusSq = 0; + this.parameters = { + width: width, + height: height, + widthSegments: widthSegments, + heightSegments: heightSegments + }; - for ( var i = 0, il = position.count; i < il; i ++ ) { + this.fromBufferGeometry( new PlaneBufferGeometry( width, height, widthSegments, heightSegments ) ); + this.mergeVertices(); - vector.x = position.getX( i ); - vector.y = position.getY( i ); - vector.z = position.getZ( i ); - maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( vector ) ); + } - } + PlaneGeometry.prototype = Object.create( Geometry.prototype ); + PlaneGeometry.prototype.constructor = PlaneGeometry; - this.boundingSphere.radius = Math.sqrt( maxRadiusSq ); + // PlaneBufferGeometry - if ( isNaN( this.boundingSphere.radius ) ) { + function PlaneBufferGeometry( width, height, widthSegments, heightSegments ) { - console.error( 'THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The "position" attribute is likely to have NaN values.', this ); + BufferGeometry.call( this ); - } + this.type = 'PlaneBufferGeometry'; - } + this.parameters = { + width: width, + height: height, + widthSegments: widthSegments, + heightSegments: heightSegments + }; - }; + var width_half = width / 2; + var height_half = height / 2; - }(), + var gridX = Math.floor( widthSegments ) || 1; + var gridY = Math.floor( heightSegments ) || 1; - computeFaceNormals: function () { + var gridX1 = gridX + 1; + var gridY1 = gridY + 1; - // backwards compatibility + var segment_width = width / gridX; + var segment_height = height / gridY; - }, + var ix, iy; - computeVertexNormals: function () { + // buffers - var index = this.index; - var attributes = this.attributes; - var groups = this.groups; + var indices = []; + var vertices = []; + var normals = []; + var uvs = []; - if ( attributes.position ) { + // generate vertices, normals and uvs - var positions = attributes.position.array; + for ( iy = 0; iy < gridY1; iy ++ ) { - if ( attributes.normal === undefined ) { + var y = iy * segment_height - height_half; - this.addAttribute( 'normal', new BufferAttribute( new Float32Array( positions.length ), 3 ) ); + for ( ix = 0; ix < gridX1; ix ++ ) { - } else { + var x = ix * segment_width - width_half; - // reset existing normals to zero + vertices.push( x, - y, 0 ); - var array = attributes.normal.array; + normals.push( 0, 0, 1 ); - for ( var i = 0, il = array.length; i < il; i ++ ) { + uvs.push( ix / gridX ); + uvs.push( 1 - ( iy / gridY ) ); - array[ i ] = 0; + } - } + } - } + // indices - var normals = attributes.normal.array; + for ( iy = 0; iy < gridY; iy ++ ) { - var vA, vB, vC; - var pA = new Vector3(), pB = new Vector3(), pC = new Vector3(); - var cb = new Vector3(), ab = new Vector3(); + for ( ix = 0; ix < gridX; ix ++ ) { - // indexed elements + var a = ix + gridX1 * iy; + var b = ix + gridX1 * ( iy + 1 ); + var c = ( ix + 1 ) + gridX1 * ( iy + 1 ); + var d = ( ix + 1 ) + gridX1 * iy; - if ( index ) { + // faces - var indices = index.array; + indices.push( a, b, d ); + indices.push( b, c, d ); - if ( groups.length === 0 ) { + } - this.addGroup( 0, indices.length ); + } - } + // build geometry - for ( var j = 0, jl = groups.length; j < jl; ++ j ) { + this.setIndex( indices ); + this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); + this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); + this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); - var group = groups[ j ]; + } - var start = group.start; - var count = group.count; + PlaneBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); + PlaneBufferGeometry.prototype.constructor = PlaneBufferGeometry; - for ( var i = start, il = start + count; i < il; i += 3 ) { + /** + * @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.TextureCube( [posx, negx, posy, negy, posz, negz] ), + * combine: THREE.Multiply, + * reflectivity: , + * refractionRatio: , + * + * depthTest: , + * depthWrite: , + * + * wireframe: , + * wireframeLinewidth: , + * + * skinning: , + * morphTargets: + * } + */ - vA = indices[ i + 0 ] * 3; - vB = indices[ i + 1 ] * 3; - vC = indices[ i + 2 ] * 3; + function MeshBasicMaterial( parameters ) { - pA.fromArray( positions, vA ); - pB.fromArray( positions, vB ); - pC.fromArray( positions, vC ); + Material.call( this ); - cb.subVectors( pC, pB ); - ab.subVectors( pA, pB ); - cb.cross( ab ); + this.type = 'MeshBasicMaterial'; - normals[ vA ] += cb.x; - normals[ vA + 1 ] += cb.y; - normals[ vA + 2 ] += cb.z; + this.color = new Color( 0xffffff ); // emissive - normals[ vB ] += cb.x; - normals[ vB + 1 ] += cb.y; - normals[ vB + 2 ] += cb.z; + this.map = null; - normals[ vC ] += cb.x; - normals[ vC + 1 ] += cb.y; - normals[ vC + 2 ] += cb.z; + this.lightMap = null; + this.lightMapIntensity = 1.0; - } + this.aoMap = null; + this.aoMapIntensity = 1.0; - } + this.specularMap = null; - } else { + this.alphaMap = null; - // non-indexed elements (unconnected triangle soup) + this.envMap = null; + this.combine = MultiplyOperation; + this.reflectivity = 1; + this.refractionRatio = 0.98; - for ( var i = 0, il = positions.length; i < il; i += 9 ) { + this.wireframe = false; + this.wireframeLinewidth = 1; + this.wireframeLinecap = 'round'; + this.wireframeLinejoin = 'round'; - pA.fromArray( positions, i ); - pB.fromArray( positions, i + 3 ); - pC.fromArray( positions, i + 6 ); + this.skinning = false; + this.morphTargets = false; - cb.subVectors( pC, pB ); - ab.subVectors( pA, pB ); - cb.cross( ab ); + this.lights = false; - normals[ i ] = cb.x; - normals[ i + 1 ] = cb.y; - normals[ i + 2 ] = cb.z; + this.setValues( parameters ); - normals[ i + 3 ] = cb.x; - normals[ i + 4 ] = cb.y; - normals[ i + 5 ] = cb.z; + } - normals[ i + 6 ] = cb.x; - normals[ i + 7 ] = cb.y; - normals[ i + 8 ] = cb.z; + MeshBasicMaterial.prototype = Object.create( Material.prototype ); + MeshBasicMaterial.prototype.constructor = MeshBasicMaterial; - } + MeshBasicMaterial.prototype.isMeshBasicMaterial = true; - } + MeshBasicMaterial.prototype.copy = function ( source ) { - this.normalizeNormals(); + Material.prototype.copy.call( this, source ); - attributes.normal.needsUpdate = true; + this.color.copy( source.color ); - } + this.map = source.map; - }, + this.lightMap = source.lightMap; + this.lightMapIntensity = source.lightMapIntensity; - merge: function ( geometry, offset ) { + this.aoMap = source.aoMap; + this.aoMapIntensity = source.aoMapIntensity; - if ( ( geometry && geometry.isBufferGeometry ) === false ) { + this.specularMap = source.specularMap; - console.error( 'THREE.BufferGeometry.merge(): geometry not an instance of THREE.BufferGeometry.', geometry ); - return; + this.alphaMap = source.alphaMap; - } + this.envMap = source.envMap; + this.combine = source.combine; + this.reflectivity = source.reflectivity; + this.refractionRatio = source.refractionRatio; - if ( offset === undefined ) offset = 0; + this.wireframe = source.wireframe; + this.wireframeLinewidth = source.wireframeLinewidth; + this.wireframeLinecap = source.wireframeLinecap; + this.wireframeLinejoin = source.wireframeLinejoin; - var attributes = this.attributes; + this.skinning = source.skinning; + this.morphTargets = source.morphTargets; - for ( var key in attributes ) { + return this; - if ( geometry.attributes[ key ] === undefined ) continue; + }; - var attribute1 = attributes[ key ]; - var attributeArray1 = attribute1.array; + /** + * @author bhouston / http://clara.io + */ - var attribute2 = geometry.attributes[ key ]; - var attributeArray2 = attribute2.array; + function Ray( origin, direction ) { - var attributeSize = attribute2.itemSize; + this.origin = ( origin !== undefined ) ? origin : new Vector3(); + this.direction = ( direction !== undefined ) ? direction : new Vector3(); - for ( var i = 0, j = attributeSize * offset; i < attributeArray2.length; i ++, j ++ ) { + } - attributeArray1[ j ] = attributeArray2[ i ]; + Object.assign( Ray.prototype, { - } + set: function ( origin, direction ) { - } + this.origin.copy( origin ); + this.direction.copy( direction ); return this; }, - normalizeNormals: function () { - - var normals = this.attributes.normal; - - var x, y, z, n; + clone: function () { - for ( var i = 0, il = normals.count; i < il; i ++ ) { + return new this.constructor().copy( this ); - x = normals.getX( i ); - y = normals.getY( i ); - z = normals.getZ( i ); + }, - n = 1.0 / Math.sqrt( x * x + y * y + z * z ); + copy: function ( ray ) { - normals.setXYZ( i, x * n, y * n, z * n ); + this.origin.copy( ray.origin ); + this.direction.copy( ray.direction ); - } + return this; }, - toNonIndexed: function () { + at: function ( t, optionalTarget ) { - if ( this.index === null ) { + var result = optionalTarget || new Vector3(); - console.warn( 'THREE.BufferGeometry.toNonIndexed(): Geometry is already non-indexed.' ); - return this; + return result.copy( this.direction ).multiplyScalar( t ).add( this.origin ); - } + }, - var geometry2 = new BufferGeometry(); + lookAt: function ( v ) { - var indices = this.index.array; - var attributes = this.attributes; + this.direction.copy( v ).sub( this.origin ).normalize(); - for ( var name in attributes ) { + return this; - var attribute = attributes[ name ]; + }, - var array = attribute.array; - var itemSize = attribute.itemSize; + recast: function () { - var array2 = new array.constructor( indices.length * itemSize ); + var v1 = new Vector3(); - var index = 0, index2 = 0; + return function recast( t ) { - for ( var i = 0, l = indices.length; i < l; i ++ ) { + this.origin.copy( this.at( t, v1 ) ); - index = indices[ i ] * itemSize; + return this; - for ( var j = 0; j < itemSize; j ++ ) { + }; - array2[ index2 ++ ] = array[ index ++ ]; + }(), - } + closestPointToPoint: function ( point, optionalTarget ) { - } + var result = optionalTarget || new Vector3(); + result.subVectors( point, this.origin ); + var directionDistance = result.dot( this.direction ); - geometry2.addAttribute( name, new BufferAttribute( array2, itemSize ) ); + if ( directionDistance < 0 ) { + + return result.copy( this.origin ); } - return geometry2; + return result.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin ); }, - toJSON: function () { + distanceToPoint: function ( point ) { - var data = { - metadata: { - version: 4.5, - type: 'BufferGeometry', - generator: 'BufferGeometry.toJSON' - } - }; + return Math.sqrt( this.distanceSqToPoint( point ) ); - // standard BufferGeometry serialization + }, - data.uuid = this.uuid; - data.type = this.type; - if ( this.name !== '' ) data.name = this.name; + distanceSqToPoint: function () { - if ( this.parameters !== undefined ) { + var v1 = new Vector3(); - var parameters = this.parameters; + return function distanceSqToPoint( point ) { - for ( var key in parameters ) { + var directionDistance = v1.subVectors( point, this.origin ).dot( this.direction ); - if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ]; + // point behind the ray - } + if ( directionDistance < 0 ) { - return data; + return this.origin.distanceToSquared( point ); - } + } - data.data = { attributes: {} }; + v1.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin ); - var index = this.index; + return v1.distanceToSquared( point ); - if ( index !== null ) { + }; - var array = Array.prototype.slice.call( index.array ); + }(), - data.data.index = { - type: index.array.constructor.name, - array: array - }; + distanceSqToSegment: function () { - } + var segCenter = new Vector3(); + var segDir = new Vector3(); + var diff = new Vector3(); - var attributes = this.attributes; + return function distanceSqToSegment( v0, v1, optionalPointOnRay, optionalPointOnSegment ) { - for ( var key in attributes ) { + // 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 - var attribute = attributes[ key ]; + segCenter.copy( v0 ).add( v1 ).multiplyScalar( 0.5 ); + segDir.copy( v1 ).sub( v0 ).normalize(); + diff.copy( this.origin ).sub( segCenter ); - var array = Array.prototype.slice.call( attribute.array ); + 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; - data.data.attributes[ key ] = { - itemSize: attribute.itemSize, - type: attribute.array.constructor.name, - array: array, - normalized: attribute.normalized - }; + if ( det > 0 ) { - } + // The ray and segment are not parallel. - var groups = this.groups; + s0 = a01 * b1 - b0; + s1 = a01 * b0 - b1; + extDet = segExtent * det; + + if ( s0 >= 0 ) { - if ( groups.length > 0 ) { + if ( s1 >= - extDet ) { - data.data.groups = JSON.parse( JSON.stringify( groups ) ); + if ( s1 <= extDet ) { - } + // region 0 + // Minimum at interior points of ray and segment. - var boundingSphere = this.boundingSphere; + var invDet = 1 / det; + s0 *= invDet; + s1 *= invDet; + sqrDist = s0 * ( s0 + a01 * s1 + 2 * b0 ) + s1 * ( a01 * s0 + s1 + 2 * b1 ) + c; - if ( boundingSphere !== null ) { + } else { - data.data.boundingSphere = { - center: boundingSphere.center.toArray(), - radius: boundingSphere.radius - }; + // region 1 - } + s1 = segExtent; + s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); + sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; - return data; + } - }, + } else { - clone: function () { + // region 5 - /* - // Handle primitives + s1 = - segExtent; + s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); + sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; - var parameters = this.parameters; + } - if ( parameters !== undefined ) { + } else { - var values = []; + if ( s1 <= - extDet ) { - for ( var key in parameters ) { + // region 4 - values.push( parameters[ key ] ); + 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; - } + } else if ( s1 <= extDet ) { - var geometry = Object.create( this.constructor.prototype ); - this.constructor.apply( geometry, values ); - return geometry; + // region 3 - } + s0 = 0; + s1 = Math.min( Math.max( - segExtent, - b1 ), segExtent ); + sqrDist = s1 * ( s1 + 2 * b1 ) + c; - return new this.constructor().copy( this ); - */ + } else { - return new BufferGeometry().copy( this ); + // 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; - copy: function ( source ) { + } - var name, i, l; + } - // reset + } else { - this.index = null; - this.attributes = {}; - this.morphAttributes = {}; - this.groups = []; - this.boundingBox = null; - this.boundingSphere = null; + // Ray and segment are parallel. - // name + s1 = ( a01 > 0 ) ? - segExtent : segExtent; + s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); + sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; - this.name = source.name; + } - // index + if ( optionalPointOnRay ) { - var index = source.index; + optionalPointOnRay.copy( this.direction ).multiplyScalar( s0 ).add( this.origin ); - if ( index !== null ) { + } - this.setIndex( index.clone() ); + if ( optionalPointOnSegment ) { - } + optionalPointOnSegment.copy( segDir ).multiplyScalar( s1 ).add( segCenter ); - // attributes + } - var attributes = source.attributes; + return sqrDist; - for ( name in attributes ) { + }; - var attribute = attributes[ name ]; - this.addAttribute( name, attribute.clone() ); + }(), - } + intersectSphere: function () { - // morph attributes + var v1 = new Vector3(); - var morphAttributes = source.morphAttributes; + return function intersectSphere( sphere, optionalTarget ) { - for ( name in morphAttributes ) { + v1.subVectors( sphere.center, this.origin ); + var tca = v1.dot( this.direction ); + var d2 = v1.dot( v1 ) - tca * tca; + var radius2 = sphere.radius * sphere.radius; - var array = []; - var morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes + if ( d2 > radius2 ) return null; - for ( i = 0, l = morphAttribute.length; i < l; i ++ ) { + var thc = Math.sqrt( radius2 - d2 ); - array.push( morphAttribute[ i ].clone() ); + // t0 = first intersect point - entrance on front of sphere + var t0 = tca - thc; - } + // t1 = second intersect point - exit point on back of sphere + var t1 = tca + thc; - this.morphAttributes[ name ] = array; + // 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, optionalTarget ); - // groups + // else t0 is in front of the ray, so return the first collision point scaled by t0 + return this.at( t0, optionalTarget ); - var groups = source.groups; + }; - for ( i = 0, l = groups.length; i < l; i ++ ) { + }(), - var group = groups[ i ]; - this.addGroup( group.start, group.count, group.materialIndex ); + intersectsSphere: function ( sphere ) { - } + return this.distanceToPoint( sphere.center ) <= sphere.radius; - // bounding box + }, - var boundingBox = source.boundingBox; + distanceToPlane: function ( plane ) { - if ( boundingBox !== null ) { + var denominator = plane.normal.dot( this.direction ); - this.boundingBox = boundingBox.clone(); + if ( denominator === 0 ) { - } + // line is coplanar, return origin + if ( plane.distanceToPoint( this.origin ) === 0 ) { - // bounding sphere + return 0; - var boundingSphere = source.boundingSphere; + } - if ( boundingSphere !== null ) { + // Null is preferable to undefined since undefined means.... it is undefined - this.boundingSphere = boundingSphere.clone(); + return null; } - // draw range + var t = - ( this.origin.dot( plane.normal ) + plane.constant ) / denominator; - this.drawRange.start = source.drawRange.start; - this.drawRange.count = source.drawRange.count; + // Return if the ray never intersects the plane - return this; + return t >= 0 ? t : null; }, - dispose: function () { - - this.dispatchEvent( { type: 'dispose' } ); - - } - - } ); + intersectPlane: function ( plane, optionalTarget ) { - /** - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - * @author mikael emtinger / http://gomo.se/ - * @author jonobr1 / http://jonobr1.com/ - */ + var t = this.distanceToPlane( plane ); - function Mesh( geometry, material ) { + if ( t === null ) { - Object3D.call( this ); + return null; - this.type = 'Mesh'; + } - this.geometry = geometry !== undefined ? geometry : new BufferGeometry(); - this.material = material !== undefined ? material : new MeshBasicMaterial( { color: Math.random() * 0xffffff } ); + return this.at( t, optionalTarget ); - this.drawMode = TrianglesDrawMode; + }, - this.updateMorphTargets(); + intersectsPlane: function ( plane ) { - } + // check if the ray lies on the plane first - Mesh.prototype = Object.assign( Object.create( Object3D.prototype ), { + var distToPoint = plane.distanceToPoint( this.origin ); - constructor: Mesh, + if ( distToPoint === 0 ) { - isMesh: true, + return true; - setDrawMode: function ( value ) { + } - this.drawMode = value; + var denominator = plane.normal.dot( this.direction ); - }, + if ( denominator * distToPoint < 0 ) { - copy: function ( source ) { + return true; - Object3D.prototype.copy.call( this, source ); + } - this.drawMode = source.drawMode; + // ray origin is behind the plane (and is pointing behind it) - return this; + return false; }, - updateMorphTargets: function () { - - var geometry = this.geometry; - var m, ml, name; + intersectBox: function ( box, optionalTarget ) { - if ( geometry.isBufferGeometry ) { + var tmin, tmax, tymin, tymax, tzmin, tzmax; - var morphAttributes = geometry.morphAttributes; - var keys = Object.keys( morphAttributes ); + var invdirx = 1 / this.direction.x, + invdiry = 1 / this.direction.y, + invdirz = 1 / this.direction.z; - if ( keys.length > 0 ) { + var origin = this.origin; - var morphAttribute = morphAttributes[ keys[ 0 ] ]; + if ( invdirx >= 0 ) { - if ( morphAttribute !== undefined ) { + tmin = ( box.min.x - origin.x ) * invdirx; + tmax = ( box.max.x - origin.x ) * invdirx; - this.morphTargetInfluences = []; - this.morphTargetDictionary = {}; + } else { - for ( m = 0, ml = morphAttribute.length; m < ml; m ++ ) { + tmin = ( box.max.x - origin.x ) * invdirx; + tmax = ( box.min.x - origin.x ) * invdirx; - name = morphAttribute[ m ].name || String( m ); + } - this.morphTargetInfluences.push( 0 ); - this.morphTargetDictionary[ name ] = m; + if ( invdiry >= 0 ) { - } + tymin = ( box.min.y - origin.y ) * invdiry; + tymax = ( box.max.y - origin.y ) * invdiry; - } + } else { - } + tymin = ( box.max.y - origin.y ) * invdiry; + tymax = ( box.min.y - origin.y ) * invdiry; - } else { + } - var morphTargets = geometry.morphTargets; + if ( ( tmin > tymax ) || ( tymin > tmax ) ) return null; - if ( morphTargets !== undefined && morphTargets.length > 0 ) { + // These lines also handle the case where tmin or tmax is NaN + // (result of 0 * Infinity). x !== x returns true if x is NaN - this.morphTargetInfluences = []; - this.morphTargetDictionary = {}; + if ( tymin > tmin || tmin !== tmin ) tmin = tymin; - for ( m = 0, ml = morphTargets.length; m < ml; m ++ ) { + if ( tymax < tmax || tmax !== tmax ) tmax = tymax; - name = morphTargets[ m ].name || String( m ); + if ( invdirz >= 0 ) { - this.morphTargetInfluences.push( 0 ); - this.morphTargetDictionary[ name ] = m; + 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; } - }, + if ( ( tmin > tzmax ) || ( tzmin > tmax ) ) return null; - raycast: ( function () { + if ( tzmin > tmin || tmin !== tmin ) tmin = tzmin; - var inverseMatrix = new Matrix4(); - var ray = new Ray(); - var sphere = new Sphere(); + if ( tzmax < tmax || tmax !== tmax ) tmax = tzmax; - var vA = new Vector3(); - var vB = new Vector3(); - var vC = new Vector3(); + //return point closest to the ray (positive side) - var tempA = new Vector3(); - var tempB = new Vector3(); - var tempC = new Vector3(); + if ( tmax < 0 ) return null; - var uvA = new Vector2(); - var uvB = new Vector2(); - var uvC = new Vector2(); + return this.at( tmin >= 0 ? tmin : tmax, optionalTarget ); - var barycoord = new Vector3(); + }, - var intersectionPoint = new Vector3(); - var intersectionPointWorld = new Vector3(); + intersectsBox: ( function () { - function uvIntersection( point, p1, p2, p3, uv1, uv2, uv3 ) { + var v = new Vector3(); - Triangle.barycoordFromPoint( point, p1, p2, p3, barycoord ); + return function intersectsBox( box ) { - uv1.multiplyScalar( barycoord.x ); - uv2.multiplyScalar( barycoord.y ); - uv3.multiplyScalar( barycoord.z ); + return this.intersectBox( box, v ) !== null; - uv1.add( uv2 ).add( uv3 ); + }; - return uv1.clone(); + } )(), - } + intersectTriangle: function () { - function checkIntersection( object, raycaster, ray, pA, pB, pC, point ) { + // Compute the offset origin, edges, and normal. + var diff = new Vector3(); + var edge1 = new Vector3(); + var edge2 = new Vector3(); + var normal = new Vector3(); - var intersect; - var material = object.material; + return function intersectTriangle( a, b, c, backfaceCulling, optionalTarget ) { - if ( material.side === BackSide ) { + // from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteIntrRay3Triangle3.h - intersect = ray.intersectTriangle( pC, pB, pA, true, point ); + edge1.subVectors( b, a ); + edge2.subVectors( c, a ); + normal.crossVectors( edge1, edge2 ); - } else { + // 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; - intersect = ray.intersectTriangle( pA, pB, pC, material.side !== DoubleSide, point ); + if ( DdN > 0 ) { - } + if ( backfaceCulling ) return null; + sign = 1; - if ( intersect === null ) return null; + } else if ( DdN < 0 ) { - intersectionPointWorld.copy( point ); - intersectionPointWorld.applyMatrix4( object.matrixWorld ); + sign = - 1; + DdN = - DdN; - var distance = raycaster.ray.origin.distanceTo( intersectionPointWorld ); + } else { - if ( distance < raycaster.near || distance > raycaster.far ) return null; + return null; - return { - distance: distance, - point: intersectionPointWorld.clone(), - object: object - }; + } - } + diff.subVectors( this.origin, a ); + var DdQxE2 = sign * this.direction.dot( edge2.crossVectors( diff, edge2 ) ); - function checkBufferGeometryIntersection( object, raycaster, ray, position, uv, a, b, c ) { + // b1 < 0, no intersection + if ( DdQxE2 < 0 ) { - vA.fromBufferAttribute( position, a ); - vB.fromBufferAttribute( position, b ); - vC.fromBufferAttribute( position, c ); + return null; - var intersection = checkIntersection( object, raycaster, ray, vA, vB, vC, intersectionPoint ); + } - if ( intersection ) { + var DdE1xQ = sign * this.direction.dot( edge1.cross( diff ) ); - if ( uv ) { + // b2 < 0, no intersection + if ( DdE1xQ < 0 ) { - uvA.fromBufferAttribute( uv, a ); - uvB.fromBufferAttribute( uv, b ); - uvC.fromBufferAttribute( uv, c ); + return null; - intersection.uv = uvIntersection( intersectionPoint, vA, vB, vC, uvA, uvB, uvC ); + } - } + // b1+b2 > 1, no intersection + if ( DdQxE2 + DdE1xQ > DdN ) { - intersection.face = new Face3( a, b, c, Triangle.normal( vA, vB, vC ) ); - intersection.faceIndex = a; + return null; } - return intersection; - - } + // Line intersects triangle, check if ray does. + var QdN = - sign * diff.dot( normal ); - return function raycast( raycaster, intersects ) { + // t < 0, no intersection + if ( QdN < 0 ) { - var geometry = this.geometry; - var material = this.material; - var matrixWorld = this.matrixWorld; + return null; - if ( material === undefined ) return; + } - // Checking boundingSphere distance to ray + // Ray intersects triangle. + return this.at( QdN / DdN, optionalTarget ); - if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); + }; - sphere.copy( geometry.boundingSphere ); - sphere.applyMatrix4( matrixWorld ); + }(), - if ( raycaster.ray.intersectsSphere( sphere ) === false ) return; + applyMatrix4: function ( matrix4 ) { - // + this.origin.applyMatrix4( matrix4 ); + this.direction.transformDirection( matrix4 ); - inverseMatrix.getInverse( matrixWorld ); - ray.copy( raycaster.ray ).applyMatrix4( inverseMatrix ); + return this; - // Check boundingBox before continuing + }, - if ( geometry.boundingBox !== null ) { + equals: function ( ray ) { - if ( ray.intersectsBox( geometry.boundingBox ) === false ) return; + return ray.origin.equals( this.origin ) && ray.direction.equals( this.direction ); - } + } - var intersection; + } ); - if ( geometry.isBufferGeometry ) { + /** + * @author bhouston / http://clara.io + */ - var a, b, c; - var index = geometry.index; - var position = geometry.attributes.position; - var uv = geometry.attributes.uv; - var i, l; + function Line3( start, end ) { - if ( index !== null ) { + this.start = ( start !== undefined ) ? start : new Vector3(); + this.end = ( end !== undefined ) ? end : new Vector3(); - // indexed buffer geometry + } - for ( i = 0, l = index.count; i < l; i += 3 ) { + Object.assign( Line3.prototype, { - a = index.getX( i ); - b = index.getX( i + 1 ); - c = index.getX( i + 2 ); + set: function ( start, end ) { - intersection = checkBufferGeometryIntersection( this, raycaster, ray, position, uv, a, b, c ); + this.start.copy( start ); + this.end.copy( end ); - if ( intersection ) { + return this; - intersection.faceIndex = Math.floor( i / 3 ); // triangle number in indices buffer semantics - intersects.push( intersection ); + }, - } + clone: function () { - } + return new this.constructor().copy( this ); - } else { + }, - // non-indexed buffer geometry + copy: function ( line ) { - for ( i = 0, l = position.count; i < l; i += 3 ) { + this.start.copy( line.start ); + this.end.copy( line.end ); - a = i; - b = i + 1; - c = i + 2; + return this; - intersection = checkBufferGeometryIntersection( this, raycaster, ray, position, uv, a, b, c ); + }, - if ( intersection ) { + getCenter: function ( optionalTarget ) { - intersection.index = a; // triangle number in positions buffer semantics - intersects.push( intersection ); + var result = optionalTarget || new Vector3(); + return result.addVectors( this.start, this.end ).multiplyScalar( 0.5 ); - } + }, - } + delta: function ( optionalTarget ) { - } + var result = optionalTarget || new Vector3(); + return result.subVectors( this.end, this.start ); - } else if ( geometry.isGeometry ) { + }, - var fvA, fvB, fvC; - var isMultiMaterial = Array.isArray( material ); + distanceSq: function () { - var vertices = geometry.vertices; - var faces = geometry.faces; - var uvs; + return this.start.distanceToSquared( this.end ); - var faceVertexUvs = geometry.faceVertexUvs[ 0 ]; - if ( faceVertexUvs.length > 0 ) uvs = faceVertexUvs; + }, - for ( var f = 0, fl = faces.length; f < fl; f ++ ) { + distance: function () { - var face = faces[ f ]; - var faceMaterial = isMultiMaterial ? material[ face.materialIndex ] : material; + return this.start.distanceTo( this.end ); - if ( faceMaterial === undefined ) continue; + }, - fvA = vertices[ face.a ]; - fvB = vertices[ face.b ]; - fvC = vertices[ face.c ]; + at: function ( t, optionalTarget ) { - if ( faceMaterial.morphTargets === true ) { + var result = optionalTarget || new Vector3(); - var morphTargets = geometry.morphTargets; - var morphInfluences = this.morphTargetInfluences; + return this.delta( result ).multiplyScalar( t ).add( this.start ); - vA.set( 0, 0, 0 ); - vB.set( 0, 0, 0 ); - vC.set( 0, 0, 0 ); + }, - for ( var t = 0, tl = morphTargets.length; t < tl; t ++ ) { + closestPointToPointParameter: function () { - var influence = morphInfluences[ t ]; + var startP = new Vector3(); + var startEnd = new Vector3(); - if ( influence === 0 ) continue; + return function closestPointToPointParameter( point, clampToLine ) { - var targets = morphTargets[ t ].vertices; + startP.subVectors( point, this.start ); + startEnd.subVectors( this.end, this.start ); - vA.addScaledVector( tempA.subVectors( targets[ face.a ], fvA ), influence ); - vB.addScaledVector( tempB.subVectors( targets[ face.b ], fvB ), influence ); - vC.addScaledVector( tempC.subVectors( targets[ face.c ], fvC ), influence ); + var startEnd2 = startEnd.dot( startEnd ); + var startEnd_startP = startEnd.dot( startP ); - } + var t = startEnd_startP / startEnd2; - vA.add( fvA ); - vB.add( fvB ); - vC.add( fvC ); + if ( clampToLine ) { - fvA = vA; - fvB = vB; - fvC = vC; + t = _Math.clamp( t, 0, 1 ); - } + } - intersection = checkIntersection( this, raycaster, ray, fvA, fvB, fvC, intersectionPoint ); + return t; - if ( intersection ) { + }; - if ( uvs && uvs[ f ] ) { + }(), - var uvs_f = uvs[ f ]; - uvA.copy( uvs_f[ 0 ] ); - uvB.copy( uvs_f[ 1 ] ); - uvC.copy( uvs_f[ 2 ] ); + closestPointToPoint: function ( point, clampToLine, optionalTarget ) { - intersection.uv = uvIntersection( intersectionPoint, fvA, fvB, fvC, uvA, uvB, uvC ); + var t = this.closestPointToPointParameter( point, clampToLine ); - } + var result = optionalTarget || new Vector3(); - intersection.face = face; - intersection.faceIndex = f; - intersects.push( intersection ); + return this.delta( result ).multiplyScalar( t ).add( this.start ); - } + }, - } + applyMatrix4: function ( matrix ) { - } + this.start.applyMatrix4( matrix ); + this.end.applyMatrix4( matrix ); - }; + return this; - }() ), + }, - clone: function () { + equals: function ( line ) { - return new this.constructor( this.geometry, this.material ).copy( this ); + return line.start.equals( this.start ) && line.end.equals( this.end ); } } ); /** + * @author bhouston / http://clara.io * @author mrdoob / http://mrdoob.com/ - * @author Mugen87 / https://github.com/Mugen87 */ - // BoxGeometry - - function BoxGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) { - - Geometry.call( this ); - - this.type = 'BoxGeometry'; - - this.parameters = { - width: width, - height: height, - depth: depth, - widthSegments: widthSegments, - heightSegments: heightSegments, - depthSegments: depthSegments - }; + function Triangle( a, b, c ) { - this.fromBufferGeometry( new BoxBufferGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) ); - this.mergeVertices(); + this.a = ( a !== undefined ) ? a : new Vector3(); + this.b = ( b !== undefined ) ? b : new Vector3(); + this.c = ( c !== undefined ) ? c : new Vector3(); } - BoxGeometry.prototype = Object.create( Geometry.prototype ); - BoxGeometry.prototype.constructor = BoxGeometry; - - // BoxBufferGeometry + Object.assign( Triangle, { - function BoxBufferGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) { + normal: function () { - BufferGeometry.call( this ); + var v0 = new Vector3(); - this.type = 'BoxBufferGeometry'; + return function normal( a, b, c, optionalTarget ) { - this.parameters = { - width: width, - height: height, - depth: depth, - widthSegments: widthSegments, - heightSegments: heightSegments, - depthSegments: depthSegments - }; + var result = optionalTarget || new Vector3(); - var scope = this; + result.subVectors( c, b ); + v0.subVectors( a, b ); + result.cross( v0 ); - // segments + var resultLengthSq = result.lengthSq(); + if ( resultLengthSq > 0 ) { - widthSegments = Math.floor( widthSegments ) || 1; - heightSegments = Math.floor( heightSegments ) || 1; - depthSegments = Math.floor( depthSegments ) || 1; + return result.multiplyScalar( 1 / Math.sqrt( resultLengthSq ) ); - // buffers + } - var indices = []; - var vertices = []; - var normals = []; - var uvs = []; + return result.set( 0, 0, 0 ); - // helper variables + }; - var numberOfVertices = 0; - var groupStart = 0; + }(), - // build each side of the box geometry + // static/instance method to calculate barycentric coordinates + // based on: http://www.blackpawn.com/texts/pointinpoly/default.html + barycoordFromPoint: function () { - 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 + var v0 = new Vector3(); + var v1 = new Vector3(); + var v2 = new Vector3(); - // build geometry + return function barycoordFromPoint( point, a, b, c, optionalTarget ) { - this.setIndex( indices ); - this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); + v0.subVectors( c, a ); + v1.subVectors( b, a ); + v2.subVectors( point, a ); - function buildPlane( u, v, w, udir, vdir, width, height, depth, gridX, gridY, materialIndex ) { + var dot00 = v0.dot( v0 ); + var dot01 = v0.dot( v1 ); + var dot02 = v0.dot( v2 ); + var dot11 = v1.dot( v1 ); + var dot12 = v1.dot( v2 ); - var segmentWidth = width / gridX; - var segmentHeight = height / gridY; + var denom = ( dot00 * dot11 - dot01 * dot01 ); - var widthHalf = width / 2; - var heightHalf = height / 2; - var depthHalf = depth / 2; + var result = optionalTarget || new Vector3(); - var gridX1 = gridX + 1; - var gridY1 = gridY + 1; + // collinear or singular triangle + if ( denom === 0 ) { - var vertexCounter = 0; - var groupCount = 0; + // arbitrary location outside of triangle? + // not sure if this is the best idea, maybe should be returning undefined + return result.set( - 2, - 1, - 1 ); - var ix, iy; + } - var vector = new Vector3(); + var invDenom = 1 / denom; + var u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom; + var v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom; - // generate vertices, normals and uvs + // barycentric coordinates must always sum to 1 + return result.set( 1 - u - v, v, u ); - for ( iy = 0; iy < gridY1; iy ++ ) { + }; - var y = iy * segmentHeight - heightHalf; + }(), - for ( ix = 0; ix < gridX1; ix ++ ) { + containsPoint: function () { - var x = ix * segmentWidth - widthHalf; + var v1 = new Vector3(); - // set values to correct vector component + return function containsPoint( point, a, b, c ) { - vector[ u ] = x * udir; - vector[ v ] = y * vdir; - vector[ w ] = depthHalf; + var result = Triangle.barycoordFromPoint( point, a, b, c, v1 ); - // now apply vector to vertex buffer + return ( result.x >= 0 ) && ( result.y >= 0 ) && ( ( result.x + result.y ) <= 1 ); - vertices.push( vector.x, vector.y, vector.z ); + }; - // set values to correct vector component + }() - vector[ u ] = 0; - vector[ v ] = 0; - vector[ w ] = depth > 0 ? 1 : - 1; + } ); - // now apply vector to normal buffer + Object.assign( Triangle.prototype, { - normals.push( vector.x, vector.y, vector.z ); + set: function ( a, b, c ) { - // uvs + this.a.copy( a ); + this.b.copy( b ); + this.c.copy( c ); - uvs.push( ix / gridX ); - uvs.push( 1 - ( iy / gridY ) ); + return this; - // counters + }, - vertexCounter += 1; + setFromPointsAndIndices: function ( points, i0, i1, i2 ) { - } + this.a.copy( points[ i0 ] ); + this.b.copy( points[ i1 ] ); + this.c.copy( points[ i2 ] ); - } + return this; - // 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 + clone: function () { - for ( iy = 0; iy < gridY; iy ++ ) { + return new this.constructor().copy( this ); - for ( ix = 0; ix < gridX; ix ++ ) { + }, - 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; + copy: function ( triangle ) { - // faces + this.a.copy( triangle.a ); + this.b.copy( triangle.b ); + this.c.copy( triangle.c ); - indices.push( a, b, d ); - indices.push( b, c, d ); + return this; - // increase counter + }, - groupCount += 6; + area: function () { - } + var v0 = new Vector3(); + var v1 = new Vector3(); - } + return function area() { - // add a group to the geometry. this will ensure multi material support + v0.subVectors( this.c, this.b ); + v1.subVectors( this.a, this.b ); - scope.addGroup( groupStart, groupCount, materialIndex ); + return v0.cross( v1 ).length() * 0.5; - // calculate new start value for groups + }; - groupStart += groupCount; + }(), - // update total number of vertices + midpoint: function ( optionalTarget ) { - numberOfVertices += vertexCounter; + var result = optionalTarget || new Vector3(); + return result.addVectors( this.a, this.b ).add( this.c ).multiplyScalar( 1 / 3 ); - } + }, - } + normal: function ( optionalTarget ) { - BoxBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); - BoxBufferGeometry.prototype.constructor = BoxBufferGeometry; + return Triangle.normal( this.a, this.b, this.c, optionalTarget ); - /** - * @author mrdoob / http://mrdoob.com/ - * @author Mugen87 / https://github.com/Mugen87 - */ + }, - // PlaneGeometry + plane: function ( optionalTarget ) { - function PlaneGeometry( width, height, widthSegments, heightSegments ) { + var result = optionalTarget || new Plane(); - Geometry.call( this ); + return result.setFromCoplanarPoints( this.a, this.b, this.c ); - this.type = 'PlaneGeometry'; + }, - this.parameters = { - width: width, - height: height, - widthSegments: widthSegments, - heightSegments: heightSegments - }; + barycoordFromPoint: function ( point, optionalTarget ) { - this.fromBufferGeometry( new PlaneBufferGeometry( width, height, widthSegments, heightSegments ) ); - this.mergeVertices(); + return Triangle.barycoordFromPoint( point, this.a, this.b, this.c, optionalTarget ); - } + }, - PlaneGeometry.prototype = Object.create( Geometry.prototype ); - PlaneGeometry.prototype.constructor = PlaneGeometry; + containsPoint: function ( point ) { - // PlaneBufferGeometry + return Triangle.containsPoint( point, this.a, this.b, this.c ); - function PlaneBufferGeometry( width, height, widthSegments, heightSegments ) { + }, - BufferGeometry.call( this ); + closestPointToPoint: function () { - this.type = 'PlaneBufferGeometry'; + var plane = new Plane(); + var edgeList = [ new Line3(), new Line3(), new Line3() ]; + var projectedPoint = new Vector3(); + var closestPoint = new Vector3(); - this.parameters = { - width: width, - height: height, - widthSegments: widthSegments, - heightSegments: heightSegments - }; + return function closestPointToPoint( point, optionalTarget ) { - var width_half = width / 2; - var height_half = height / 2; + var result = optionalTarget || new Vector3(); + var minDistance = Infinity; - var gridX = Math.floor( widthSegments ) || 1; - var gridY = Math.floor( heightSegments ) || 1; + // project the point onto the plane of the triangle - var gridX1 = gridX + 1; - var gridY1 = gridY + 1; + plane.setFromCoplanarPoints( this.a, this.b, this.c ); + plane.projectPoint( point, projectedPoint ); - var segment_width = width / gridX; - var segment_height = height / gridY; + // check if the projection lies within the triangle - var ix, iy; + if( this.containsPoint( projectedPoint ) === true ) { - // buffers + // if so, this is the closest point - var indices = []; - var vertices = []; - var normals = []; - var uvs = []; + result.copy( projectedPoint ); - // generate vertices, normals and uvs + } else { - for ( iy = 0; iy < gridY1; iy ++ ) { + // if not, the point falls outside the triangle. the result is the closest point to the triangle's edges or vertices - var y = iy * segment_height - height_half; + edgeList[ 0 ].set( this.a, this.b ); + edgeList[ 1 ].set( this.b, this.c ); + edgeList[ 2 ].set( this.c, this.a ); - for ( ix = 0; ix < gridX1; ix ++ ) { + for( var i = 0; i < edgeList.length; i ++ ) { - var x = ix * segment_width - width_half; + edgeList[ i ].closestPointToPoint( projectedPoint, true, closestPoint ); - vertices.push( x, - y, 0 ); + var distance = projectedPoint.distanceToSquared( closestPoint ); - normals.push( 0, 0, 1 ); + if( distance < minDistance ) { - uvs.push( ix / gridX ); - uvs.push( 1 - ( iy / gridY ) ); + minDistance = distance; - } + result.copy( closestPoint ); - } + } - // indices + } - for ( iy = 0; iy < gridY; iy ++ ) { + } - for ( ix = 0; ix < gridX; ix ++ ) { + return result; - var a = ix + gridX1 * iy; - var b = ix + gridX1 * ( iy + 1 ); - var c = ( ix + 1 ) + gridX1 * ( iy + 1 ); - var d = ( ix + 1 ) + gridX1 * iy; + }; - // faces + }(), - indices.push( a, b, d ); - indices.push( b, c, d ); + equals: function ( triangle ) { - } + return triangle.a.equals( this.a ) && triangle.b.equals( this.b ) && triangle.c.equals( this.c ); } - // 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 ) ); - - } - - PlaneBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); - PlaneBufferGeometry.prototype.constructor = PlaneBufferGeometry; + } ); /** * @author mrdoob / http://mrdoob.com/ + * @author alteredq / http://alteredqualia.com/ * @author mikael emtinger / http://gomo.se/ - * @author WestLangley / http://github.com/WestLangley - */ + * @author jonobr1 / http://jonobr1.com/ + */ - function Camera() { + function Mesh( geometry, material ) { Object3D.call( this ); - this.type = 'Camera'; + this.type = 'Mesh'; - this.matrixWorldInverse = new Matrix4(); - this.projectionMatrix = new Matrix4(); + this.geometry = geometry !== undefined ? geometry : new BufferGeometry(); + this.material = material !== undefined ? material : new MeshBasicMaterial( { color: Math.random() * 0xffffff } ); + + this.drawMode = TrianglesDrawMode; + + this.updateMorphTargets(); } - Camera.prototype = Object.assign( Object.create( Object3D.prototype ), { + Mesh.prototype = Object.assign( Object.create( Object3D.prototype ), { - constructor: Camera, + constructor: Mesh, - isCamera: true, + isMesh: true, + + setDrawMode: function ( value ) { + + this.drawMode = value; + + }, copy: function ( source ) { Object3D.prototype.copy.call( this, source ); - this.matrixWorldInverse.copy( source.matrixWorldInverse ); - this.projectionMatrix.copy( source.projectionMatrix ); + this.drawMode = source.drawMode; return this; }, - getWorldDirection: function () { - - var quaternion = new Quaternion(); - - return function getWorldDirection( optionalTarget ) { + updateMorphTargets: function () { - var result = optionalTarget || new Vector3(); + var geometry = this.geometry; + var m, ml, name; - this.getWorldQuaternion( quaternion ); + if ( geometry.isBufferGeometry ) { - return result.set( 0, 0, - 1 ).applyQuaternion( quaternion ); + var morphAttributes = geometry.morphAttributes; + var keys = Object.keys( morphAttributes ); - }; + if ( keys.length > 0 ) { - }(), + var morphAttribute = morphAttributes[ keys[ 0 ] ]; - clone: function () { + if ( morphAttribute !== undefined ) { - return new this.constructor().copy( this ); + this.morphTargetInfluences = []; + this.morphTargetDictionary = {}; - } + for ( m = 0, ml = morphAttribute.length; m < ml; m ++ ) { - } ); + name = morphAttribute[ m ].name || String( m ); - /** - * @author mrdoob / http://mrdoob.com/ - * @author greggman / http://games.greggman.com/ - * @author zz85 / http://www.lab4games.net/zz85/blog - * @author tschw - */ + this.morphTargetInfluences.push( 0 ); + this.morphTargetDictionary[ name ] = m; - function PerspectiveCamera( fov, aspect, near, far ) { + } - Camera.call( this ); + } - this.type = 'PerspectiveCamera'; + } - this.fov = fov !== undefined ? fov : 50; - this.zoom = 1; + } else { - this.near = near !== undefined ? near : 0.1; - this.far = far !== undefined ? far : 2000; - this.focus = 10; + var morphTargets = geometry.morphTargets; - this.aspect = aspect !== undefined ? aspect : 1; - this.view = null; + if ( morphTargets !== undefined && morphTargets.length > 0 ) { - this.filmGauge = 35; // width of the film (default in millimeters) - this.filmOffset = 0; // horizontal film offset (same unit as gauge) + this.morphTargetInfluences = []; + this.morphTargetDictionary = {}; - this.updateProjectionMatrix(); + for ( m = 0, ml = morphTargets.length; m < ml; m ++ ) { - } + name = morphTargets[ m ].name || String( m ); - PerspectiveCamera.prototype = Object.assign( Object.create( Camera.prototype ), { + this.morphTargetInfluences.push( 0 ); + this.morphTargetDictionary[ name ] = m; - constructor: PerspectiveCamera, + } - isPerspectiveCamera: true, + } - copy: function ( source ) { + } - Camera.prototype.copy.call( this, source ); + }, - this.fov = source.fov; - this.zoom = source.zoom; + raycast: ( function () { - this.near = source.near; - this.far = source.far; - this.focus = source.focus; + var inverseMatrix = new Matrix4(); + var ray = new Ray(); + var sphere = new Sphere(); - this.aspect = source.aspect; - this.view = source.view === null ? null : Object.assign( {}, source.view ); + var vA = new Vector3(); + var vB = new Vector3(); + var vC = new Vector3(); - this.filmGauge = source.filmGauge; - this.filmOffset = source.filmOffset; + var tempA = new Vector3(); + var tempB = new Vector3(); + var tempC = new Vector3(); - return this; + var uvA = new Vector2(); + var uvB = new Vector2(); + var uvC = new Vector2(); - }, + var barycoord = new Vector3(); - /** - * 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 ) { + var intersectionPoint = new Vector3(); + var intersectionPointWorld = new Vector3(); - // see http://www.bobatkins.com/photography/technical/field_of_view.html - var vExtentSlope = 0.5 * this.getFilmHeight() / focalLength; + function uvIntersection( point, p1, p2, p3, uv1, uv2, uv3 ) { - this.fov = _Math.RAD2DEG * 2 * Math.atan( vExtentSlope ); - this.updateProjectionMatrix(); + Triangle.barycoordFromPoint( point, p1, p2, p3, barycoord ); - }, + uv1.multiplyScalar( barycoord.x ); + uv2.multiplyScalar( barycoord.y ); + uv3.multiplyScalar( barycoord.z ); - /** - * Calculates the focal length from the current .fov and .filmGauge. - */ - getFocalLength: function () { + uv1.add( uv2 ).add( uv3 ); - var vExtentSlope = Math.tan( _Math.DEG2RAD * 0.5 * this.fov ); + return uv1.clone(); - return 0.5 * this.getFilmHeight() / vExtentSlope; + } - }, + function checkIntersection( object, material, raycaster, ray, pA, pB, pC, point ) { - getEffectiveFOV: function () { + var intersect; - return _Math.RAD2DEG * 2 * Math.atan( - Math.tan( _Math.DEG2RAD * 0.5 * this.fov ) / this.zoom ); + if ( material.side === BackSide ) { - }, + intersect = ray.intersectTriangle( pC, pB, pA, true, point ); - getFilmWidth: function () { + } else { - // film not completely covered in portrait format (aspect < 1) - return this.filmGauge * Math.min( this.aspect, 1 ); + intersect = ray.intersectTriangle( pA, pB, pC, material.side !== DoubleSide, point ); - }, + } - getFilmHeight: function () { + if ( intersect === null ) return null; - // film not completely covered in landscape format (aspect > 1) - return this.filmGauge / Math.max( this.aspect, 1 ); + intersectionPointWorld.copy( point ); + intersectionPointWorld.applyMatrix4( object.matrixWorld ); - }, + var distance = raycaster.ray.origin.distanceTo( intersectionPointWorld ); - /** - * 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.setOffset( fullWidth, fullHeight, w * 0, h * 0, w, h ); - * --B-- - * camera.setOffset( fullWidth, fullHeight, w * 1, h * 0, w, h ); - * --C-- - * camera.setOffset( fullWidth, fullHeight, w * 2, h * 0, w, h ); - * --D-- - * camera.setOffset( fullWidth, fullHeight, w * 0, h * 1, w, h ); - * --E-- - * camera.setOffset( fullWidth, fullHeight, w * 1, h * 1, w, h ); - * --F-- - * camera.setOffset( 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 ) { + if ( distance < raycaster.near || distance > raycaster.far ) return null; - this.aspect = fullWidth / fullHeight; + return { + distance: distance, + point: intersectionPointWorld.clone(), + object: object + }; - this.view = { - fullWidth: fullWidth, - fullHeight: fullHeight, - offsetX: x, - offsetY: y, - width: width, - height: height - }; + } - this.updateProjectionMatrix(); + function checkBufferGeometryIntersection( object, raycaster, ray, position, uv, a, b, c ) { - }, + vA.fromBufferAttribute( position, a ); + vB.fromBufferAttribute( position, b ); + vC.fromBufferAttribute( position, c ); - clearViewOffset: function () { + var intersection = checkIntersection( object, object.material, raycaster, ray, vA, vB, vC, intersectionPoint ); - this.view = null; - this.updateProjectionMatrix(); + if ( intersection ) { - }, + if ( uv ) { - updateProjectionMatrix: function () { + uvA.fromBufferAttribute( uv, a ); + uvB.fromBufferAttribute( uv, b ); + uvC.fromBufferAttribute( uv, c ); - 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; + intersection.uv = uvIntersection( intersectionPoint, vA, vB, vC, uvA, uvB, uvC ); - if ( view !== null ) { + } - var fullWidth = view.fullWidth, - fullHeight = view.fullHeight; + intersection.face = new Face3( a, b, c, Triangle.normal( vA, vB, vC ) ); + intersection.faceIndex = a; - left += view.offsetX * width / fullWidth; - top -= view.offsetY * height / fullHeight; - width *= view.width / fullWidth; - height *= view.height / fullHeight; + } + + return intersection; } - var skew = this.filmOffset; - if ( skew !== 0 ) left += near * skew / this.getFilmWidth(); + return function raycast( raycaster, intersects ) { - this.projectionMatrix.makePerspective( left, left + width, top, top - height, near, this.far ); + var geometry = this.geometry; + var material = this.material; + var matrixWorld = this.matrixWorld; - }, + if ( material === undefined ) return; - toJSON: function ( meta ) { + // Checking boundingSphere distance to ray - var data = Object3D.prototype.toJSON.call( this, meta ); + if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); - data.object.fov = this.fov; - data.object.zoom = this.zoom; + sphere.copy( geometry.boundingSphere ); + sphere.applyMatrix4( matrixWorld ); - data.object.near = this.near; - data.object.far = this.far; - data.object.focus = this.focus; + if ( raycaster.ray.intersectsSphere( sphere ) === false ) return; - data.object.aspect = this.aspect; + // - if ( this.view !== null ) data.object.view = Object.assign( {}, this.view ); + inverseMatrix.getInverse( matrixWorld ); + ray.copy( raycaster.ray ).applyMatrix4( inverseMatrix ); - data.object.filmGauge = this.filmGauge; - data.object.filmOffset = this.filmOffset; + // Check boundingBox before continuing - return data; + if ( geometry.boundingBox !== null ) { - } + if ( ray.intersectsBox( geometry.boundingBox ) === false ) return; - } ); + } - /** - * @author alteredq / http://alteredqualia.com/ - * @author arose / http://github.com/arose - */ + var intersection; - function OrthographicCamera( left, right, top, bottom, near, far ) { + if ( geometry.isBufferGeometry ) { - Camera.call( this ); + var a, b, c; + var index = geometry.index; + var position = geometry.attributes.position; + var uv = geometry.attributes.uv; + var i, l; - this.type = 'OrthographicCamera'; + if ( index !== null ) { - this.zoom = 1; - this.view = null; + // indexed buffer geometry - this.left = left; - this.right = right; - this.top = top; - this.bottom = bottom; + for ( i = 0, l = index.count; i < l; i += 3 ) { - this.near = ( near !== undefined ) ? near : 0.1; - this.far = ( far !== undefined ) ? far : 2000; + a = index.getX( i ); + b = index.getX( i + 1 ); + c = index.getX( i + 2 ); - this.updateProjectionMatrix(); + intersection = checkBufferGeometryIntersection( this, raycaster, ray, position, uv, a, b, c ); - } + if ( intersection ) { - OrthographicCamera.prototype = Object.assign( Object.create( Camera.prototype ), { + intersection.faceIndex = Math.floor( i / 3 ); // triangle number in indices buffer semantics + intersects.push( intersection ); - constructor: OrthographicCamera, + } - isOrthographicCamera: true, + } - copy: function ( source ) { + } else { - Camera.prototype.copy.call( this, source ); + // non-indexed buffer geometry - this.left = source.left; - this.right = source.right; - this.top = source.top; - this.bottom = source.bottom; - this.near = source.near; - this.far = source.far; + for ( i = 0, l = position.count; i < l; i += 3 ) { - this.zoom = source.zoom; - this.view = source.view === null ? null : Object.assign( {}, source.view ); + a = i; + b = i + 1; + c = i + 2; - return this; + intersection = checkBufferGeometryIntersection( this, raycaster, ray, position, uv, a, b, c ); - }, + if ( intersection ) { - setViewOffset: function( fullWidth, fullHeight, x, y, width, height ) { + intersection.index = a; // triangle number in positions buffer semantics + intersects.push( intersection ); - this.view = { - fullWidth: fullWidth, - fullHeight: fullHeight, - offsetX: x, - offsetY: y, - width: width, - height: height - }; + } - this.updateProjectionMatrix(); + } - }, + } - clearViewOffset: function() { + } else if ( geometry.isGeometry ) { - this.view = null; - this.updateProjectionMatrix(); + var fvA, fvB, fvC; + var isMultiMaterial = Array.isArray( material ); - }, + var vertices = geometry.vertices; + var faces = geometry.faces; + var uvs; - updateProjectionMatrix: function () { + var faceVertexUvs = geometry.faceVertexUvs[ 0 ]; + if ( faceVertexUvs.length > 0 ) uvs = faceVertexUvs; - var dx = ( this.right - this.left ) / ( 2 * this.zoom ); - var dy = ( this.top - this.bottom ) / ( 2 * this.zoom ); - var cx = ( this.right + this.left ) / 2; - var cy = ( this.top + this.bottom ) / 2; + for ( var f = 0, fl = faces.length; f < fl; f ++ ) { - var left = cx - dx; - var right = cx + dx; - var top = cy + dy; - var bottom = cy - dy; + var face = faces[ f ]; + var faceMaterial = isMultiMaterial ? material[ face.materialIndex ] : material; - if ( this.view !== null ) { + if ( faceMaterial === undefined ) continue; - var zoomW = this.zoom / ( this.view.width / this.view.fullWidth ); - var zoomH = this.zoom / ( this.view.height / this.view.fullHeight ); - var scaleW = ( this.right - this.left ) / this.view.width; - var scaleH = ( this.top - this.bottom ) / this.view.height; + fvA = vertices[ face.a ]; + fvB = vertices[ face.b ]; + fvC = vertices[ face.c ]; - left += scaleW * ( this.view.offsetX / zoomW ); - right = left + scaleW * ( this.view.width / zoomW ); - top -= scaleH * ( this.view.offsetY / zoomH ); - bottom = top - scaleH * ( this.view.height / zoomH ); + if ( faceMaterial.morphTargets === true ) { - } + var morphTargets = geometry.morphTargets; + var morphInfluences = this.morphTargetInfluences; - this.projectionMatrix.makeOrthographic( left, right, top, bottom, this.near, this.far ); + vA.set( 0, 0, 0 ); + vB.set( 0, 0, 0 ); + vC.set( 0, 0, 0 ); - }, + for ( var t = 0, tl = morphTargets.length; t < tl; t ++ ) { - toJSON: function ( meta ) { + var influence = morphInfluences[ t ]; - var data = Object3D.prototype.toJSON.call( this, meta ); + if ( influence === 0 ) continue; - data.object.zoom = this.zoom; - data.object.left = this.left; - data.object.right = this.right; - data.object.top = this.top; - data.object.bottom = this.bottom; - data.object.near = this.near; - data.object.far = this.far; + var targets = morphTargets[ t ].vertices; - if ( this.view !== null ) data.object.view = Object.assign( {}, this.view ); + vA.addScaledVector( tempA.subVectors( targets[ face.a ], fvA ), influence ); + vB.addScaledVector( tempB.subVectors( targets[ face.b ], fvB ), influence ); + vC.addScaledVector( tempC.subVectors( targets[ face.c ], fvC ), influence ); - return data; + } - } + vA.add( fvA ); + vB.add( fvB ); + vC.add( fvC ); - } ); + fvA = vA; + fvB = vB; + fvC = vC; - /** - * @author mrdoob / http://mrdoob.com/ - */ + } - function WebGLAttributes( gl ) { + intersection = checkIntersection( this, faceMaterial, raycaster, ray, fvA, fvB, fvC, intersectionPoint ); - var buffers = {}; + if ( intersection ) { - function createBuffer( attribute, bufferType ) { + if ( uvs && uvs[ f ] ) { - var array = attribute.array; - var usage = attribute.dynamic ? gl.DYNAMIC_DRAW : gl.STATIC_DRAW; + var uvs_f = uvs[ f ]; + uvA.copy( uvs_f[ 0 ] ); + uvB.copy( uvs_f[ 1 ] ); + uvC.copy( uvs_f[ 2 ] ); - var buffer = gl.createBuffer(); + intersection.uv = uvIntersection( intersectionPoint, fvA, fvB, fvC, uvA, uvB, uvC ); - gl.bindBuffer( bufferType, buffer ); - gl.bufferData( bufferType, array, usage ); + } - attribute.onUploadCallback(); + intersection.face = face; + intersection.faceIndex = f; + intersects.push( intersection ); - var type = gl.FLOAT; + } - if ( array instanceof Float32Array ) { + } - type = gl.FLOAT; + } - } else if ( array instanceof Float64Array ) { + }; - console.warn( 'THREE.WebGLAttributes: Unsupported data buffer format: Float64Array.' ); + }() ), - } else if ( array instanceof Uint16Array ) { + clone: function () { - type = gl.UNSIGNED_SHORT; + return new this.constructor( this.geometry, this.material ).copy( this ); - } else if ( array instanceof Int16Array ) { + } - type = gl.SHORT; + } ); - } else if ( array instanceof Uint32Array ) { + /** + * @author mrdoob / http://mrdoob.com/ + */ - type = gl.UNSIGNED_INT; + function WebGLBackground( renderer, state, geometries, premultipliedAlpha ) { - } else if ( array instanceof Int32Array ) { + var clearColor = new Color( 0x000000 ); + var clearAlpha = 0; - type = gl.INT; + var planeCamera, planeMesh; + var boxMesh; - } else if ( array instanceof Int8Array ) { + function render( renderList, scene, camera, forceClear ) { - type = gl.BYTE; + var background = scene.background; - } else if ( array instanceof Uint8Array ) { + if ( background === null ) { - type = gl.UNSIGNED_BYTE; + setClear( clearColor, clearAlpha ); - } + } else if ( background && background.isColor ) { - return { - buffer: buffer, - type: type, - bytesPerElement: array.BYTES_PER_ELEMENT, - version: attribute.version - }; + setClear( background, 1 ); + forceClear = true; - } + } - function updateBuffer( buffer, attribute, bufferType ) { + if ( renderer.autoClear || forceClear ) { - var array = attribute.array; - var updateRange = attribute.updateRange; + renderer.clear( renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil ); - gl.bindBuffer( bufferType, buffer ); + } - if ( attribute.dynamic === false ) { + if ( background && background.isCubeTexture ) { - gl.bufferData( bufferType, array, gl.STATIC_DRAW ); + if ( boxMesh === undefined ) { - } else if ( updateRange.count === - 1 ) { + boxMesh = new Mesh( + new BoxBufferGeometry( 1, 1, 1 ), + new ShaderMaterial( { + uniforms: ShaderLib.cube.uniforms, + vertexShader: ShaderLib.cube.vertexShader, + fragmentShader: ShaderLib.cube.fragmentShader, + side: BackSide, + depthTest: true, + depthWrite: false, + polygonOffset: true, + fog: false + } ) + ); - // Not using update ranges + boxMesh.geometry.removeAttribute( 'normal' ); + boxMesh.geometry.removeAttribute( 'uv' ); - gl.bufferSubData( bufferType, 0, array ); + boxMesh.onBeforeRender = function ( renderer, scene, camera ) { - } else if ( updateRange.count === 0 ) { + var scale = camera.far; - console.error( 'THREE.WebGLObjects.updateBuffer: dynamic THREE.BufferAttribute marked as needsUpdate but updateRange.count is 0, ensure you are using set methods or updating manually.' ); + this.matrixWorld.makeScale( scale, scale, scale ); + this.matrixWorld.copyPosition( camera.matrixWorld ); - } else { + this.material.polygonOffsetUnits = scale * 10; - gl.bufferSubData( bufferType, updateRange.offset * array.BYTES_PER_ELEMENT, - array.subarray( updateRange.offset, updateRange.offset + updateRange.count ) ); + }; - updateRange.count = 0; // reset range + geometries.update( boxMesh.geometry ); - } + } - } + boxMesh.material.uniforms.tCube.value = background; - // + renderList.push( boxMesh, boxMesh.geometry, boxMesh.material, 0, null ); - function get( attribute ) { + } else if ( background && background.isTexture ) { - if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data; + if ( planeCamera === undefined ) { - return buffers[ attribute.uuid ]; + planeCamera = new OrthographicCamera( - 1, 1, 1, - 1, 0, 1 ); - } + planeMesh = new Mesh( + new PlaneBufferGeometry( 2, 2 ), + new MeshBasicMaterial( { depthTest: false, depthWrite: false, fog: false } ) + ); - function remove( attribute ) { + geometries.update( planeMesh.geometry ); - var data = buffers[ attribute.uuid ]; + } - if ( data ) { + planeMesh.material.map = background; - gl.deleteBuffer( data.buffer ); + // TODO Push this to renderList - delete buffers[ attribute.uuid ]; + renderer.renderBufferDirect( planeCamera, null, planeMesh.geometry, planeMesh.material, planeMesh, null ); } } - function update( attribute, bufferType ) { + function setClear( color, alpha ) { - if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data; + state.buffers.color.setClear( color.r, color.g, color.b, alpha, premultipliedAlpha ); - var data = buffers[ attribute.uuid ]; + } - if ( data === undefined ) { + return { - buffers[ attribute.uuid ] = createBuffer( attribute, bufferType ); + getClearColor: function () { - } else if ( data.version < attribute.version ) { + return clearColor; - updateBuffer( data.buffer, attribute, bufferType ); + }, + setClearColor: function ( color, alpha ) { - data.version = attribute.version; + clearColor.set( color ); + clearAlpha = alpha !== undefined ? alpha : 1; + setClear( clearColor, clearAlpha ); - } + }, + getClearAlpha: function () { - } + return clearAlpha; - return { + }, + setClearAlpha: function ( alpha ) { - get: get, - remove: remove, - update: update + clearAlpha = alpha; + setClear( clearColor, clearAlpha ); + + }, + render: render }; @@ -16203,43 +16596,42 @@ function WebGLRenderList() { - var opaque = []; - var opaqueLastIndex = - 1; + var renderItems = []; + var renderItemsIndex = 0; + var opaque = []; var transparent = []; - var transparentLastIndex = - 1; function init() { - opaqueLastIndex = - 1; - transparentLastIndex = - 1; + renderItemsIndex = 0; + + opaque.length = 0; + transparent.length = 0; } function push( object, geometry, material, z, group ) { - var array, index; + var renderItem = renderItems[ renderItemsIndex ]; - // allocate the next position in the appropriate array + if ( renderItem === undefined ) { - if ( material.transparent ) { + renderItem = { + id: object.id, + object: object, + geometry: geometry, + material: material, + program: material.program, + renderOrder: object.renderOrder, + z: z, + group: group + }; - array = transparent; - index = ++ transparentLastIndex; + renderItems[ renderItemsIndex ] = renderItem; } else { - array = opaque; - index = ++ opaqueLastIndex; - - } - - // recycle existing render item or grow the array - - var renderItem = array[ index ]; - - if ( renderItem ) { - renderItem.id = object.id; renderItem.object = object; renderItem.geometry = geometry; @@ -16249,37 +16641,18 @@ renderItem.z = z; renderItem.group = group; - } else { - - renderItem = { - id: object.id, - object: object, - geometry: geometry, - material: material, - program: material.program, - renderOrder: object.renderOrder, - z: z, - group: group - }; - - // assert( index === array.length ); - array.push( renderItem ); - } - } - - function finish() { + ( material.transparent === true ? transparent : opaque ).push( renderItem ); - opaque.length = opaqueLastIndex + 1; - transparent.length = transparentLastIndex + 1; + renderItemsIndex ++; } function sort() { - opaque.sort( painterSortStable ); - transparent.sort( reversePainterSortStable ); + if ( opaque.length > 1 ) opaque.sort( painterSortStable ); + if ( transparent.length > 1 ) transparent.sort( reversePainterSortStable ); } @@ -16289,7 +16662,6 @@ init: init, push: push, - finish: finish, sort: sort }; @@ -16335,47 +16707,143 @@ * @author mrdoob / http://mrdoob.com/ */ - function WebGLIndexedBufferRenderer( gl, extensions, infoRender ) { + function absNumericalSort( a, b ) { - var mode; + return Math.abs( b[ 1 ] ) - Math.abs( a[ 1 ] ); - function setMode( value ) { + } - mode = value; + function WebGLMorphtargets( gl ) { - } + var influencesList = {}; + var morphInfluences = new Float32Array( 8 ); - var type, size; + function update( object, geometry, material, program ) { - function setIndex( index ) { + var objectInfluences = object.morphTargetInfluences; - if ( index.array instanceof Uint32Array && extensions.get( 'OES_element_index_uint' ) ) { + var length = objectInfluences.length; - type = gl.UNSIGNED_INT; - size = 4; + var influences = influencesList[ geometry.id ]; - } else if ( index.array instanceof Uint16Array ) { + if ( influences === undefined ) { - type = gl.UNSIGNED_SHORT; - size = 2; + // initialise list - } else { + influences = []; - type = gl.UNSIGNED_BYTE; - size = 1; + for ( var i = 0; i < length; i ++ ) { + + influences[ i ] = [ i, 0 ]; + + } + + influencesList[ geometry.id ] = influences; + + } + + var morphTargets = material.morphTargets && geometry.morphAttributes.position; + var morphNormals = material.morphNormals && geometry.morphAttributes.normal; + + // Remove current morphAttributes + + for ( var i = 0; i < length; i ++ ) { + + var influence = influences[ i ]; + + if ( influence[ 1 ] !== 0 ) { + + if ( morphTargets ) geometry.removeAttribute( 'morphTarget' + i ); + if ( morphNormals ) geometry.removeAttribute( 'morphNormal' + i ); + + } + + } + + // Collect influences + + for ( var i = 0; i < length; i ++ ) { + + var influence = influences[ i ]; + + influence[ 0 ] = i; + influence[ 1 ] = objectInfluences[ i ]; + + } + + influences.sort( absNumericalSort ); + + // Add morphAttributes + + for ( var i = 0; i < 8; i ++ ) { + + var influence = influences[ i ]; + + if ( influence ) { + + var index = influence[ 0 ]; + var value = influence[ 1 ]; + + if ( value ) { + + if ( morphTargets ) geometry.addAttribute( 'morphTarget' + i, morphTargets[ index ] ); + if ( morphNormals ) geometry.addAttribute( 'morphNormal' + i, morphNormals[ index ] ); + + morphInfluences[ i ] = value; + continue; + + } + + } + + morphInfluences[ i ] = 0; } + program.getUniforms().setValue( gl, 'morphTargetInfluences', morphInfluences ); + + } + + return { + + update: update + + } + + } + + /** + * @author mrdoob / http://mrdoob.com/ + */ + + function WebGLIndexedBufferRenderer( gl, extensions, infoRender ) { + + var mode; + + function setMode( value ) { + + mode = value; + + } + + var type, bytesPerElement; + + function setIndex( value ) { + + type = value.type; + bytesPerElement = value.bytesPerElement; + } function render( start, count ) { - gl.drawElements( mode, count, type, start * size ); + gl.drawElements( mode, count, type, start * bytesPerElement ); infoRender.calls ++; infoRender.vertices += count; if ( mode === gl.TRIANGLES ) infoRender.faces += count / 3; + else if ( mode === gl.POINTS ) infoRender.points += count; } @@ -16390,12 +16858,13 @@ } - extension.drawElementsInstancedANGLE( mode, count, type, start * size, geometry.maxInstancedCount ); + extension.drawElementsInstancedANGLE( mode, count, type, start * bytesPerElement, geometry.maxInstancedCount ); infoRender.calls ++; infoRender.vertices += count * geometry.maxInstancedCount; if ( mode === gl.TRIANGLES ) infoRender.faces += geometry.maxInstancedCount * count / 3; + else if ( mode === gl.POINTS ) infoRender.points += geometry.maxInstancedCount * count; } @@ -16430,6 +16899,7 @@ infoRender.vertices += count; if ( mode === gl.TRIANGLES ) infoRender.faces += count / 3; + else if ( mode === gl.POINTS ) infoRender.points += count; } @@ -16462,6 +16932,7 @@ infoRender.vertices += count * geometry.maxInstancedCount; if ( mode === gl.TRIANGLES ) infoRender.faces += geometry.maxInstancedCount * count / 3; + else if ( mode === gl.POINTS ) infoRender.points += geometry.maxInstancedCount * count; } @@ -16666,7 +17137,7 @@ * @author mrdoob / http://mrdoob.com/ */ - function WebGLLights() { + function UniformsCache() { var lights = {}; @@ -16723,7 +17194,9 @@ shadow: false, shadowBias: 0, shadowRadius: 1, - shadowMapSize: new Vector2() + shadowMapSize: new Vector2(), + shadowCameraNear: 1, + shadowCameraFar: 1000 }; break; @@ -16757,11 +17230,237 @@ } + function WebGLLights() { + + var cache = new UniformsCache(); + + var state = { + + hash: '', + + ambient: [ 0, 0, 0 ], + directional: [], + directionalShadowMap: [], + directionalShadowMatrix: [], + spot: [], + spotShadowMap: [], + spotShadowMatrix: [], + rectArea: [], + point: [], + pointShadowMap: [], + pointShadowMatrix: [], + hemi: [] + + }; + + var vector3 = new Vector3(); + var matrix4 = new Matrix4(); + var matrix42 = new Matrix4(); + + function setup( lights, shadows, camera ) { + + var r = 0, g = 0, b = 0; + + var directionalLength = 0; + var pointLength = 0; + var spotLength = 0; + var rectAreaLength = 0; + var hemiLength = 0; + + var viewMatrix = camera.matrixWorldInverse; + + for ( var i = 0, l = lights.length; i < l; i ++ ) { + + var light = lights[ i ]; + + var color = light.color; + var intensity = light.intensity; + var distance = light.distance; + + var shadowMap = ( light.shadow && light.shadow.map ) ? light.shadow.map.texture : null; + + if ( light.isAmbientLight ) { + + r += color.r * intensity; + g += color.g * intensity; + b += color.b * intensity; + + } else if ( light.isDirectionalLight ) { + + var uniforms = cache.get( light ); + + uniforms.color.copy( light.color ).multiplyScalar( light.intensity ); + uniforms.direction.setFromMatrixPosition( light.matrixWorld ); + vector3.setFromMatrixPosition( light.target.matrixWorld ); + uniforms.direction.sub( vector3 ); + uniforms.direction.transformDirection( viewMatrix ); + + uniforms.shadow = light.castShadow; + + if ( light.castShadow ) { + + var shadow = light.shadow; + + uniforms.shadowBias = shadow.bias; + uniforms.shadowRadius = shadow.radius; + uniforms.shadowMapSize = shadow.mapSize; + + } + + state.directionalShadowMap[ directionalLength ] = shadowMap; + state.directionalShadowMatrix[ directionalLength ] = light.shadow.matrix; + state.directional[ directionalLength ] = uniforms; + + directionalLength ++; + + } else if ( light.isSpotLight ) { + + var uniforms = cache.get( light ); + + uniforms.position.setFromMatrixPosition( light.matrixWorld ); + uniforms.position.applyMatrix4( viewMatrix ); + + uniforms.color.copy( color ).multiplyScalar( intensity ); + uniforms.distance = distance; + + uniforms.direction.setFromMatrixPosition( light.matrixWorld ); + vector3.setFromMatrixPosition( light.target.matrixWorld ); + uniforms.direction.sub( vector3 ); + uniforms.direction.transformDirection( viewMatrix ); + + uniforms.coneCos = Math.cos( light.angle ); + uniforms.penumbraCos = Math.cos( light.angle * ( 1 - light.penumbra ) ); + uniforms.decay = ( light.distance === 0 ) ? 0.0 : light.decay; + + uniforms.shadow = light.castShadow; + + if ( light.castShadow ) { + + var shadow = light.shadow; + + uniforms.shadowBias = shadow.bias; + uniforms.shadowRadius = shadow.radius; + uniforms.shadowMapSize = shadow.mapSize; + + } + + state.spotShadowMap[ spotLength ] = shadowMap; + state.spotShadowMatrix[ spotLength ] = light.shadow.matrix; + state.spot[ spotLength ] = uniforms; + + spotLength ++; + + } else if ( light.isRectAreaLight ) { + + var uniforms = cache.get( light ); + + // (a) intensity controls irradiance of entire light + uniforms.color + .copy( color ) + .multiplyScalar( intensity / ( light.width * light.height ) ); + + // (b) intensity controls the radiance per light area + // uniforms.color.copy( color ).multiplyScalar( intensity ); + + uniforms.position.setFromMatrixPosition( light.matrixWorld ); + uniforms.position.applyMatrix4( viewMatrix ); + + // extract local rotation of light to derive width/height half vectors + matrix42.identity(); + matrix4.copy( light.matrixWorld ); + matrix4.premultiply( viewMatrix ); + matrix42.extractRotation( matrix4 ); + + uniforms.halfWidth.set( light.width * 0.5, 0.0, 0.0 ); + uniforms.halfHeight.set( 0.0, light.height * 0.5, 0.0 ); + + uniforms.halfWidth.applyMatrix4( matrix42 ); + uniforms.halfHeight.applyMatrix4( matrix42 ); + + // TODO (abelnation): RectAreaLight distance? + // uniforms.distance = distance; + + state.rectArea[ rectAreaLength ] = uniforms; + + rectAreaLength ++; + + } else if ( light.isPointLight ) { + + var uniforms = cache.get( light ); + + uniforms.position.setFromMatrixPosition( light.matrixWorld ); + uniforms.position.applyMatrix4( viewMatrix ); + + uniforms.color.copy( light.color ).multiplyScalar( light.intensity ); + uniforms.distance = light.distance; + uniforms.decay = ( light.distance === 0 ) ? 0.0 : light.decay; + + uniforms.shadow = light.castShadow; + + if ( light.castShadow ) { + + var shadow = light.shadow; + + uniforms.shadowBias = shadow.bias; + uniforms.shadowRadius = shadow.radius; + uniforms.shadowMapSize = shadow.mapSize; + uniforms.shadowCameraNear = shadow.camera.near; + uniforms.shadowCameraFar = shadow.camera.far; + + } + + state.pointShadowMap[ pointLength ] = shadowMap; + state.pointShadowMatrix[ pointLength ] = light.shadow.matrix; + state.point[ pointLength ] = uniforms; + + pointLength ++; + + } else if ( light.isHemisphereLight ) { + + var uniforms = cache.get( light ); + + uniforms.direction.setFromMatrixPosition( light.matrixWorld ); + uniforms.direction.transformDirection( viewMatrix ); + uniforms.direction.normalize(); + + uniforms.skyColor.copy( light.color ).multiplyScalar( intensity ); + uniforms.groundColor.copy( light.groundColor ).multiplyScalar( intensity ); + + state.hemi[ hemiLength ] = uniforms; + + hemiLength ++; + + } + + } + + state.ambient[ 0 ] = r; + state.ambient[ 1 ] = g; + state.ambient[ 2 ] = b; + + state.directional.length = directionalLength; + state.spot.length = spotLength; + state.rectArea.length = rectAreaLength; + state.point.length = pointLength; + state.hemi.length = hemiLength; + + // TODO (sam-g-steel) why aren't we using join + state.hash = directionalLength + ',' + pointLength + ',' + spotLength + ',' + rectAreaLength + ',' + hemiLength + ',' + shadows.length; + + } + + return { + setup: setup, + state: state + } + + } + /** * @author mrdoob / http://mrdoob.com/ */ - function WebGLObjects( gl, geometries, infoRender ) { + function WebGLObjects( geometries, infoRender ) { var updateList = {}; @@ -17042,15 +17741,14 @@ } - function WebGLProgram( renderer, code, material, parameters ) { + function WebGLProgram( renderer, extensions, code, material, shader, parameters ) { var gl = renderer.context; - var extensions = material.extensions; var defines = material.defines; - var vertexShader = material.__webglShader.vertexShader; - var fragmentShader = material.__webglShader.fragmentShader; + var vertexShader = shader.vertexShader; + var fragmentShader = shader.fragmentShader; var shadowMapTypeDefine = 'SHADOWMAP_TYPE_BASIC'; @@ -17126,7 +17824,7 @@ // - var customExtensions = generateExtensions( extensions, parameters, renderer.extensions ); + var customExtensions = generateExtensions( material.extensions, parameters, extensions ); var customDefines = generateDefines( defines ); @@ -17162,7 +17860,7 @@ 'precision ' + parameters.precision + ' float;', 'precision ' + parameters.precision + ' int;', - '#define SHADER_NAME ' + material.__webglShader.name, + '#define SHADER_NAME ' + shader.name, customDefines, @@ -17207,7 +17905,7 @@ parameters.sizeAttenuation ? '#define USE_SIZEATTENUATION' : '', parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '', - parameters.logarithmicDepthBuffer && renderer.extensions.get( 'EXT_frag_depth' ) ? '#define USE_LOGDEPTHBUF_EXT' : '', + parameters.logarithmicDepthBuffer && extensions.get( 'EXT_frag_depth' ) ? '#define USE_LOGDEPTHBUF_EXT' : '', 'uniform mat4 modelMatrix;', 'uniform mat4 modelViewMatrix;', @@ -17269,7 +17967,7 @@ 'precision ' + parameters.precision + ' float;', 'precision ' + parameters.precision + ' int;', - '#define SHADER_NAME ' + material.__webglShader.name, + '#define SHADER_NAME ' + shader.name, customDefines, @@ -17314,9 +18012,9 @@ parameters.physicallyCorrectLights ? "#define PHYSICALLY_CORRECT_LIGHTS" : '', parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '', - parameters.logarithmicDepthBuffer && renderer.extensions.get( 'EXT_frag_depth' ) ? '#define USE_LOGDEPTHBUF_EXT' : '', + parameters.logarithmicDepthBuffer && extensions.get( 'EXT_frag_depth' ) ? '#define USE_LOGDEPTHBUF_EXT' : '', - parameters.envMap && renderer.extensions.get( 'EXT_shader_texture_lod' ) ? '#define TEXTURE_LOD_EXT' : '', + parameters.envMap && extensions.get( 'EXT_shader_texture_lod' ) ? '#define TEXTURE_LOD_EXT' : '', 'uniform mat4 viewMatrix;', 'uniform vec3 cameraPosition;', @@ -17443,12 +18141,11 @@ var cachedUniforms; - this.getUniforms = function() { + this.getUniforms = function () { if ( cachedUniforms === undefined ) { - cachedUniforms = - new WebGLUniforms( gl, program, renderer ); + cachedUniforms = new WebGLUniforms( gl, program, renderer ); } @@ -17460,7 +18157,7 @@ var cachedAttributes; - this.getAttributes = function() { + this.getAttributes = function () { if ( cachedAttributes === undefined ) { @@ -17523,12 +18220,13 @@ * @author mrdoob / http://mrdoob.com/ */ - function WebGLPrograms( renderer, capabilities ) { + function WebGLPrograms( renderer, extensions, capabilities ) { var programs = []; var shaderIDs = { MeshDepthMaterial: 'depth', + MeshDistanceMaterial: 'distanceRGBA', MeshNormalMaterial: 'normal', MeshBasicMaterial: 'basic', MeshLambertMaterial: 'lambert', @@ -17538,7 +18236,8 @@ MeshPhysicalMaterial: 'physical', LineBasicMaterial: 'basic', LineDashedMaterial: 'dashed', - PointsMaterial: 'points' + PointsMaterial: 'points', + ShadowMaterial: 'shadow' }; var parameterNames = [ @@ -17621,7 +18320,7 @@ } - this.getParameters = function ( material, lights, fog, nClipPlanes, nClipIntersection, object ) { + this.getParameters = function ( material, lights, shadows, fog, nClipPlanes, nClipIntersection, object ) { var shaderID = shaderIDs[ material.type ]; @@ -17629,7 +18328,7 @@ // (not to blow over maxLights budget) var maxBones = object.isSkinnedMesh ? allocateBones( object ) : 0; - var precision = renderer.getPrecision(); + var precision = capabilities.precision; if ( material.precision !== null ) { @@ -17680,7 +18379,7 @@ useFog: material.fog, fogExp: ( fog && fog.isFogExp2 ), - flatShading: material.shading === FlatShading, + flatShading: material.flatShading, sizeAttenuation: material.sizeAttenuation, logarithmicDepthBuffer: capabilities.logarithmicDepthBuffer, @@ -17705,7 +18404,7 @@ dithering: material.dithering, - shadowMapEnabled: renderer.shadowMap.enabled && object.receiveShadow && lights.shadows.length > 0, + shadowMapEnabled: renderer.shadowMap.enabled && object.receiveShadow && shadows.length > 0, shadowMapType: renderer.shadowMap.type, toneMapping: renderer.toneMapping, @@ -17757,13 +18456,15 @@ } + array.push( material.onBeforeCompile.toString() ); + array.push( renderer.gammaOutput ); return array.join(); }; - this.acquireProgram = function ( material, parameters, code ) { + this.acquireProgram = function ( material, shader, parameters, code ) { var program; @@ -17785,7 +18486,7 @@ if ( program === undefined ) { - program = new WebGLProgram( renderer, code, material, parameters ); + program = new WebGLProgram( renderer, extensions, code, material, shader, parameters ); programs.push( program ); } @@ -17819,7 +18520,7 @@ * @author mrdoob / http://mrdoob.com/ */ - function WebGLTextures( _gl, extensions, state, properties, capabilities, paramThreeToGL, infoMemory ) { + function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, infoMemory ) { var _isWebGL2 = ( typeof WebGL2RenderingContext !== 'undefined' && _gl instanceof WebGL2RenderingContext ); @@ -17885,6 +18586,13 @@ } + function textureNeedsGenerateMipmaps( texture, isPowerOfTwo ) { + + return texture.generateMipmaps && isPowerOfTwo && + texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter; + + } + // Fallback filters for non-power-of-2 textures function filterFallback( f ) { @@ -18071,8 +18779,8 @@ var image = cubeImage[ 0 ], isPowerOfTwoImage = isPowerOfTwo( image ), - glFormat = paramThreeToGL( texture.format ), - glType = paramThreeToGL( texture.type ); + glFormat = utils.convert( texture.format ), + glType = utils.convert( texture.type ); setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture, isPowerOfTwoImage ); @@ -18106,7 +18814,7 @@ } else { - console.warn( "THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()" ); + console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()' ); } @@ -18122,7 +18830,7 @@ } - if ( texture.generateMipmaps && isPowerOfTwoImage ) { + if ( textureNeedsGenerateMipmaps( texture, isPowerOfTwoImage ) ) { _gl.generateMipmap( _gl.TEXTURE_CUBE_MAP ); @@ -18156,11 +18864,11 @@ if ( isPowerOfTwoImage ) { - _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, paramThreeToGL( texture.wrapS ) ); - _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, paramThreeToGL( texture.wrapT ) ); + _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, utils.convert( texture.wrapS ) ); + _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, utils.convert( texture.wrapT ) ); - _gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, paramThreeToGL( texture.magFilter ) ); - _gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, paramThreeToGL( texture.minFilter ) ); + _gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, utils.convert( texture.magFilter ) ); + _gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, utils.convert( texture.minFilter ) ); } else { @@ -18232,8 +18940,8 @@ } var isPowerOfTwoImage = isPowerOfTwo( image ), - glFormat = paramThreeToGL( texture.format ), - glType = paramThreeToGL( texture.type ); + glFormat = utils.convert( texture.format ), + glType = utils.convert( texture.type ); setTextureParameters( _gl.TEXTURE_2D, texture, isPowerOfTwoImage ); @@ -18267,7 +18975,7 @@ console.warn( 'THREE.WebGLRenderer: Use UnsignedShortType or UnsignedIntType for DepthFormat DepthTexture.' ); texture.type = UnsignedShortType; - glType = paramThreeToGL( texture.type ); + glType = utils.convert( texture.type ); } @@ -18284,10 +18992,10 @@ // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/) if ( texture.type !== UnsignedInt248Type ) { - console.warn( 'THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture.' ); + console.warn( 'THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture.' ); texture.type = UnsignedInt248Type; - glType = paramThreeToGL( texture.type ); + glType = utils.convert( texture.type ); } @@ -18332,7 +19040,7 @@ } else { - console.warn( "THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()" ); + console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()' ); } @@ -18371,7 +19079,7 @@ } - if ( texture.generateMipmaps && isPowerOfTwoImage ) _gl.generateMipmap( _gl.TEXTURE_2D ); + if ( textureNeedsGenerateMipmaps( texture, isPowerOfTwoImage ) ) _gl.generateMipmap( _gl.TEXTURE_2D ); textureProperties.__version = texture.version; @@ -18384,8 +19092,8 @@ // Setup storage for target texture and bind it to correct framebuffer function setupFrameBufferTexture( framebuffer, renderTarget, attachment, textureTarget ) { - var glFormat = paramThreeToGL( renderTarget.texture.format ); - var glType = paramThreeToGL( renderTarget.texture.type ); + var glFormat = utils.convert( renderTarget.texture.format ); + var glType = utils.convert( renderTarget.texture.type ); state.texImage2D( textureTarget, 0, glFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null ); _gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); _gl.framebufferTexture2D( _gl.FRAMEBUFFER, attachment, textureTarget, properties.get( renderTarget.texture ).__webglTexture, 0 ); @@ -18423,13 +19131,13 @@ function setupDepthTexture( framebuffer, renderTarget ) { var isCube = ( renderTarget && renderTarget.isWebGLRenderTargetCube ); - if ( isCube ) throw new Error('Depth Texture with cube render targets is not supported!'); + if ( isCube ) throw new Error( 'Depth Texture with cube render targets is not supported' ); _gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); if ( !( renderTarget.depthTexture && renderTarget.depthTexture.isDepthTexture ) ) { - throw new Error('renderTarget.depthTexture must be an instance of THREE.DepthTexture'); + throw new Error( 'renderTarget.depthTexture must be an instance of THREE.DepthTexture' ); } @@ -18456,7 +19164,7 @@ } else { - throw new Error('Unknown depthTexture format') + throw new Error( 'Unknown depthTexture format' ); } @@ -18471,7 +19179,7 @@ if ( renderTarget.depthTexture ) { - if ( isCube ) throw new Error('target.depthTexture not supported in Cube render targets'); + if ( isCube ) throw new Error( 'target.depthTexture not supported in Cube render targets' ); setupDepthTexture( renderTargetProperties.__webglFramebuffer, renderTarget ); @@ -18549,7 +19257,7 @@ } - if ( renderTarget.texture.generateMipmaps && isTargetPowerOfTwo ) _gl.generateMipmap( _gl.TEXTURE_CUBE_MAP ); + if ( textureNeedsGenerateMipmaps( renderTarget.texture, isTargetPowerOfTwo ) ) _gl.generateMipmap( _gl.TEXTURE_CUBE_MAP ); state.bindTexture( _gl.TEXTURE_CUBE_MAP, null ); } else { @@ -18558,7 +19266,7 @@ setTextureParameters( _gl.TEXTURE_2D, renderTarget.texture, isTargetPowerOfTwo ); setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D ); - if ( renderTarget.texture.generateMipmaps && isTargetPowerOfTwo ) _gl.generateMipmap( _gl.TEXTURE_2D ); + if ( textureNeedsGenerateMipmaps( renderTarget.texture, isTargetPowerOfTwo ) ) _gl.generateMipmap( _gl.TEXTURE_2D ); state.bindTexture( _gl.TEXTURE_2D, null ); } @@ -18576,12 +19284,11 @@ function updateRenderTargetMipmap( renderTarget ) { var texture = renderTarget.texture; + var isTargetPowerOfTwo = isPowerOfTwo( renderTarget ); - if ( texture.generateMipmaps && isPowerOfTwo( renderTarget ) && - texture.minFilter !== NearestFilter && - texture.minFilter !== LinearFilter ) { + if ( textureNeedsGenerateMipmaps( texture, isTargetPowerOfTwo ) ) { - var target = (renderTarget && renderTarget.isWebGLRenderTargetCube) ? _gl.TEXTURE_CUBE_MAP : _gl.TEXTURE_2D; + var target = renderTarget.isWebGLRenderTargetCube ? _gl.TEXTURE_CUBE_MAP : _gl.TEXTURE_2D; var webglTexture = properties.get( texture ).__webglTexture; state.bindTexture( target, webglTexture ); @@ -18648,7 +19355,7 @@ * @author mrdoob / http://mrdoob.com/ */ - function WebGLState( gl, extensions, paramThreeToGL ) { + function WebGLState( gl, extensions, utils ) { function ColorBuffer() { @@ -18656,7 +19363,7 @@ var color = new Vector4(); var currentColorMask = null; - var currentColorClear = new Vector4(); + var currentColorClear = new Vector4( 0, 0, 0, 0 ); return { @@ -18701,7 +19408,7 @@ locked = false; currentColorMask = null; - currentColorClear.set( 0, 0, 0, 1 ); + currentColorClear.set( - 1, 0, 0, 0 ); // set to invalid state } @@ -18964,6 +19671,8 @@ var compressedTextureFormats = null; + var currentProgram = null; + var currentBlending = null; var currentBlendEquation = null; var currentBlendSrc = null; @@ -18981,8 +19690,6 @@ var currentPolygonOffsetFactor = null; var currentPolygonOffsetUnits = null; - var currentScissorTest = null; - var maxTextures = gl.getParameter( gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS ); var version = parseFloat( /^WebGL\ ([0-9])/.exec( gl.getParameter( gl.VERSION ) )[ 1 ] ); @@ -19017,25 +19724,23 @@ emptyTextures[ gl.TEXTURE_2D ] = createTexture( gl.TEXTURE_2D, gl.TEXTURE_2D, 1 ); emptyTextures[ gl.TEXTURE_CUBE_MAP ] = createTexture( gl.TEXTURE_CUBE_MAP, gl.TEXTURE_CUBE_MAP_POSITIVE_X, 6 ); - // - - function init() { + // init - colorBuffer.setClear( 0, 0, 0, 1 ); - depthBuffer.setClear( 1 ); - stencilBuffer.setClear( 0 ); + colorBuffer.setClear( 0, 0, 0, 1 ); + depthBuffer.setClear( 1 ); + stencilBuffer.setClear( 0 ); - enable( gl.DEPTH_TEST ); - depthBuffer.setFunc( LessEqualDepth ); + enable( gl.DEPTH_TEST ); + depthBuffer.setFunc( LessEqualDepth ); - setFlipSided( false ); - setCullFace( CullFaceBack ); - enable( gl.CULL_FACE ); + setFlipSided( false ); + setCullFace( CullFaceBack ); + enable( gl.CULL_FACE ); - enable( gl.BLEND ); - setBlending( NormalBlending ); + enable( gl.BLEND ); + setBlending( NormalBlending ); - } + // function initAttributes() { @@ -19154,6 +19859,22 @@ } + function useProgram( program ) { + + if ( currentProgram !== program ) { + + gl.useProgram( program ); + + currentProgram = program; + + return true; + + } + + return false; + + } + function setBlending( blending, blendEquation, blendSrc, blendDst, blendEquationAlpha, blendSrcAlpha, blendDstAlpha, premultipliedAlpha ) { if ( blending !== NoBlending ) { @@ -19166,72 +19887,83 @@ } - if ( ( blending !== CustomBlending ) && ( blending !== currentBlending || premultipliedAlpha !== currentPremultipledAlpha ) ) { + if ( blending !== CustomBlending ) { - if ( blending === AdditiveBlending ) { + if ( blending !== currentBlending || premultipliedAlpha !== currentPremultipledAlpha ) { - if ( premultipliedAlpha ) { + switch ( blending ) { - gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD ); - gl.blendFuncSeparate( gl.ONE, gl.ONE, gl.ONE, gl.ONE ); + case AdditiveBlending: - } else { + if ( premultipliedAlpha ) { - gl.blendEquation( gl.FUNC_ADD ); - gl.blendFunc( gl.SRC_ALPHA, gl.ONE ); + gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD ); + gl.blendFuncSeparate( gl.ONE, gl.ONE, gl.ONE, gl.ONE ); - } + } else { - } else if ( blending === SubtractiveBlending ) { + gl.blendEquation( gl.FUNC_ADD ); + gl.blendFunc( gl.SRC_ALPHA, gl.ONE ); - if ( premultipliedAlpha ) { + } + break; - gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD ); - gl.blendFuncSeparate( gl.ZERO, gl.ZERO, gl.ONE_MINUS_SRC_COLOR, gl.ONE_MINUS_SRC_ALPHA ); + case SubtractiveBlending: - } else { + if ( premultipliedAlpha ) { - gl.blendEquation( gl.FUNC_ADD ); - gl.blendFunc( gl.ZERO, gl.ONE_MINUS_SRC_COLOR ); + gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD ); + gl.blendFuncSeparate( gl.ZERO, gl.ZERO, gl.ONE_MINUS_SRC_COLOR, gl.ONE_MINUS_SRC_ALPHA ); - } + } else { - } else if ( blending === MultiplyBlending ) { + gl.blendEquation( gl.FUNC_ADD ); + gl.blendFunc( gl.ZERO, gl.ONE_MINUS_SRC_COLOR ); - if ( premultipliedAlpha ) { + } + break; - gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD ); - gl.blendFuncSeparate( gl.ZERO, gl.SRC_COLOR, gl.ZERO, gl.SRC_ALPHA ); + case MultiplyBlending: - } else { + if ( premultipliedAlpha ) { - gl.blendEquation( gl.FUNC_ADD ); - gl.blendFunc( gl.ZERO, gl.SRC_COLOR ); + gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD ); + gl.blendFuncSeparate( gl.ZERO, gl.SRC_COLOR, gl.ZERO, gl.SRC_ALPHA ); - } + } else { - } else { + gl.blendEquation( gl.FUNC_ADD ); + gl.blendFunc( gl.ZERO, gl.SRC_COLOR ); + + } + break; - if ( premultipliedAlpha ) { + default: - gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD ); - gl.blendFuncSeparate( gl.ONE, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA ); + if ( premultipliedAlpha ) { - } else { + gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD ); + gl.blendFuncSeparate( gl.ONE, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA ); - gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD ); - gl.blendFuncSeparate( gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA ); + } else { + + gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD ); + gl.blendFuncSeparate( gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA ); + + } } } - currentBlending = blending; - currentPremultipledAlpha = premultipliedAlpha; - - } + currentBlendEquation = null; + currentBlendSrc = null; + currentBlendDst = null; + currentBlendEquationAlpha = null; + currentBlendSrcAlpha = null; + currentBlendDstAlpha = null; - if ( blending === CustomBlending ) { + } else { blendEquationAlpha = blendEquationAlpha || blendEquation; blendSrcAlpha = blendSrcAlpha || blendSrc; @@ -19239,7 +19971,7 @@ if ( blendEquation !== currentBlendEquation || blendEquationAlpha !== currentBlendEquationAlpha ) { - gl.blendEquationSeparate( paramThreeToGL( blendEquation ), paramThreeToGL( blendEquationAlpha ) ); + gl.blendEquationSeparate( utils.convert( blendEquation ), utils.convert( blendEquationAlpha ) ); currentBlendEquation = blendEquation; currentBlendEquationAlpha = blendEquationAlpha; @@ -19248,7 +19980,7 @@ if ( blendSrc !== currentBlendSrc || blendDst !== currentBlendDst || blendSrcAlpha !== currentBlendSrcAlpha || blendDstAlpha !== currentBlendDstAlpha ) { - gl.blendFuncSeparate( paramThreeToGL( blendSrc ), paramThreeToGL( blendDst ), paramThreeToGL( blendSrcAlpha ), paramThreeToGL( blendDstAlpha ) ); + gl.blendFuncSeparate( utils.convert( blendSrc ), utils.convert( blendDst ), utils.convert( blendSrcAlpha ), utils.convert( blendDstAlpha ) ); currentBlendSrc = blendSrc; currentBlendDst = blendDst; @@ -19257,17 +19989,11 @@ } - } else { - - currentBlendEquation = null; - currentBlendSrc = null; - currentBlendDst = null; - currentBlendEquationAlpha = null; - currentBlendSrcAlpha = null; - currentBlendDstAlpha = null; - } + currentBlending = blending; + currentPremultipledAlpha = premultipliedAlpha; + } function setMaterial( material ) { @@ -19382,16 +20108,8 @@ } - function getScissorTest() { - - return currentScissorTest; - - } - function setScissorTest( scissorTest ) { - currentScissorTest = scissorTest; - if ( scissorTest ) { enable( gl.SCISSOR_TEST ); @@ -19521,6 +20239,8 @@ currentTextureSlot = null; currentBoundTextures = {}; + currentProgram = null; + currentBlending = null; currentFlipSided = null; @@ -19540,7 +20260,6 @@ stencil: stencilBuffer }, - init: init, initAttributes: initAttributes, enableAttribute: enableAttribute, enableAttributeAndDivisor: enableAttributeAndDivisor, @@ -19549,6 +20268,8 @@ disable: disable, getCompressedTextureFormats: getCompressedTextureFormats, + useProgram: useProgram, + setBlending: setBlending, setMaterial: setMaterial, @@ -19558,7 +20279,6 @@ setLineWidth: setLineWidth, setPolygonOffset: setPolygonOffset, - getScissorTest: getScissorTest, setScissorTest: setScissorTest, activeTexture: activeTexture, @@ -19643,7 +20363,7 @@ } - var logarithmicDepthBuffer = parameters.logarithmicDepthBuffer === true && !! extensions.get( 'EXT_frag_depth' ); + var logarithmicDepthBuffer = parameters.logarithmicDepthBuffer === true; var maxTextures = gl.getParameter( gl.MAX_TEXTURE_IMAGE_UNITS ); var maxVertexTextures = gl.getParameter( gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS ); @@ -19685,6 +20405,240 @@ } + /** + * @author mrdoob / http://mrdoob.com/ + */ + + function ArrayCamera( array ) { + + PerspectiveCamera.call( this ); + + this.cameras = array || []; + + } + + ArrayCamera.prototype = Object.assign( Object.create( PerspectiveCamera.prototype ), { + + constructor: ArrayCamera, + + isArrayCamera: true + + } ); + + /** + * @author mrdoob / http://mrdoob.com/ + */ + + function WebVRManager( renderer ) { + + var scope = this; + + var device = null; + var frameData = null; + + if ( 'VRFrameData' in window ) { + + frameData = new window.VRFrameData(); + + } + + var matrixWorldInverse = new Matrix4(); + + var standingMatrix = new Matrix4(); + var standingMatrixInverse = new Matrix4(); + + var cameraL = new PerspectiveCamera(); + cameraL.bounds = new Vector4( 0.0, 0.0, 0.5, 1.0 ); + cameraL.layers.enable( 1 ); + + var cameraR = new PerspectiveCamera(); + cameraR.bounds = new Vector4( 0.5, 0.0, 0.5, 1.0 ); + cameraR.layers.enable( 2 ); + + var cameraVR = new ArrayCamera( [ cameraL, cameraR ] ); + cameraVR.layers.enable( 1 ); + cameraVR.layers.enable( 2 ); + + // + + var currentSize, currentPixelRatio; + + function onVRDisplayPresentChange() { + + if ( device !== null && device.isPresenting ) { + + var eyeParameters = device.getEyeParameters( 'left' ); + var renderWidth = eyeParameters.renderWidth; + var renderHeight = eyeParameters.renderHeight; + + currentPixelRatio = renderer.getPixelRatio(); + currentSize = renderer.getSize(); + + renderer.setDrawingBufferSize( renderWidth * 2, renderHeight, 1 ); + + } else if ( scope.enabled ) { + + renderer.setDrawingBufferSize( currentSize.width, currentSize.height, currentPixelRatio ); + + } + + } + + window.addEventListener( 'vrdisplaypresentchange', onVRDisplayPresentChange, false ); + + // + + this.enabled = false; + this.standing = false; + + this.getDevice = function () { + + return device; + + }; + + this.setDevice = function ( value ) { + + if ( value !== undefined ) device = value; + + }; + + this.getCamera = function ( camera ) { + + if ( device === null ) return camera; + + device.depthNear = camera.near; + device.depthFar = camera.far; + + device.getFrameData( frameData ); + + // + + var pose = frameData.pose; + + if ( pose.position !== null ) { + + camera.position.fromArray( pose.position ); + + } else { + + camera.position.set( 0, 0, 0 ); + + } + + if ( pose.orientation !== null ) { + + camera.quaternion.fromArray( pose.orientation ); + + } + + camera.updateMatrixWorld(); + + var stageParameters = device.stageParameters; + + if ( this.standing && stageParameters ) { + + standingMatrix.fromArray( stageParameters.sittingToStandingTransform ); + standingMatrixInverse.getInverse( standingMatrix ); + + camera.matrixWorld.multiply( standingMatrix ); + camera.matrixWorldInverse.multiply( standingMatrixInverse ); + + } + + if ( device.isPresenting === false ) return camera; + + // + + cameraL.near = camera.near; + cameraR.near = camera.near; + + cameraL.far = camera.far; + cameraR.far = camera.far; + + cameraVR.matrixWorld.copy( camera.matrixWorld ); + cameraVR.matrixWorldInverse.copy( camera.matrixWorldInverse ); + + cameraL.matrixWorldInverse.fromArray( frameData.leftViewMatrix ); + cameraR.matrixWorldInverse.fromArray( frameData.rightViewMatrix ); + + if ( this.standing && stageParameters ) { + + cameraL.matrixWorldInverse.multiply( standingMatrixInverse ); + cameraR.matrixWorldInverse.multiply( standingMatrixInverse ); + + } + + var parent = camera.parent; + + if ( parent !== null ) { + + matrixWorldInverse.getInverse( parent.matrixWorld ); + + cameraL.matrixWorldInverse.multiply( matrixWorldInverse ); + cameraR.matrixWorldInverse.multiply( matrixWorldInverse ); + + } + + // envMap and Mirror needs camera.matrixWorld + + cameraL.matrixWorld.getInverse( cameraL.matrixWorldInverse ); + cameraR.matrixWorld.getInverse( cameraR.matrixWorldInverse ); + + cameraL.projectionMatrix.fromArray( frameData.leftProjectionMatrix ); + cameraR.projectionMatrix.fromArray( frameData.rightProjectionMatrix ); + + // HACK @mrdoob + // https://github.com/w3c/webvr/issues/203 + + cameraVR.projectionMatrix.copy( cameraL.projectionMatrix ); + + // + + var layers = device.getLayers(); + + if ( layers.length ) { + + var layer = layers[ 0 ]; + + if ( layer.leftBounds !== null && layer.leftBounds.length === 4 ) { + + cameraL.bounds.fromArray( layer.leftBounds ); + + } + + if ( layer.rightBounds !== null && layer.rightBounds.length === 4 ) { + + cameraR.bounds.fromArray( layer.rightBounds ); + + } + + } + + return cameraVR; + + }; + + this.getStandingMatrix = function () { + + return standingMatrix; + + }; + + this.submitFrame = function () { + + if ( device && device.isPresenting ) device.submitFrame(); + + }; + + this.dispose = function() { + + window.removeEventListener( 'vrdisplaypresentchange', onVRDisplayPresentChange ); + + }; + + } + /** * @author mrdoob / http://mrdoob.com/ */ @@ -19908,7 +20862,142 @@ } - // import { Sphere } from '../math/Sphere'; + /** + * @author thespite / http://www.twitter.com/thespite + */ + + function WebGLUtils ( gl, extensions ) { + + function convert ( p ) { + + var extension; + + if ( p === RepeatWrapping ) return gl.REPEAT; + if ( p === ClampToEdgeWrapping ) return gl.CLAMP_TO_EDGE; + if ( p === MirroredRepeatWrapping ) return gl.MIRRORED_REPEAT; + + if ( p === NearestFilter ) return gl.NEAREST; + if ( p === NearestMipMapNearestFilter ) return gl.NEAREST_MIPMAP_NEAREST; + if ( p === NearestMipMapLinearFilter ) return gl.NEAREST_MIPMAP_LINEAR; + + if ( p === LinearFilter ) return gl.LINEAR; + if ( p === LinearMipMapNearestFilter ) return gl.LINEAR_MIPMAP_NEAREST; + if ( p === LinearMipMapLinearFilter ) return gl.LINEAR_MIPMAP_LINEAR; + + if ( p === UnsignedByteType ) return gl.UNSIGNED_BYTE; + if ( p === UnsignedShort4444Type ) return gl.UNSIGNED_SHORT_4_4_4_4; + if ( p === UnsignedShort5551Type ) return gl.UNSIGNED_SHORT_5_5_5_1; + if ( p === UnsignedShort565Type ) return gl.UNSIGNED_SHORT_5_6_5; + + if ( p === ByteType ) return gl.BYTE; + if ( p === ShortType ) return gl.SHORT; + if ( p === UnsignedShortType ) return gl.UNSIGNED_SHORT; + if ( p === IntType ) return gl.INT; + if ( p === UnsignedIntType ) return gl.UNSIGNED_INT; + if ( p === FloatType ) return gl.FLOAT; + + if ( p === HalfFloatType ) { + + extension = extensions.get( 'OES_texture_half_float' ); + + if ( extension !== null ) return extension.HALF_FLOAT_OES; + + } + + if ( p === AlphaFormat ) return gl.ALPHA; + if ( p === RGBFormat ) return gl.RGB; + if ( p === RGBAFormat ) return gl.RGBA; + if ( p === LuminanceFormat ) return gl.LUMINANCE; + if ( p === LuminanceAlphaFormat ) return gl.LUMINANCE_ALPHA; + if ( p === DepthFormat ) return gl.DEPTH_COMPONENT; + if ( p === DepthStencilFormat ) return gl.DEPTH_STENCIL; + + if ( p === AddEquation ) return gl.FUNC_ADD; + if ( p === SubtractEquation ) return gl.FUNC_SUBTRACT; + if ( p === ReverseSubtractEquation ) return gl.FUNC_REVERSE_SUBTRACT; + + if ( p === ZeroFactor ) return gl.ZERO; + if ( p === OneFactor ) return gl.ONE; + if ( p === SrcColorFactor ) return gl.SRC_COLOR; + if ( p === OneMinusSrcColorFactor ) return gl.ONE_MINUS_SRC_COLOR; + if ( p === SrcAlphaFactor ) return gl.SRC_ALPHA; + if ( p === OneMinusSrcAlphaFactor ) return gl.ONE_MINUS_SRC_ALPHA; + if ( p === DstAlphaFactor ) return gl.DST_ALPHA; + if ( p === OneMinusDstAlphaFactor ) return gl.ONE_MINUS_DST_ALPHA; + + if ( p === DstColorFactor ) return gl.DST_COLOR; + if ( p === OneMinusDstColorFactor ) return gl.ONE_MINUS_DST_COLOR; + if ( p === SrcAlphaSaturateFactor ) return gl.SRC_ALPHA_SATURATE; + + if ( p === RGB_S3TC_DXT1_Format || p === RGBA_S3TC_DXT1_Format || + p === RGBA_S3TC_DXT3_Format || p === RGBA_S3TC_DXT5_Format ) { + + extension = extensions.get( 'WEBGL_compressed_texture_s3tc' ); + + if ( extension !== null ) { + + if ( p === RGB_S3TC_DXT1_Format ) return extension.COMPRESSED_RGB_S3TC_DXT1_EXT; + if ( p === RGBA_S3TC_DXT1_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT1_EXT; + if ( p === RGBA_S3TC_DXT3_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT3_EXT; + if ( p === RGBA_S3TC_DXT5_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT5_EXT; + + } + + } + + if ( p === RGB_PVRTC_4BPPV1_Format || p === RGB_PVRTC_2BPPV1_Format || + p === RGBA_PVRTC_4BPPV1_Format || p === RGBA_PVRTC_2BPPV1_Format ) { + + extension = extensions.get( 'WEBGL_compressed_texture_pvrtc' ); + + if ( extension !== null ) { + + if ( p === RGB_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_4BPPV1_IMG; + if ( p === RGB_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_2BPPV1_IMG; + if ( p === RGBA_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG; + if ( p === RGBA_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG; + + } + + } + + if ( p === RGB_ETC1_Format ) { + + extension = extensions.get( 'WEBGL_compressed_texture_etc1' ); + + if ( extension !== null ) return extension.COMPRESSED_RGB_ETC1_WEBGL; + + } + + if ( p === MinEquation || p === MaxEquation ) { + + extension = extensions.get( 'EXT_blend_minmax' ); + + if ( extension !== null ) { + + if ( p === MinEquation ) return extension.MIN_EXT; + if ( p === MaxEquation ) return extension.MAX_EXT; + + } + + } + + if ( p === UnsignedInt248Type ) { + + extension = extensions.get( 'WEBGL_depth_texture' ); + + if ( extension !== null ) return extension.UNSIGNED_INT_24_8_WEBGL; + + } + + return 0; + + } + + return { convert: convert } + + } + /** * @author supereggbert / http://www.paulbrunt.co.uk/ * @author mrdoob / http://mrdoob.com/ @@ -19933,14 +21022,13 @@ _premultipliedAlpha = parameters.premultipliedAlpha !== undefined ? parameters.premultipliedAlpha : true, _preserveDrawingBuffer = parameters.preserveDrawingBuffer !== undefined ? parameters.preserveDrawingBuffer : false; - var lights = []; + var lightsArray = []; + var shadowsArray = []; var currentRenderList = null; - var morphInfluences = new Float32Array( 8 ); - - var sprites = []; - var lensFlares = []; + var spritesArray = []; + var flaresArray = []; // public properties @@ -19988,39 +21076,37 @@ var _this = this, + _isContextLost = false, + // internal state cache - _currentProgram = null, _currentRenderTarget = null, _currentFramebuffer = null, _currentMaterialId = - 1, _currentGeometryProgram = '', + _currentCamera = null, + _currentArrayCamera = null, + _currentViewport = new Vector4(), _currentScissor = new Vector4(), _currentScissorTest = null, - _currentViewport = new Vector4(), - // _usedTextureUnits = 0, // - _clearColor = new Color( 0x000000 ), - _clearAlpha = 0, - _width = _canvas.width, _height = _canvas.height, _pixelRatio = 1, + _viewport = new Vector4( 0, 0, _width, _height ), _scissor = new Vector4( 0, 0, _width, _height ), _scissorTest = false, - _viewport = new Vector4( 0, 0, _width, _height ), - // frustum _frustum = new Frustum(), @@ -20036,31 +21122,6 @@ _projScreenMatrix = new Matrix4(), _vector3 = new Vector3(), - _matrix4 = new Matrix4(), - _matrix42 = new Matrix4(), - - // light arrays cache - - _lights = { - - hash: '', - - ambient: [ 0, 0, 0 ], - directional: [], - directionalShadowMap: [], - directionalShadowMatrix: [], - spot: [], - spotShadowMap: [], - spotShadowMatrix: [], - rectArea: [], - point: [], - pointShadowMap: [], - pointShadowMatrix: [], - hemi: [], - - shadows: [] - - }, // info @@ -20087,6 +21148,11 @@ }; + function getTargetPixelRatio() { + + return _currentRenderTarget === null ? _pixelRatio : 1; + + } // initialize @@ -20132,6 +21198,7 @@ } _canvas.addEventListener( 'webglcontextlost', onContextLost, false ); + _canvas.addEventListener( 'webglcontextrestored', onContextRestore, false ); } catch ( error ) { @@ -20139,95 +21206,82 @@ } - var extensions = new WebGLExtensions( _gl ); - - extensions.get( 'WEBGL_depth_texture' ); - extensions.get( 'OES_texture_float' ); - extensions.get( 'OES_texture_float_linear' ); - extensions.get( 'OES_texture_half_float' ); - extensions.get( 'OES_texture_half_float_linear' ); - extensions.get( 'OES_standard_derivatives' ); - extensions.get( 'ANGLE_instanced_arrays' ); - - if ( extensions.get( 'OES_element_index_uint' ) ) { - - BufferGeometry.MaxIndex = 4294967296; - - } - - var capabilities = new WebGLCapabilities( _gl, extensions, parameters ); + var extensions, capabilities, state; + var properties, textures, attributes, geometries, objects, lights; + var programCache, renderLists; - var state = new WebGLState( _gl, extensions, paramThreeToGL ); + var background, morphtargets, bufferRenderer, indexedBufferRenderer; + var flareRenderer, spriteRenderer; - var properties = new WebGLProperties(); - var textures = new WebGLTextures( _gl, extensions, state, properties, capabilities, paramThreeToGL, _infoMemory ); - var attributes = new WebGLAttributes( _gl ); - var geometries = new WebGLGeometries( _gl, attributes, _infoMemory ); - var objects = new WebGLObjects( _gl, geometries, _infoRender ); - var programCache = new WebGLPrograms( this, capabilities ); - var lightCache = new WebGLLights(); - var renderLists = new WebGLRenderLists(); + var utils; - this.info.programs = programCache.programs; + function initGLContext() { - var bufferRenderer = new WebGLBufferRenderer( _gl, extensions, _infoRender ); - var indexedBufferRenderer = new WebGLIndexedBufferRenderer( _gl, extensions, _infoRender ); - - // + extensions = new WebGLExtensions( _gl ); + extensions.get( 'WEBGL_depth_texture' ); + extensions.get( 'OES_texture_float' ); + extensions.get( 'OES_texture_float_linear' ); + extensions.get( 'OES_texture_half_float' ); + extensions.get( 'OES_texture_half_float_linear' ); + extensions.get( 'OES_standard_derivatives' ); + extensions.get( 'ANGLE_instanced_arrays' ); - var backgroundPlaneCamera, backgroundPlaneMesh; - var backgroundBoxCamera, backgroundBoxMesh; - - // - - function getTargetPixelRatio() { + if ( extensions.get( 'OES_element_index_uint' ) ) { - return _currentRenderTarget === null ? _pixelRatio : 1; + BufferGeometry.MaxIndex = 4294967296; - } + } - function setDefaultGLState() { + utils = new WebGLUtils( _gl, extensions ); - state.init(); + capabilities = new WebGLCapabilities( _gl, extensions, parameters ); + state = new WebGLState( _gl, extensions, utils ); state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ) ); state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ) ); - state.buffers.color.setClear( _clearColor.r, _clearColor.g, _clearColor.b, _clearAlpha, _premultipliedAlpha ); + properties = new WebGLProperties(); + textures = new WebGLTextures( _gl, extensions, state, properties, capabilities, utils, _infoMemory ); + attributes = new WebGLAttributes( _gl ); + geometries = new WebGLGeometries( _gl, attributes, _infoMemory ); + objects = new WebGLObjects( geometries, _infoRender ); + morphtargets = new WebGLMorphtargets( _gl ); + programCache = new WebGLPrograms( _this, extensions, capabilities ); + lights = new WebGLLights(); + renderLists = new WebGLRenderLists(); - } + background = new WebGLBackground( _this, state, geometries, _premultipliedAlpha ); - function resetGLState() { + bufferRenderer = new WebGLBufferRenderer( _gl, extensions, _infoRender ); + indexedBufferRenderer = new WebGLIndexedBufferRenderer( _gl, extensions, _infoRender ); - _currentProgram = null; - _currentCamera = null; + flareRenderer = new WebGLFlareRenderer( _this, _gl, state, textures, capabilities ); + spriteRenderer = new WebGLSpriteRenderer( _this, _gl, state, textures, capabilities ); - _currentGeometryProgram = ''; - _currentMaterialId = - 1; + _this.info.programs = programCache.programs; - state.reset(); + _this.context = _gl; + _this.capabilities = capabilities; + _this.extensions = extensions; + _this.properties = properties; + _this.renderLists = renderLists; + _this.state = state; } - setDefaultGLState(); - - this.context = _gl; - this.capabilities = capabilities; - this.extensions = extensions; - this.properties = properties; - this.state = state; + initGLContext(); - // shadow map + // vr - var shadowMap = new WebGLShadowMap( this, _lights, objects, capabilities ); + var vr = new WebVRManager( _this ); - this.shadowMap = shadowMap; + this.vr = vr; + // shadow map - // Plugins + var shadowMap = new WebGLShadowMap( _this, objects, capabilities.maxTextureSize ); - var spritePlugin = new SpritePlugin( this, sprites ); - var lensFlarePlugin = new LensFlarePlugin( this, lensFlares ); + this.shadowMap = shadowMap; // API @@ -20250,15 +21304,10 @@ }; - this.getMaxAnisotropy = function () { - - return capabilities.getMaxAnisotropy(); + this.forceContextRestore = function () { - }; - - this.getPrecision = function () { - - return capabilities.precision; + var extension = extensions.get( 'WEBGL_lose_context' ); + if ( extension ) extension.restoreContext(); }; @@ -20274,7 +21323,7 @@ _pixelRatio = value; - this.setSize( _viewport.z, _viewport.w, false ); + this.setSize( _width, _height, false ); }; @@ -20289,6 +21338,15 @@ this.setSize = function ( width, height, updateStyle ) { + var device = vr.getDevice(); + + if ( device && device.isPresenting ) { + + console.warn( 'THREE.WebGLRenderer: Can\'t change size while VR device is presenting.' ); + return; + + } + _width = width; _height = height; @@ -20306,55 +21364,55 @@ }; - this.setViewport = function ( x, y, width, height ) { + this.getDrawingBufferSize = function () { - state.viewport( _viewport.set( x, y, width, height ) ); + return { + width: _width * _pixelRatio, + height: _height * _pixelRatio + }; }; - this.setScissor = function ( x, y, width, height ) { + this.setDrawingBufferSize = function ( width, height, pixelRatio ) { - state.scissor( _scissor.set( x, y, width, height ) ); + _width = width; + _height = height; - }; + _pixelRatio = pixelRatio; - this.setScissorTest = function ( boolean ) { + _canvas.width = width * pixelRatio; + _canvas.height = height * pixelRatio; - state.setScissorTest( _scissorTest = boolean ); + this.setViewport( 0, 0, width, height ); }; - // Clearing - - this.getClearColor = function () { + this.setViewport = function ( x, y, width, height ) { - return _clearColor; + _viewport.set( x, _height - y - height, width, height ); + state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ) ); }; - this.setClearColor = function ( color, alpha ) { - - _clearColor.set( color ); - - _clearAlpha = alpha !== undefined ? alpha : 1; + this.setScissor = function ( x, y, width, height ) { - state.buffers.color.setClear( _clearColor.r, _clearColor.g, _clearColor.b, _clearAlpha, _premultipliedAlpha ); + _scissor.set( x, _height - y - height, width, height ); + state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ) ); }; - this.getClearAlpha = function () { + this.setScissorTest = function ( boolean ) { - return _clearAlpha; + state.setScissorTest( _scissorTest = boolean ); }; - this.setClearAlpha = function ( alpha ) { - - _clearAlpha = alpha; - - state.buffers.color.setClear( _clearColor.r, _clearColor.g, _clearColor.b, _clearAlpha, _premultipliedAlpha ); + // Clearing - }; + this.getClearColor = background.getClearColor; + this.setClearColor = background.setClearColor; + this.getClearAlpha = background.getClearAlpha; + this.setClearAlpha = background.setClearAlpha; this.clear = function ( color, depth, stencil ) { @@ -20393,16 +21451,17 @@ }; - // Reset - - this.resetGLState = resetGLState; + // this.dispose = function () { _canvas.removeEventListener( 'webglcontextlost', onContextLost, false ); + _canvas.removeEventListener( 'webglcontextrestored', onContextRestore, false ); renderLists.dispose(); + vr.dispose(); + }; // Events @@ -20411,11 +21470,19 @@ event.preventDefault(); - resetGLState(); - setDefaultGLState(); + console.log( 'THREE.WebGLRenderer: Context Lost.' ); - properties.clear(); - objects.clear(); + _isContextLost = true; + + } + + function onContextRestore( event ) { + + console.log( 'THREE.WebGLRenderer: Context Restored.' ); + + _isContextLost = false; + + initGLContext(); } @@ -20496,7 +21563,7 @@ if ( ! material.isMeshPhongMaterial && ! material.isMeshStandardMaterial && ! material.isMeshNormalMaterial && - material.shading === FlatShading ) { + material.flatShading === true ) { for ( var i = 0, l = object.count * 3; i < l; i += 9 ) { @@ -20537,7 +21604,7 @@ state.enableAttribute( programAttributes.uv ); - _gl.vertexAttribPointer( attributes.uv, 2, _gl.FLOAT, false, 0, 0 ); + _gl.vertexAttribPointer( programAttributes.uv, 2, _gl.FLOAT, false, 0, 0 ); } @@ -20560,12 +21627,6 @@ }; - function absNumericalSort( a, b ) { - - return Math.abs( b[ 0 ] ) - Math.abs( a[ 0 ] ); - - } - this.renderBufferDirect = function ( camera, fog, geometry, material, object, group ) { state.setMaterial( material ); @@ -20582,61 +21643,9 @@ } - // morph targets - - var morphTargetInfluences = object.morphTargetInfluences; - - if ( morphTargetInfluences !== undefined ) { - - // TODO Remove allocations - - var activeInfluences = []; - - for ( var i = 0, l = morphTargetInfluences.length; i < l; i ++ ) { - - var influence = morphTargetInfluences[ i ]; - activeInfluences.push( [ influence, i ] ); - - } - - activeInfluences.sort( absNumericalSort ); - - if ( activeInfluences.length > 8 ) { - - activeInfluences.length = 8; - - } - - var morphAttributes = geometry.morphAttributes; - - for ( var i = 0, l = activeInfluences.length; i < l; i ++ ) { - - var influence = activeInfluences[ i ]; - morphInfluences[ i ] = influence[ 0 ]; - - if ( influence[ 0 ] !== 0 ) { - - var index = influence[ 1 ]; - - if ( material.morphTargets === true && morphAttributes.position ) geometry.addAttribute( 'morphTarget' + i, morphAttributes.position[ index ] ); - if ( material.morphNormals === true && morphAttributes.normal ) geometry.addAttribute( 'morphNormal' + i, morphAttributes.normal[ index ] ); - - } else { - - if ( material.morphTargets === true ) geometry.removeAttribute( 'morphTarget' + i ); - if ( material.morphNormals === true ) geometry.removeAttribute( 'morphNormal' + i ); - - } - - } - - for ( var i = activeInfluences.length, il = morphInfluences.length; i < il; i ++ ) { + if ( object.morphTargetInfluences ) { - morphInfluences[ i ] = 0.0; - - } - - program.getUniforms().setValue( _gl, 'morphTargetInfluences', morphInfluences ); + morphtargets.update( object, geometry, material, program ); updateBuffers = true; @@ -20655,12 +21664,15 @@ } + var attribute; var renderer = bufferRenderer; if ( index !== null ) { + attribute = attributes.get( index ); + renderer = indexedBufferRenderer; - renderer.setIndex( index ); + renderer.setIndex( attribute ); } @@ -20670,7 +21682,7 @@ if ( index !== null ) { - _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, attributes.get( index ).buffer ); + _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, attribute.buffer ); } @@ -20813,11 +21825,15 @@ var normalized = geometryAttribute.normalized; var size = geometryAttribute.itemSize; - var attributeProperties = attributes.get( geometryAttribute ); + var attribute = attributes.get( geometryAttribute ); + + // TODO Attribute may not be available on context restore - var buffer = attributeProperties.buffer; - var type = attributeProperties.type; - var bytesPerElement = attributeProperties.bytesPerElement; + if ( attribute === undefined ) continue; + + var buffer = attribute.buffer; + var type = attribute.type; + var bytesPerElement = attribute.bytesPerElement; if ( geometryAttribute.isInterleavedBufferAttribute ) { @@ -20908,19 +21924,26 @@ this.compile = function ( scene, camera ) { - lights = []; + lightsArray.length = 0; + shadowsArray.length = 0; scene.traverse( function ( object ) { if ( object.isLight ) { - lights.push( object ); + lightsArray.push( object ); + + if ( object.castShadow ) { + + shadowsArray.push( object ); + + } } } ); - setupLights( lights, camera ); + lights.setup( lightsArray, shadowsArray, camera ); scene.traverse( function ( object ) { @@ -20946,17 +21969,46 @@ }; + // Animation Loop + + var isAnimating = false; + var onAnimationFrame = null; + + function start() { + + if ( isAnimating ) return; + ( vr.getDevice() || window ).requestAnimationFrame( loop ); + isAnimating = true; + + } + + function loop( time ) { + + if ( onAnimationFrame !== null ) onAnimationFrame( time ); + ( vr.getDevice() || window ).requestAnimationFrame( loop ); + + } + + this.animate = function ( callback ) { + + onAnimationFrame = callback; + start(); + + }; + // Rendering this.render = function ( scene, camera, renderTarget, forceClear ) { - if ( camera !== undefined && camera.isCamera !== true ) { + if ( ! ( camera && camera.isCamera ) ) { console.error( 'THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.' ); return; } + if ( _isContextLost ) return; + // reset caching for this frame _currentGeometryProgram = ''; @@ -20969,18 +22021,22 @@ // update camera matrices and frustum - camera.onBeforeRender( _this ); - if ( camera.parent === null ) camera.updateMatrixWorld(); - camera.matrixWorldInverse.getInverse( camera.matrixWorld ); + if ( vr.enabled ) { + + camera = vr.getCamera( camera ); + + } _projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse ); _frustum.setFromMatrix( _projScreenMatrix ); - lights.length = 0; - sprites.length = 0; - lensFlares.length = 0; + lightsArray.length = 0; + shadowsArray.length = 0; + + spritesArray.length = 0; + flaresArray.length = 0; _localClippingEnabled = this.localClippingEnabled; _clippingEnabled = _clipping.init( this.clippingPlanes, _localClippingEnabled, camera ); @@ -20990,8 +22046,6 @@ projectObject( scene, camera, _this.sortObjects ); - currentRenderList.finish(); - if ( _this.sortObjects === true ) { currentRenderList.sort(); @@ -21002,11 +22056,9 @@ if ( _clippingEnabled ) _clipping.beginShadows(); - setupShadows( lights ); + shadowMap.render( shadowsArray, scene, camera ); - shadowMap.render( scene, camera ); - - setupLights( lights, camera ); + lights.setup( lightsArray, shadowsArray, camera ); if ( _clippingEnabled ) _clipping.endShadows(); @@ -21028,81 +22080,9 @@ // - var background = scene.background; - - if ( background === null ) { - - state.buffers.color.setClear( _clearColor.r, _clearColor.g, _clearColor.b, _clearAlpha, _premultipliedAlpha ); - - } else if ( background && background.isColor ) { - - state.buffers.color.setClear( background.r, background.g, background.b, 1, _premultipliedAlpha ); - forceClear = true; - - } - - if ( this.autoClear || forceClear ) { - - this.clear( this.autoClearColor, this.autoClearDepth, this.autoClearStencil ); - - } - - if ( background && background.isCubeTexture ) { - - if ( backgroundBoxCamera === undefined ) { - - backgroundBoxCamera = new PerspectiveCamera(); - - backgroundBoxMesh = new Mesh( - new BoxBufferGeometry( 5, 5, 5 ), - new ShaderMaterial( { - uniforms: ShaderLib.cube.uniforms, - vertexShader: ShaderLib.cube.vertexShader, - fragmentShader: ShaderLib.cube.fragmentShader, - side: BackSide, - depthTest: false, - depthWrite: false, - fog: false - } ) - ); - - } - - backgroundBoxCamera.projectionMatrix.copy( camera.projectionMatrix ); - - backgroundBoxCamera.matrixWorld.extractRotation( camera.matrixWorld ); - backgroundBoxCamera.matrixWorldInverse.getInverse( backgroundBoxCamera.matrixWorld ); - + background.render( currentRenderList, scene, camera, forceClear ); - backgroundBoxMesh.material.uniforms[ "tCube" ].value = background; - backgroundBoxMesh.modelViewMatrix.multiplyMatrices( backgroundBoxCamera.matrixWorldInverse, backgroundBoxMesh.matrixWorld ); - - objects.update( backgroundBoxMesh ); - - _this.renderBufferDirect( backgroundBoxCamera, null, backgroundBoxMesh.geometry, backgroundBoxMesh.material, backgroundBoxMesh, null ); - - } else if ( background && background.isTexture ) { - - if ( backgroundPlaneCamera === undefined ) { - - backgroundPlaneCamera = new OrthographicCamera( - 1, 1, 1, - 1, 0, 1 ); - - backgroundPlaneMesh = new Mesh( - new PlaneBufferGeometry( 2, 2 ), - new MeshBasicMaterial( { depthTest: false, depthWrite: false, fog: false } ) - ); - - } - - backgroundPlaneMesh.material.map = background; - - objects.update( backgroundPlaneMesh ); - - _this.renderBufferDirect( backgroundPlaneCamera, null, backgroundPlaneMesh.geometry, backgroundPlaneMesh.material, backgroundPlaneMesh, null ); - - } - - // + // render scene var opaqueObjects = currentRenderList.opaque; var transparentObjects = currentRenderList.transparent; @@ -21126,10 +22106,10 @@ } - // custom render plugins (post pass) + // custom renderers - spritePlugin.render( scene, camera ); - lensFlarePlugin.render( scene, camera, _currentViewport ); + spriteRenderer.render( spritesArray, scene, camera ); + flareRenderer.render( flaresArray, scene, camera, _currentViewport ); // Generate mipmap if we're using any kind of mipmap filtering @@ -21145,13 +22125,13 @@ state.buffers.depth.setMask( true ); state.buffers.color.setMask( true ); - if ( camera.isArrayCamera && camera.enabled ) { + state.setPolygonOffset( false ); - _this.setScissorTest( false ); + if ( vr.enabled ) { - } + vr.submitFrame(); - camera.onAfterRender( _this ); + } // _gl.finish(); @@ -21214,7 +22194,7 @@ function projectObject( object, camera, sortObjects ) { - if ( ! object.visible ) return; + if ( object.visible === false ) return; var visible = object.layers.test( camera.layers ); @@ -21222,19 +22202,25 @@ if ( object.isLight ) { - lights.push( object ); + lightsArray.push( object ); + + if ( object.castShadow ) { + + shadowsArray.push( object ); + + } } else if ( object.isSprite ) { if ( ! object.frustumCulled || _frustum.intersectsSprite( object ) ) { - sprites.push( object ); + spritesArray.push( object ); } } else if ( object.isLensFlare ) { - lensFlares.push( object ); + flaresArray.push( object ); } else if ( object.isImmediateRenderObject ) { @@ -21317,45 +22303,49 @@ var material = overrideMaterial === undefined ? renderItem.material : overrideMaterial; var group = renderItem.group; - object.onBeforeRender( _this, scene, camera, geometry, material, group ); + if ( camera.isArrayCamera ) { - if ( camera.isArrayCamera && camera.enabled ) { + _currentArrayCamera = camera; var cameras = camera.cameras; for ( var j = 0, jl = cameras.length; j < jl; j ++ ) { var camera2 = cameras[ j ]; - var bounds = camera2.bounds; - _this.setViewport( - bounds.x * _width * _pixelRatio, bounds.y * _height * _pixelRatio, - bounds.z * _width * _pixelRatio, bounds.w * _height * _pixelRatio - ); - _this.setScissor( - bounds.x * _width * _pixelRatio, bounds.y * _height * _pixelRatio, - bounds.z * _width * _pixelRatio, bounds.w * _height * _pixelRatio - ); - _this.setScissorTest( true ); + if ( object.layers.test( camera2.layers ) ) { + + var bounds = camera2.bounds; - renderObject( object, scene, camera2, geometry, material, group ); + var x = bounds.x * _width; + var y = bounds.y * _height; + var width = bounds.z * _width; + var height = bounds.w * _height; + + state.viewport( _currentViewport.set( x, y, width, height ).multiplyScalar( _pixelRatio ) ); + + renderObject( object, scene, camera2, geometry, material, group ); + + } } } else { + _currentArrayCamera = null; + renderObject( object, scene, camera, geometry, material, group ); } - object.onAfterRender( _this, scene, camera, geometry, material, group ); - } } function renderObject( object, scene, camera, geometry, material, group ) { + object.onBeforeRender( _this, scene, camera, geometry, material, group ); + object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld ); object.normalMatrix.getNormalMatrix( object.modelViewMatrix ); @@ -21375,6 +22365,8 @@ } + object.onAfterRender( _this, scene, camera, geometry, material, group ); + } function initMaterial( material, fog, object ) { @@ -21382,7 +22374,7 @@ var materialProperties = properties.get( material ); var parameters = programCache.getParameters( - material, _lights, fog, _clipping.numPlanes, _clipping.numIntersection, object ); + material, lights.state, shadowsArray, fog, _clipping.numPlanes, _clipping.numIntersection, object ); var code = programCache.getProgramCode( material, parameters ); @@ -21417,7 +22409,7 @@ var shader = ShaderLib[ parameters.shaderID ]; - materialProperties.__webglShader = { + materialProperties.shader = { name: material.type, uniforms: UniformsUtils.clone( shader.uniforms ), vertexShader: shader.vertexShader, @@ -21426,7 +22418,7 @@ } else { - materialProperties.__webglShader = { + materialProperties.shader = { name: material.type, uniforms: material.uniforms, vertexShader: material.vertexShader, @@ -21435,9 +22427,9 @@ } - material.__webglShader = materialProperties.__webglShader; + material.onBeforeCompile( materialProperties.shader ); - program = programCache.acquireProgram( material, parameters, code ); + program = programCache.acquireProgram( material, materialProperties.shader, parameters, code ); materialProperties.program = program; material.program = program; @@ -21478,7 +22470,7 @@ } - var uniforms = materialProperties.__webglShader.uniforms; + var uniforms = materialProperties.shader.uniforms; if ( ! material.isShaderMaterial && ! material.isRawShaderMaterial || @@ -21494,25 +22486,25 @@ // store the light setup it was created for - materialProperties.lightsHash = _lights.hash; + materialProperties.lightsHash = lights.state.hash; if ( material.lights ) { // wire up the material to this renderer's lighting state - uniforms.ambientLightColor.value = _lights.ambient; - uniforms.directionalLights.value = _lights.directional; - uniforms.spotLights.value = _lights.spot; - uniforms.rectAreaLights.value = _lights.rectArea; - uniforms.pointLights.value = _lights.point; - uniforms.hemisphereLights.value = _lights.hemi; - - uniforms.directionalShadowMap.value = _lights.directionalShadowMap; - uniforms.directionalShadowMatrix.value = _lights.directionalShadowMatrix; - uniforms.spotShadowMap.value = _lights.spotShadowMap; - uniforms.spotShadowMatrix.value = _lights.spotShadowMatrix; - uniforms.pointShadowMap.value = _lights.pointShadowMap; - uniforms.pointShadowMatrix.value = _lights.pointShadowMatrix; + uniforms.ambientLightColor.value = lights.state.ambient; + uniforms.directionalLights.value = lights.state.directional; + uniforms.spotLights.value = lights.state.spot; + uniforms.rectAreaLights.value = lights.state.rectArea; + uniforms.pointLights.value = lights.state.point; + uniforms.hemisphereLights.value = lights.state.hemi; + + uniforms.directionalShadowMap.value = lights.state.directionalShadowMap; + uniforms.directionalShadowMatrix.value = lights.state.directionalShadowMatrix; + uniforms.spotShadowMap.value = lights.state.spotShadowMap; + uniforms.spotShadowMatrix.value = lights.state.spotShadowMatrix; + uniforms.pointShadowMap.value = lights.state.pointShadowMap; + uniforms.pointShadowMatrix.value = lights.state.pointShadowMatrix; // TODO (abelnation): add area lights shadow info to uniforms } @@ -21560,7 +22552,7 @@ material.needsUpdate = true; - } else if ( material.lights && materialProperties.lightsHash !== _lights.hash ) { + } else if ( material.lights && materialProperties.lightsHash !== lights.state.hash ) { material.needsUpdate = true; @@ -21587,12 +22579,9 @@ var program = materialProperties.program, p_uniforms = program.getUniforms(), - m_uniforms = materialProperties.__webglShader.uniforms; + m_uniforms = materialProperties.shader.uniforms; - if ( program.id !== _currentProgram ) { - - _gl.useProgram( program.program ); - _currentProgram = program.id; + if ( state.useProgram( program.program ) ) { refreshProgram = true; refreshMaterial = true; @@ -21619,10 +22608,11 @@ } + // Avoid unneeded uniform updates per ArrayCamera's sub-camera - if ( camera !== _currentCamera ) { + if ( _currentCamera !== ( _currentArrayCamera || camera ) ) { - _currentCamera = camera; + _currentCamera = ( _currentArrayCamera || camera ); // lighting uniforms depend on the camera so enforce an update // now, in case this material supports lights - or later, when @@ -21663,9 +22653,6 @@ } - p_uniforms.setValue( _gl, 'toneMappingExposure', _this.toneMappingExposure ); - p_uniforms.setValue( _gl, 'toneMappingWhitePoint', _this.toneMappingWhitePoint ); - } // skinning uniforms must be set even if material didn't change @@ -21725,6 +22712,9 @@ if ( refreshMaterial ) { + p_uniforms.setValue( _gl, 'toneMappingExposure', _this.toneMappingExposure ); + p_uniforms.setValue( _gl, 'toneMappingWhitePoint', _this.toneMappingWhitePoint ); + if ( material.lights ) { // the current material requires lighting info @@ -21748,66 +22738,77 @@ } - if ( material.isMeshBasicMaterial || - material.isMeshLambertMaterial || - material.isMeshPhongMaterial || - material.isMeshStandardMaterial || - material.isMeshNormalMaterial || - material.isMeshDepthMaterial ) { + if ( material.isMeshBasicMaterial ) { refreshUniformsCommon( m_uniforms, material ); - } - - // refresh single material specific uniforms - - if ( material.isLineBasicMaterial ) { + } else if ( material.isMeshLambertMaterial ) { - refreshUniformsLine( m_uniforms, material ); + refreshUniformsCommon( m_uniforms, material ); + refreshUniformsLambert( m_uniforms, material ); - } else if ( material.isLineDashedMaterial ) { + } else if ( material.isMeshPhongMaterial ) { - refreshUniformsLine( m_uniforms, material ); - refreshUniformsDash( m_uniforms, material ); + refreshUniformsCommon( m_uniforms, material ); - } else if ( material.isPointsMaterial ) { + if ( material.isMeshToonMaterial ) { - refreshUniformsPoints( m_uniforms, material ); + refreshUniformsToon( m_uniforms, material ); - } else if ( material.isMeshLambertMaterial ) { + } else { - refreshUniformsLambert( m_uniforms, material ); + refreshUniformsPhong( m_uniforms, material ); - } else if ( material.isMeshToonMaterial ) { + } - refreshUniformsToon( m_uniforms, material ); + } else if ( material.isMeshStandardMaterial ) { - } else if ( material.isMeshPhongMaterial ) { + refreshUniformsCommon( m_uniforms, material ); - refreshUniformsPhong( m_uniforms, material ); + if ( material.isMeshPhysicalMaterial ) { - } else if ( material.isMeshPhysicalMaterial ) { + refreshUniformsPhysical( m_uniforms, material ); - refreshUniformsPhysical( m_uniforms, material ); + } else { - } else if ( material.isMeshStandardMaterial ) { + refreshUniformsStandard( m_uniforms, material ); - refreshUniformsStandard( m_uniforms, material ); + } } else if ( material.isMeshDepthMaterial ) { - if ( material.displacementMap ) { + refreshUniformsCommon( m_uniforms, material ); + refreshUniformsDepth( m_uniforms, material ); - m_uniforms.displacementMap.value = material.displacementMap; - m_uniforms.displacementScale.value = material.displacementScale; - m_uniforms.displacementBias.value = material.displacementBias; + } else if ( material.isMeshDistanceMaterial ) { - } + refreshUniformsCommon( m_uniforms, material ); + refreshUniformsDistance( m_uniforms, material ); } else if ( material.isMeshNormalMaterial ) { + refreshUniformsCommon( m_uniforms, material ); refreshUniformsNormal( m_uniforms, material ); + } else if ( material.isLineBasicMaterial ) { + + refreshUniformsLine( m_uniforms, material ); + + if ( material.isLineDashedMaterial ) { + + refreshUniformsDash( m_uniforms, material ); + + } + + } else if ( material.isPointsMaterial ) { + + refreshUniformsPoints( m_uniforms, material ); + + } else if ( material.isShadowMaterial ) { + + m_uniforms.color.value = material.color; + m_uniforms.opacity.value = material.opacity; + } // RectAreaLight Texture @@ -21838,7 +22839,11 @@ uniforms.opacity.value = material.opacity; - uniforms.diffuse.value = material.color; + if ( material.color ) { + + uniforms.diffuse.value = material.color; + + } if ( material.emissive ) { @@ -21846,9 +22851,38 @@ } - uniforms.map.value = material.map; - uniforms.specularMap.value = material.specularMap; - uniforms.alphaMap.value = material.alphaMap; + if ( material.map ) { + + uniforms.map.value = material.map; + + } + + if ( material.alphaMap ) { + + uniforms.alphaMap.value = material.alphaMap; + + } + + if ( material.specularMap ) { + + uniforms.specularMap.value = material.specularMap; + + } + + if ( material.envMap ) { + + uniforms.envMap.value = material.envMap; + + // don't flip CubeTexture envMaps, flip everything else: + // WebGLRenderTargetCube will be flipped for backwards compatibility + // WebGLRenderTargetCube.texture will be flipped because it's a Texture and NOT a CubeTexture + // this check must be handled differently, or removed entirely, if WebGLRenderTargetCube uses a CubeTexture in the future + uniforms.flipEnvMap.value = ( ! ( material.envMap && material.envMap.isCubeTexture ) ) ? 1 : - 1; + + uniforms.reflectivity.value = material.reflectivity; + uniforms.refractionRatio.value = material.refractionRatio; + + } if ( material.lightMap ) { @@ -21921,23 +22955,18 @@ } - var offset = uvScaleMap.offset; - var repeat = uvScaleMap.repeat; + if ( uvScaleMap.matrixAutoUpdate === true ) { - uniforms.offsetRepeat.value.set( offset.x, offset.y, repeat.x, repeat.y ); + var offset = uvScaleMap.offset; + var repeat = uvScaleMap.repeat; + var rotation = uvScaleMap.rotation; + uvScaleMap.matrix.setUvTransform( offset.x, offset.y, repeat.x, repeat.y, rotation, 0.5, 0.5 ); - } - - uniforms.envMap.value = material.envMap; + } - // don't flip CubeTexture envMaps, flip everything else: - // WebGLRenderTargetCube will be flipped for backwards compatibility - // WebGLRenderTargetCube.texture will be flipped because it's a Texture and NOT a CubeTexture - // this check must be handled differently, or removed entirely, if WebGLRenderTargetCube uses a CubeTexture in the future - uniforms.flipEnvMap.value = ( ! ( material.envMap && material.envMap.isCubeTexture ) ) ? 1 : - 1; + uniforms.uvTransform.value.copy( uvScaleMap.matrix ); - uniforms.reflectivity.value = material.reflectivity; - uniforms.refractionRatio.value = material.refractionRatio; + } } @@ -21967,10 +22996,16 @@ if ( material.map !== null ) { - var offset = material.map.offset; - var repeat = material.map.repeat; + if ( material.map.matrixAutoUpdate === true ) { - uniforms.offsetRepeat.value.set( offset.x, offset.y, repeat.x, repeat.y ); + var offset = material.map.offset; + var repeat = material.map.repeat; + var rotation = material.map.rotation; + material.map.matrix.setUvTransform( offset.x, offset.y, repeat.x, repeat.y, rotation, 0.5, 0.5 ); + + } + + uniforms.uvTransform.value.copy( material.map.matrix ); } @@ -22113,6 +23148,34 @@ } + function refreshUniformsDepth( uniforms, material ) { + + if ( material.displacementMap ) { + + uniforms.displacementMap.value = material.displacementMap; + uniforms.displacementScale.value = material.displacementScale; + uniforms.displacementBias.value = material.displacementBias; + + } + + } + + function refreshUniformsDistance( uniforms, material ) { + + if ( material.displacementMap ) { + + uniforms.displacementMap.value = material.displacementMap; + uniforms.displacementScale.value = material.displacementScale; + uniforms.displacementBias.value = material.displacementBias; + + } + + uniforms.referencePosition.value.copy( material.referencePosition ); + uniforms.nearDistance.value = material.nearDistance; + uniforms.farDistance.value = material.farDistance; + + } + function refreshUniformsNormal( uniforms, material ) { if ( material.bumpMap ) { @@ -22153,224 +23216,6 @@ } - // Lighting - - function setupShadows( lights ) { - - var lightShadowsLength = 0; - - for ( var i = 0, l = lights.length; i < l; i ++ ) { - - var light = lights[ i ]; - - if ( light.castShadow ) { - - _lights.shadows[ lightShadowsLength ] = light; - lightShadowsLength ++; - - } - - } - - _lights.shadows.length = lightShadowsLength; - - } - - function setupLights( lights, camera ) { - - var l, ll, light, shadow, - r = 0, g = 0, b = 0, - color, - intensity, - distance, - shadowMap, - - viewMatrix = camera.matrixWorldInverse, - - directionalLength = 0, - pointLength = 0, - spotLength = 0, - rectAreaLength = 0, - hemiLength = 0; - - for ( l = 0, ll = lights.length; l < ll; l ++ ) { - - light = lights[ l ]; - - color = light.color; - intensity = light.intensity; - distance = light.distance; - - shadowMap = ( light.shadow && light.shadow.map ) ? light.shadow.map.texture : null; - - if ( light.isAmbientLight ) { - - r += color.r * intensity; - g += color.g * intensity; - b += color.b * intensity; - - } else if ( light.isDirectionalLight ) { - - var uniforms = lightCache.get( light ); - - uniforms.color.copy( light.color ).multiplyScalar( light.intensity ); - uniforms.direction.setFromMatrixPosition( light.matrixWorld ); - _vector3.setFromMatrixPosition( light.target.matrixWorld ); - uniforms.direction.sub( _vector3 ); - uniforms.direction.transformDirection( viewMatrix ); - - uniforms.shadow = light.castShadow; - - if ( light.castShadow ) { - - shadow = light.shadow; - - uniforms.shadowBias = shadow.bias; - uniforms.shadowRadius = shadow.radius; - uniforms.shadowMapSize = shadow.mapSize; - - } - - _lights.directionalShadowMap[ directionalLength ] = shadowMap; - _lights.directionalShadowMatrix[ directionalLength ] = light.shadow.matrix; - _lights.directional[ directionalLength ] = uniforms; - - directionalLength ++; - - } else if ( light.isSpotLight ) { - - var uniforms = lightCache.get( light ); - - uniforms.position.setFromMatrixPosition( light.matrixWorld ); - uniforms.position.applyMatrix4( viewMatrix ); - - uniforms.color.copy( color ).multiplyScalar( intensity ); - uniforms.distance = distance; - - uniforms.direction.setFromMatrixPosition( light.matrixWorld ); - _vector3.setFromMatrixPosition( light.target.matrixWorld ); - uniforms.direction.sub( _vector3 ); - uniforms.direction.transformDirection( viewMatrix ); - - uniforms.coneCos = Math.cos( light.angle ); - uniforms.penumbraCos = Math.cos( light.angle * ( 1 - light.penumbra ) ); - uniforms.decay = ( light.distance === 0 ) ? 0.0 : light.decay; - - uniforms.shadow = light.castShadow; - - if ( light.castShadow ) { - - shadow = light.shadow; - - uniforms.shadowBias = shadow.bias; - uniforms.shadowRadius = shadow.radius; - uniforms.shadowMapSize = shadow.mapSize; - - } - - _lights.spotShadowMap[ spotLength ] = shadowMap; - _lights.spotShadowMatrix[ spotLength ] = light.shadow.matrix; - _lights.spot[ spotLength ] = uniforms; - - spotLength ++; - - } else if ( light.isRectAreaLight ) { - - var uniforms = lightCache.get( light ); - - // (a) intensity controls irradiance of entire light - uniforms.color - .copy( color ) - .multiplyScalar( intensity / ( light.width * light.height ) ); - - // (b) intensity controls the radiance per light area - // uniforms.color.copy( color ).multiplyScalar( intensity ); - - uniforms.position.setFromMatrixPosition( light.matrixWorld ); - uniforms.position.applyMatrix4( viewMatrix ); - - // extract local rotation of light to derive width/height half vectors - _matrix42.identity(); - _matrix4.copy( light.matrixWorld ); - _matrix4.premultiply( viewMatrix ); - _matrix42.extractRotation( _matrix4 ); - - uniforms.halfWidth.set( light.width * 0.5, 0.0, 0.0 ); - uniforms.halfHeight.set( 0.0, light.height * 0.5, 0.0 ); - - uniforms.halfWidth.applyMatrix4( _matrix42 ); - uniforms.halfHeight.applyMatrix4( _matrix42 ); - - // TODO (abelnation): RectAreaLight distance? - // uniforms.distance = distance; - - _lights.rectArea[ rectAreaLength ] = uniforms; - - rectAreaLength ++; - - } else if ( light.isPointLight ) { - - var uniforms = lightCache.get( light ); - - uniforms.position.setFromMatrixPosition( light.matrixWorld ); - uniforms.position.applyMatrix4( viewMatrix ); - - uniforms.color.copy( light.color ).multiplyScalar( light.intensity ); - uniforms.distance = light.distance; - uniforms.decay = ( light.distance === 0 ) ? 0.0 : light.decay; - - uniforms.shadow = light.castShadow; - - if ( light.castShadow ) { - - shadow = light.shadow; - - uniforms.shadowBias = shadow.bias; - uniforms.shadowRadius = shadow.radius; - uniforms.shadowMapSize = shadow.mapSize; - - } - - _lights.pointShadowMap[ pointLength ] = shadowMap; - _lights.pointShadowMatrix[ pointLength ] = light.shadow.matrix; - _lights.point[ pointLength ] = uniforms; - - pointLength ++; - - } else if ( light.isHemisphereLight ) { - - var uniforms = lightCache.get( light ); - - uniforms.direction.setFromMatrixPosition( light.matrixWorld ); - uniforms.direction.transformDirection( viewMatrix ); - uniforms.direction.normalize(); - - uniforms.skyColor.copy( light.color ).multiplyScalar( intensity ); - uniforms.groundColor.copy( light.groundColor ).multiplyScalar( intensity ); - - _lights.hemi[ hemiLength ] = uniforms; - - hemiLength ++; - - } - - } - - _lights.ambient[ 0 ] = r; - _lights.ambient[ 1 ] = g; - _lights.ambient[ 2 ] = b; - - _lights.directional.length = directionalLength; - _lights.spot.length = spotLength; - _lights.rectArea.length = rectAreaLength; - _lights.point.length = pointLength; - _lights.hemi.length = hemiLength; - - // TODO (sam-g-steel) why aren't we using join - _lights.hash = directionalLength + ',' + pointLength + ',' + spotLength + ',' + rectAreaLength + ',' + hemiLength + ',' + _lights.shadows.length; - - } - // GL state setting this.setFaceCulling = function ( cullFace, frontFaceDirection ) { @@ -22504,37 +23349,34 @@ } - var isCube = ( renderTarget && renderTarget.isWebGLRenderTargetCube ); - var framebuffer; + var framebuffer = null; + var isCube = false; if ( renderTarget ) { - var renderTargetProperties = properties.get( renderTarget ); + var __webglFramebuffer = properties.get( renderTarget ).__webglFramebuffer; - if ( isCube ) { + if ( renderTarget.isWebGLRenderTargetCube ) { - framebuffer = renderTargetProperties.__webglFramebuffer[ renderTarget.activeCubeFace ]; + framebuffer = __webglFramebuffer[ renderTarget.activeCubeFace ]; + isCube = true; } else { - framebuffer = renderTargetProperties.__webglFramebuffer; + framebuffer = __webglFramebuffer; } + _currentViewport.copy( renderTarget.viewport ); _currentScissor.copy( renderTarget.scissor ); _currentScissorTest = renderTarget.scissorTest; - _currentViewport.copy( renderTarget.viewport ); - } else { - framebuffer = null; - + _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ); _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ); _currentScissorTest = _scissorTest; - _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ); - } if ( _currentFramebuffer !== framebuffer ) { @@ -22544,11 +23386,10 @@ } + state.viewport( _currentViewport ); state.scissor( _currentScissor ); state.setScissorTest( _currentScissorTest ); - state.viewport( _currentViewport ); - if ( isCube ) { var textureProperties = properties.get( renderTarget.texture ); @@ -22560,7 +23401,7 @@ this.readRenderTargetPixels = function ( renderTarget, x, y, width, height, buffer ) { - if ( ( renderTarget && renderTarget.isWebGLRenderTarget ) === false ) { + if ( ! ( renderTarget && renderTarget.isWebGLRenderTarget ) ) { console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.' ); return; @@ -22587,14 +23428,14 @@ var textureFormat = texture.format; var textureType = texture.type; - if ( textureFormat !== RGBAFormat && paramThreeToGL( textureFormat ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_FORMAT ) ) { + if ( textureFormat !== RGBAFormat && utils.convert( textureFormat ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_FORMAT ) ) { console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.' ); return; } - if ( textureType !== UnsignedByteType && paramThreeToGL( textureType ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_TYPE ) && // IE11, Edge and Chrome Mac < 52 (#9513) + if ( textureType !== UnsignedByteType && utils.convert( textureType ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_TYPE ) && // IE11, Edge and Chrome Mac < 52 (#9513) ! ( textureType === FloatType && ( extensions.get( 'OES_texture_float' ) || extensions.get( 'WEBGL_color_buffer_float' ) ) ) && // Chrome Mac >= 52 and Firefox ! ( textureType === HalfFloatType && extensions.get( 'EXT_color_buffer_half_float' ) ) ) { @@ -22609,7 +23450,7 @@ if ( ( x >= 0 && x <= ( renderTarget.width - width ) ) && ( y >= 0 && y <= ( renderTarget.height - height ) ) ) { - _gl.readPixels( x, y, width, height, paramThreeToGL( textureFormat ), paramThreeToGL( textureType ), buffer ); + _gl.readPixels( x, y, width, height, utils.convert( textureFormat ), utils.convert( textureType ), buffer ); } @@ -22633,134 +23474,6 @@ }; - // Map three.js constants to WebGL constants - - function paramThreeToGL( p ) { - - var extension; - - if ( p === RepeatWrapping ) return _gl.REPEAT; - if ( p === ClampToEdgeWrapping ) return _gl.CLAMP_TO_EDGE; - if ( p === MirroredRepeatWrapping ) return _gl.MIRRORED_REPEAT; - - if ( p === NearestFilter ) return _gl.NEAREST; - if ( p === NearestMipMapNearestFilter ) return _gl.NEAREST_MIPMAP_NEAREST; - if ( p === NearestMipMapLinearFilter ) return _gl.NEAREST_MIPMAP_LINEAR; - - if ( p === LinearFilter ) return _gl.LINEAR; - if ( p === LinearMipMapNearestFilter ) return _gl.LINEAR_MIPMAP_NEAREST; - if ( p === LinearMipMapLinearFilter ) return _gl.LINEAR_MIPMAP_LINEAR; - - if ( p === UnsignedByteType ) return _gl.UNSIGNED_BYTE; - if ( p === UnsignedShort4444Type ) return _gl.UNSIGNED_SHORT_4_4_4_4; - if ( p === UnsignedShort5551Type ) return _gl.UNSIGNED_SHORT_5_5_5_1; - if ( p === UnsignedShort565Type ) return _gl.UNSIGNED_SHORT_5_6_5; - - if ( p === ByteType ) return _gl.BYTE; - if ( p === ShortType ) return _gl.SHORT; - if ( p === UnsignedShortType ) return _gl.UNSIGNED_SHORT; - if ( p === IntType ) return _gl.INT; - if ( p === UnsignedIntType ) return _gl.UNSIGNED_INT; - if ( p === FloatType ) return _gl.FLOAT; - - if ( p === HalfFloatType ) { - - extension = extensions.get( 'OES_texture_half_float' ); - - if ( extension !== null ) return extension.HALF_FLOAT_OES; - - } - - if ( p === AlphaFormat ) return _gl.ALPHA; - if ( p === RGBFormat ) return _gl.RGB; - if ( p === RGBAFormat ) return _gl.RGBA; - if ( p === LuminanceFormat ) return _gl.LUMINANCE; - if ( p === LuminanceAlphaFormat ) return _gl.LUMINANCE_ALPHA; - if ( p === DepthFormat ) return _gl.DEPTH_COMPONENT; - if ( p === DepthStencilFormat ) return _gl.DEPTH_STENCIL; - - if ( p === AddEquation ) return _gl.FUNC_ADD; - if ( p === SubtractEquation ) return _gl.FUNC_SUBTRACT; - if ( p === ReverseSubtractEquation ) return _gl.FUNC_REVERSE_SUBTRACT; - - if ( p === ZeroFactor ) return _gl.ZERO; - if ( p === OneFactor ) return _gl.ONE; - if ( p === SrcColorFactor ) return _gl.SRC_COLOR; - if ( p === OneMinusSrcColorFactor ) return _gl.ONE_MINUS_SRC_COLOR; - if ( p === SrcAlphaFactor ) return _gl.SRC_ALPHA; - if ( p === OneMinusSrcAlphaFactor ) return _gl.ONE_MINUS_SRC_ALPHA; - if ( p === DstAlphaFactor ) return _gl.DST_ALPHA; - if ( p === OneMinusDstAlphaFactor ) return _gl.ONE_MINUS_DST_ALPHA; - - if ( p === DstColorFactor ) return _gl.DST_COLOR; - if ( p === OneMinusDstColorFactor ) return _gl.ONE_MINUS_DST_COLOR; - if ( p === SrcAlphaSaturateFactor ) return _gl.SRC_ALPHA_SATURATE; - - if ( p === RGB_S3TC_DXT1_Format || p === RGBA_S3TC_DXT1_Format || - p === RGBA_S3TC_DXT3_Format || p === RGBA_S3TC_DXT5_Format ) { - - extension = extensions.get( 'WEBGL_compressed_texture_s3tc' ); - - if ( extension !== null ) { - - if ( p === RGB_S3TC_DXT1_Format ) return extension.COMPRESSED_RGB_S3TC_DXT1_EXT; - if ( p === RGBA_S3TC_DXT1_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT1_EXT; - if ( p === RGBA_S3TC_DXT3_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT3_EXT; - if ( p === RGBA_S3TC_DXT5_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT5_EXT; - - } - - } - - if ( p === RGB_PVRTC_4BPPV1_Format || p === RGB_PVRTC_2BPPV1_Format || - p === RGBA_PVRTC_4BPPV1_Format || p === RGBA_PVRTC_2BPPV1_Format ) { - - extension = extensions.get( 'WEBGL_compressed_texture_pvrtc' ); - - if ( extension !== null ) { - - if ( p === RGB_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_4BPPV1_IMG; - if ( p === RGB_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_2BPPV1_IMG; - if ( p === RGBA_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG; - if ( p === RGBA_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG; - - } - - } - - if ( p === RGB_ETC1_Format ) { - - extension = extensions.get( 'WEBGL_compressed_texture_etc1' ); - - if ( extension !== null ) return extension.COMPRESSED_RGB_ETC1_WEBGL; - - } - - if ( p === MinEquation || p === MaxEquation ) { - - extension = extensions.get( 'EXT_blend_minmax' ); - - if ( extension !== null ) { - - if ( p === MinEquation ) return extension.MIN_EXT; - if ( p === MaxEquation ) return extension.MAX_EXT; - - } - - } - - if ( p === UnsignedInt248Type ) { - - extension = extensions.get( 'WEBGL_depth_texture' ); - - if ( extension !== null ) return extension.UNSIGNED_INT_24_8_WEBGL; - - } - - return 0; - - } - } /** @@ -24135,17 +24848,17 @@ function update() { - requestAnimationFrame( update ); - if ( video.readyState >= video.HAVE_CURRENT_DATA ) { scope.needsUpdate = true; } + requestAnimationFrame( update ); + } - update(); + requestAnimationFrame( update ); } @@ -24180,21 +24893,6 @@ CompressedTexture.prototype.isCompressedTexture = true; - /** - * @author mrdoob / http://mrdoob.com/ - */ - - function CanvasTexture( canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) { - - Texture.call( this, canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ); - - this.needsUpdate = true; - - } - - CanvasTexture.prototype = Object.create( Texture.prototype ); - CanvasTexture.prototype.constructor = CanvasTexture; - /** * @author Matt DesLauriers / @mattdesl * @author atix / arthursilber.de @@ -24206,7 +24904,7 @@ if ( format !== DepthFormat && format !== DepthStencilFormat ) { - throw new Error( 'DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat' ) + throw new Error( 'DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat' ); } @@ -25854,7 +26552,7 @@ if ( indices ) return vertIndices; return result; - } + }; } )(), @@ -26192,7 +26890,7 @@ hIdx, nextIdx, intersection; for ( ihIdx = 0; ihIdx < indepHoles.length; ihIdx ++ ) { - chkHole = holes[ indepHoles[ ihIdx ]]; + chkHole = holes[ indepHoles[ ihIdx ] ]; for ( hIdx = 0; hIdx < chkHole.length; hIdx ++ ) { nextIdx = hIdx + 1; nextIdx %= chkHole.length; @@ -26225,7 +26923,7 @@ counter --; if ( counter < 0 ) { - console.log( "Infinite Loop! Holes left:" + indepHoles.length + ", Probably Hole outside Shape!" ); + console.log( 'THREE.ShapeUtils: Infinite Loop! Holes left:" + indepHoles.length + ", Probably Hole outside Shape!' ); break; } @@ -26243,7 +26941,7 @@ holeIdx = indepHoles[ h ]; // prevent multiple checks - cutKey = shapePt.x + ":" + shapePt.y + ":" + holeIdx; + cutKey = shapePt.x + ':' + shapePt.y + ':' + holeIdx; if ( failedCuts[ cutKey ] !== undefined ) continue; hole = holes[ holeIdx ]; @@ -26308,11 +27006,11 @@ for ( i = 0, il = allpoints.length; i < il; i ++ ) { - key = allpoints[ i ].x + ":" + allpoints[ i ].y; + key = allpoints[ i ].x + ':' + allpoints[ i ].y; if ( allPointsMap[ key ] !== undefined ) { - console.warn( "THREE.ShapeUtils: Duplicate point", key, i ); + console.warn( 'THREE.ShapeUtils: Duplicate point', key, i ); } @@ -26334,7 +27032,7 @@ for ( f = 0; f < 3; f ++ ) { - key = face[ f ].x + ":" + face[ f ].y; + key = face[ f ].x + ':' + face[ f ].y; index = allPointsMap[ key ]; @@ -26411,7 +27109,6 @@ if ( typeof ( shapes ) === "undefined" ) { - shapes = []; return; } @@ -26566,8 +27263,6 @@ } - reverse = false; // If vertices are in order now, we shouldn't need to worry about them again (hopefully)! - } @@ -26611,7 +27306,7 @@ // inPt' is the intersection of the two lines parallel to the two // adjacent edges of inPt at a distance of 1 unit on the left side. - var v_trans_x, v_trans_y, shrink_by = 1; // resulting translation vector for inPt + var v_trans_x, v_trans_y, shrink_by; // resulting translation vector for inPt // good reading for geometry algorithms (here: line-line intersection) // http://geomalgorithms.com/a05-_intersect-1.html @@ -27216,7 +27911,7 @@ var font = parameters.font; - if ( ( font && font.isFont ) === false ) { + if ( ! ( font && font.isFont ) ) { console.error( 'THREE.TextGeometry: font parameter is not an instance of THREE.Font.' ); return new Geometry(); @@ -28508,43 +29203,28 @@ * @author mrdoob / http://mrdoob.com/ * * parameters = { + * color: , * opacity: * } */ function ShadowMaterial( parameters ) { - ShaderMaterial.call( this, { - uniforms: UniformsUtils.merge( [ - UniformsLib.lights, - { - opacity: { value: 1.0 } - } - ] ), - vertexShader: ShaderChunk[ 'shadow_vert' ], - fragmentShader: ShaderChunk[ 'shadow_frag' ] - } ); + Material.call( this ); + + this.type = 'ShadowMaterial'; + + this.color = new Color( 0x000000 ); + this.opacity = 1.0; this.lights = true; this.transparent = true; - Object.defineProperties( this, { - opacity: { - enumerable: true, - get: function () { - return this.uniforms.opacity.value; - }, - set: function ( value ) { - this.uniforms.opacity.value = value; - } - } - } ); - this.setValues( parameters ); } - ShadowMaterial.prototype = Object.create( ShaderMaterial.prototype ); + ShadowMaterial.prototype = Object.create( Material.prototype ); ShadowMaterial.prototype.constructor = ShadowMaterial; ShadowMaterial.prototype.isShadowMaterial = true; @@ -29007,7 +29687,7 @@ function MeshNormalMaterial( parameters ) { - Material.call( this, parameters ); + Material.call( this ); this.type = 'MeshNormalMaterial'; @@ -29207,36 +29887,26 @@ function LineDashedMaterial( parameters ) { - Material.call( this ); + LineBasicMaterial.call( this ); this.type = 'LineDashedMaterial'; - this.color = new Color( 0xffffff ); - - this.linewidth = 1; - this.scale = 1; this.dashSize = 3; this.gapSize = 1; - this.lights = false; - this.setValues( parameters ); } - LineDashedMaterial.prototype = Object.create( Material.prototype ); + LineDashedMaterial.prototype = Object.create( LineBasicMaterial.prototype ); LineDashedMaterial.prototype.constructor = LineDashedMaterial; LineDashedMaterial.prototype.isLineDashedMaterial = true; LineDashedMaterial.prototype.copy = function ( source ) { - Material.prototype.copy.call( this, source ); - - this.color.copy( source.color ); - - this.linewidth = source.linewidth; + LineBasicMaterial.prototype.copy.call( this, source ); this.scale = source.scale; this.dashSize = source.dashSize; @@ -29261,6 +29931,7 @@ MeshNormalMaterial: MeshNormalMaterial, MeshLambertMaterial: MeshLambertMaterial, MeshDepthMaterial: MeshDepthMaterial, + MeshDistanceMaterial: MeshDistanceMaterial, MeshBasicMaterial: MeshBasicMaterial, LineDashedMaterial: LineDashedMaterial, LineBasicMaterial: LineBasicMaterial, @@ -29445,9 +30116,8 @@ case 'arraybuffer': case 'blob': - response = new ArrayBuffer( data.length ); - - var view = new Uint8Array( response ); + + var view = new Uint8Array( data.length ); for ( var i = 0; i < data.length; i ++ ) { @@ -29457,9 +30127,12 @@ if ( responseType === 'blob' ) { - response = new Blob( [ response ], { type: mimeType } ); + response = new Blob( [ view.buffer ], { type: mimeType } ); - } + } else { + + response = view.buffer; + } break; @@ -29484,7 +30157,7 @@ } - // Wait for next browser tick + // Wait for next browser tick like standard XMLHttpRequest event dispatching does window.setTimeout( function () { if ( onLoad ) onLoad( response ); @@ -29495,7 +30168,7 @@ } catch ( error ) { - // Wait for next browser tick + // Wait for next browser tick like standard XMLHttpRequest event dispatching does window.setTimeout( function () { if ( onError ) onError( error ); @@ -29857,6 +30530,8 @@ Object.assign( ImageLoader.prototype, { + crossOrigin: 'Anonymous', + load: function ( url, onLoad, onProgress, onError ) { if ( url === undefined ) url = ''; @@ -29954,6 +30629,8 @@ Object.assign( CubeTextureLoader.prototype, { + crossOrigin: 'Anonymous', + load: function ( urls, onLoad, onProgress, onError ) { var texture = new CubeTexture(); @@ -30022,6 +30699,8 @@ Object.assign( TextureLoader.prototype, { + crossOrigin: 'Anonymous', + load: function ( url, onLoad, onProgress, onError ) { var loader = new ImageLoader( this.manager ); @@ -31802,7 +32481,7 @@ } else { - // by default, we asssume a constructor compatible with the base + // by default, we assume a constructor compatible with the base return new trackType( json.name, json.times, json.values, json.interpolation ); @@ -32306,7 +32985,7 @@ if ( json.fragmentShader !== undefined ) material.fragmentShader = json.fragmentShader; if ( json.vertexColors !== undefined ) material.vertexColors = json.vertexColors; if ( json.fog !== undefined ) material.fog = json.fog; - if ( json.shading !== undefined ) material.shading = json.shading; + if ( json.flatShading !== undefined ) material.flatShading = json.flatShading; if ( json.blending !== undefined ) material.blending = json.blending; if ( json.side !== undefined ) material.side = json.side; if ( json.opacity !== undefined ) material.opacity = json.opacity; @@ -32319,8 +32998,17 @@ if ( json.wireframeLinewidth !== undefined ) material.wireframeLinewidth = json.wireframeLinewidth; if ( json.wireframeLinecap !== undefined ) material.wireframeLinecap = json.wireframeLinecap; if ( json.wireframeLinejoin !== undefined ) material.wireframeLinejoin = json.wireframeLinejoin; + if ( json.skinning !== undefined ) material.skinning = json.skinning; if ( json.morphTargets !== undefined ) material.morphTargets = json.morphTargets; + if ( json.dithering !== undefined ) material.dithering = json.dithering; + + if ( json.visible !== undefined ) material.visible = json.visible; + if ( json.userData !== undefined ) material.userData = json.userData; + + // Deprecated + + if ( json.shading !== undefined ) material.flatShading = json.shading === 1; // THREE.FlatShading // for PointsMaterial @@ -32476,7 +33164,8 @@ var TYPED_ARRAYS = { Int8Array: Int8Array, Uint8Array: Uint8Array, - Uint8ClampedArray: Uint8ClampedArray, + // Workaround for IE11 pre KB2929437. See #11440 + Uint8ClampedArray: typeof Uint8ClampedArray !== 'undefined' ? Uint8ClampedArray : Uint8Array, Int16Array: Int16Array, Uint16Array: Uint16Array, Int32Array: Int32Array, @@ -33822,6 +34511,8 @@ if ( data.offset !== undefined ) texture.offset.fromArray( data.offset ); if ( data.repeat !== undefined ) texture.repeat.fromArray( data.repeat ); + if ( data.rotation !== undefined ) texture.rotation = data.rotation; + if ( data.wrap !== undefined ) { texture.wrapS = parseConstant( data.wrap[ 0 ], TEXTURE_WRAPPING ); @@ -34091,9 +34782,11 @@ if ( data.children !== undefined ) { - for ( var child in data.children ) { + var children = data.children; - object.add( this.parseObject( data.children[ child ], geometries, materials ) ); + for ( var i = 0; i < children.length; i ++ ) { + + object.add( this.parseObject( children[ i ], geometries, materials ) ); } @@ -35727,6 +36420,7 @@ var scope = this; var loader = new FileLoader( this.manager ); + loader.setPath( this.path ); loader.load( url, function ( text ) { var json; @@ -35754,6 +36448,13 @@ return new Font( json ); + }, + + setPath: function ( value ) { + + this.path = value; + return this; + } } ); @@ -35956,7 +36657,7 @@ this.renderTarget = new WebGLRenderTargetCube( cubeResolution, cubeResolution, options ); this.renderTarget.texture.name = "CubeCamera"; - this.updateCubeMap = function ( renderer, scene ) { + this.update = function ( renderer, scene ) { if ( this.parent === null ) this.updateMatrixWorld(); @@ -35989,31 +36690,27 @@ }; - } - - CubeCamera.prototype = Object.create( Object3D.prototype ); - CubeCamera.prototype.constructor = CubeCamera; + this.clear = function ( renderer, color, depth, stencil ) { - /** - * @author mrdoob / http://mrdoob.com/ - */ + var renderTarget = this.renderTarget; - function ArrayCamera( array ) { + for ( var i = 0; i < 6; i ++ ) { - PerspectiveCamera.call( this ); + renderTarget.activeCubeFace = i; + renderer.setRenderTarget( renderTarget ); - this.enabled = false; - this.cameras = array || []; + renderer.clear( color, depth, stencil ); - } + } - ArrayCamera.prototype = Object.assign( Object.create( PerspectiveCamera.prototype ), { + renderer.setRenderTarget( null ); - constructor: ArrayCamera, + }; - isArrayCamera: true + } - } ); + CubeCamera.prototype = Object.create( Object3D.prototype ); + CubeCamera.prototype.constructor = CubeCamera; /** * @author mrdoob / http://mrdoob.com/ @@ -36424,7 +37121,7 @@ return this.gain.gain.value; }, - + setVolume: function ( value ) { this.gain.gain.value = value; @@ -36875,6 +37572,19 @@ }, + /** + * Replaces spaces with underscores and removes unsupported characters from + * node names, to ensure compatibility with parseTrackName(). + * + * @param {string} name Node name to be sanitized. + * @return {string} + */ + sanitizeNodeName: function ( name ) { + + return name.replace( /\s/g, '_' ).replace( /[^\w-]/g, '' ); + + }, + parseTrackName: function () { // Parent directories, delimited by '/' or ':'. Currently unused, but must @@ -39796,6 +40506,7 @@ this.getElapsedTime(); this.running = false; + this.autoStart = false; }, @@ -39971,322 +40682,6 @@ } ); - /** - * @author alteredq / http://alteredqualia.com/ - */ - - function MorphBlendMesh( geometry, material ) { - - Mesh.call( this, geometry, material ); - - this.animationsMap = {}; - this.animationsList = []; - - // prepare default animation - // (all frames played together in 1 second) - - var numFrames = this.geometry.morphTargets.length; - - var name = "__default"; - - var startFrame = 0; - var endFrame = numFrames - 1; - - var fps = numFrames / 1; - - this.createAnimation( name, startFrame, endFrame, fps ); - this.setAnimationWeight( name, 1 ); - - } - - MorphBlendMesh.prototype = Object.create( Mesh.prototype ); - MorphBlendMesh.prototype.constructor = MorphBlendMesh; - - MorphBlendMesh.prototype.createAnimation = function ( name, start, end, fps ) { - - var animation = { - - start: start, - end: end, - - length: end - start + 1, - - fps: fps, - duration: ( end - start ) / fps, - - lastFrame: 0, - currentFrame: 0, - - active: false, - - time: 0, - direction: 1, - weight: 1, - - directionBackwards: false, - mirroredLoop: false - - }; - - this.animationsMap[ name ] = animation; - this.animationsList.push( animation ); - - }; - - MorphBlendMesh.prototype.autoCreateAnimations = function ( fps ) { - - var pattern = /([a-z]+)_?(\d+)/i; - - var firstAnimation, frameRanges = {}; - - var geometry = this.geometry; - - for ( var i = 0, il = geometry.morphTargets.length; i < il; i ++ ) { - - var morph = geometry.morphTargets[ i ]; - var chunks = morph.name.match( pattern ); - - if ( chunks && chunks.length > 1 ) { - - var name = chunks[ 1 ]; - - if ( ! frameRanges[ name ] ) frameRanges[ name ] = { start: Infinity, end: - Infinity }; - - var range = frameRanges[ name ]; - - if ( i < range.start ) range.start = i; - if ( i > range.end ) range.end = i; - - if ( ! firstAnimation ) firstAnimation = name; - - } - - } - - for ( var name in frameRanges ) { - - var range = frameRanges[ name ]; - this.createAnimation( name, range.start, range.end, fps ); - - } - - this.firstAnimation = firstAnimation; - - }; - - MorphBlendMesh.prototype.setAnimationDirectionForward = function ( name ) { - - var animation = this.animationsMap[ name ]; - - if ( animation ) { - - animation.direction = 1; - animation.directionBackwards = false; - - } - - }; - - MorphBlendMesh.prototype.setAnimationDirectionBackward = function ( name ) { - - var animation = this.animationsMap[ name ]; - - if ( animation ) { - - animation.direction = - 1; - animation.directionBackwards = true; - - } - - }; - - MorphBlendMesh.prototype.setAnimationFPS = function ( name, fps ) { - - var animation = this.animationsMap[ name ]; - - if ( animation ) { - - animation.fps = fps; - animation.duration = ( animation.end - animation.start ) / animation.fps; - - } - - }; - - MorphBlendMesh.prototype.setAnimationDuration = function ( name, duration ) { - - var animation = this.animationsMap[ name ]; - - if ( animation ) { - - animation.duration = duration; - animation.fps = ( animation.end - animation.start ) / animation.duration; - - } - - }; - - MorphBlendMesh.prototype.setAnimationWeight = function ( name, weight ) { - - var animation = this.animationsMap[ name ]; - - if ( animation ) { - - animation.weight = weight; - - } - - }; - - MorphBlendMesh.prototype.setAnimationTime = function ( name, time ) { - - var animation = this.animationsMap[ name ]; - - if ( animation ) { - - animation.time = time; - - } - - }; - - MorphBlendMesh.prototype.getAnimationTime = function ( name ) { - - var time = 0; - - var animation = this.animationsMap[ name ]; - - if ( animation ) { - - time = animation.time; - - } - - return time; - - }; - - MorphBlendMesh.prototype.getAnimationDuration = function ( name ) { - - var duration = - 1; - - var animation = this.animationsMap[ name ]; - - if ( animation ) { - - duration = animation.duration; - - } - - return duration; - - }; - - MorphBlendMesh.prototype.playAnimation = function ( name ) { - - var animation = this.animationsMap[ name ]; - - if ( animation ) { - - animation.time = 0; - animation.active = true; - - } else { - - console.warn( "THREE.MorphBlendMesh: animation[" + name + "] undefined in .playAnimation()" ); - - } - - }; - - MorphBlendMesh.prototype.stopAnimation = function ( name ) { - - var animation = this.animationsMap[ name ]; - - if ( animation ) { - - animation.active = false; - - } - - }; - - MorphBlendMesh.prototype.update = function ( delta ) { - - for ( var i = 0, il = this.animationsList.length; i < il; i ++ ) { - - var animation = this.animationsList[ i ]; - - if ( ! animation.active ) continue; - - var frameTime = animation.duration / animation.length; - - animation.time += animation.direction * delta; - - if ( animation.mirroredLoop ) { - - if ( animation.time > animation.duration || animation.time < 0 ) { - - animation.direction *= - 1; - - if ( animation.time > animation.duration ) { - - animation.time = animation.duration; - animation.directionBackwards = true; - - } - - if ( animation.time < 0 ) { - - animation.time = 0; - animation.directionBackwards = false; - - } - - } - - } else { - - animation.time = animation.time % animation.duration; - - if ( animation.time < 0 ) animation.time += animation.duration; - - } - - var keyframe = animation.start + _Math.clamp( Math.floor( animation.time / frameTime ), 0, animation.length - 1 ); - var weight = animation.weight; - - if ( keyframe !== animation.currentFrame ) { - - this.morphTargetInfluences[ animation.lastFrame ] = 0; - this.morphTargetInfluences[ animation.currentFrame ] = 1 * weight; - - this.morphTargetInfluences[ keyframe ] = 0; - - animation.lastFrame = animation.currentFrame; - animation.currentFrame = keyframe; - - } - - var mix = ( animation.time % frameTime ) / frameTime; - - if ( animation.directionBackwards ) mix = 1 - mix; - - if ( animation.currentFrame !== animation.lastFrame ) { - - this.morphTargetInfluences[ animation.currentFrame ] = mix * weight; - this.morphTargetInfluences[ animation.lastFrame ] = ( 1 - mix ) * weight; - - } else { - - this.morphTargetInfluences[ animation.currentFrame ] = weight; - - } - - } - - }; - /** * @author alteredq / http://alteredqualia.com/ */ @@ -40308,7 +40703,7 @@ /** * @author mrdoob / http://mrdoob.com/ * @author WestLangley / http://github.com/WestLangley - */ + */ function VertexNormalsHelper( object, size, hex, linewidth ) { @@ -40453,9 +40848,9 @@ * @author alteredq / http://alteredqualia.com/ * @author mrdoob / http://mrdoob.com/ * @author WestLangley / http://github.com/WestLangley - */ + */ - function SpotLightHelper( light ) { + function SpotLightHelper( light, color ) { Object3D.call( this ); @@ -40465,6 +40860,8 @@ this.matrix = light.matrixWorld; this.matrixAutoUpdate = false; + this.color = color; + var geometry = new BufferGeometry(); var positions = [ @@ -40515,6 +40912,8 @@ return function update() { + this.light.updateMatrixWorld(); + var coneLength = this.light.distance ? this.light.distance : 1000; var coneWidth = coneLength * Math.tan( this.light.angle ); @@ -40525,7 +40924,15 @@ this.cone.lookAt( vector2.sub( vector ) ); - this.cone.material.color.copy( this.light.color ); + if ( this.color !== undefined ) { + + this.cone.material.color.set( this.color ); + + } else { + + this.cone.material.color.copy( this.light.color ); + + } }; @@ -40539,9 +40946,29 @@ * @author Mugen87 / https://github.com/Mugen87 */ + function getBoneList( object ) { + + var boneList = []; + + if ( object && object.isBone ) { + + boneList.push( object ); + + } + + for ( var i = 0; i < object.children.length; i ++ ) { + + boneList.push.apply( boneList, getBoneList( object.children[ i ] ) ); + + } + + return boneList; + + } + function SkeletonHelper( object ) { - this.bones = this.getBoneList( object ); + var bones = getBoneList( object ); var geometry = new BufferGeometry(); @@ -40551,9 +40978,9 @@ var color1 = new Color( 0, 0, 1 ); var color2 = new Color( 0, 1, 0 ); - for ( var i = 0; i < this.bones.length; i ++ ) { + for ( var i = 0; i < bones.length; i ++ ) { - var bone = this.bones[ i ]; + var bone = bones[ i ]; if ( bone.parent && bone.parent.isBone ) { @@ -40574,55 +41001,35 @@ LineSegments.call( this, geometry, material ); this.root = object; + this.bones = bones; this.matrix = object.matrixWorld; this.matrixAutoUpdate = false; - this.update(); - } - SkeletonHelper.prototype = Object.create( LineSegments.prototype ); SkeletonHelper.prototype.constructor = SkeletonHelper; - SkeletonHelper.prototype.getBoneList = function( object ) { - - var boneList = []; - - if ( object && object.isBone ) { - - boneList.push( object ); - - } - - for ( var i = 0; i < object.children.length; i ++ ) { - - boneList.push.apply( boneList, this.getBoneList( object.children[ i ] ) ); - - } - - return boneList; - - }; - - SkeletonHelper.prototype.update = function () { + SkeletonHelper.prototype.updateMatrixWorld = function () { var vector = new Vector3(); var boneMatrix = new Matrix4(); var matrixWorldInv = new Matrix4(); - return function update() { + return function updateMatrixWorld( force ) { + + var bones = this.bones; var geometry = this.geometry; var position = geometry.getAttribute( 'position' ); matrixWorldInv.getInverse( this.root.matrixWorld ); - for ( var i = 0, j = 0; i < this.bones.length; i ++ ) { + for ( var i = 0, j = 0; i < bones.length; i ++ ) { - var bone = this.bones[ i ]; + var bone = bones[ i ]; if ( bone.parent && bone.parent.isBone ) { @@ -40642,6 +41049,8 @@ geometry.getAttribute( 'position' ).needsUpdate = true; + Object3D.prototype.updateMatrixWorld.call( this, force ); + }; }(); @@ -40651,20 +41060,24 @@ * @author mrdoob / http://mrdoob.com/ */ - function PointLightHelper( light, sphereSize ) { + function PointLightHelper( light, sphereSize, color ) { this.light = light; this.light.updateMatrixWorld(); + this.color = color; + var geometry = new SphereBufferGeometry( sphereSize, 4, 2 ); var material = new MeshBasicMaterial( { wireframe: true, fog: false } ); - material.color.copy( this.light.color ); Mesh.call( this, geometry, material ); this.matrix = this.light.matrixWorld; this.matrixAutoUpdate = false; + this.update(); + + /* var distanceGeometry = new THREE.IcosahedronGeometry( 1, 2 ); var distanceMaterial = new THREE.MeshBasicMaterial( { color: hexColor, fog: false, wireframe: true, opacity: 0.1, transparent: true } ); @@ -40701,7 +41114,15 @@ PointLightHelper.prototype.update = function () { - this.material.color.copy( this.light.color ); + if ( this.color !== undefined ) { + + this.material.color.set( this.color ); + + } else { + + this.material.color.copy( this.light.color ); + + } /* var d = this.light.distance; @@ -40726,7 +41147,7 @@ * @author WestLangley / http://github.com/WestLangley */ - function RectAreaLightHelper( light ) { + function RectAreaLightHelper( light, color ) { Object3D.call( this ); @@ -40736,13 +41157,17 @@ this.matrix = light.matrixWorld; this.matrixAutoUpdate = false; - var material = new LineBasicMaterial( { color: light.color } ); + this.color = color; + + var material = new LineBasicMaterial( { fog: false } ); var geometry = new BufferGeometry(); geometry.addAttribute( 'position', new BufferAttribute( new Float32Array( 5 * 3 ), 3 ) ); - this.add( new Line( geometry, material ) ); + this.line = new Line( geometry, material ); + this.add( this.line ); + this.update(); @@ -40760,18 +41185,12 @@ RectAreaLightHelper.prototype.update = function () { - var line = this.children[ 0 ]; - - // update material - - line.material.color.copy( this.light.color ); - // calculate new dimensions of the helper var hx = this.light.width * 0.5; var hy = this.light.height * 0.5; - var position = line.geometry.attributes.position; + var position = this.line.geometry.attributes.position; var array = position.array; // update vertices @@ -40784,6 +41203,16 @@ position.needsUpdate = true; + if ( this.color !== undefined ) { + + this.line.material.color.set( this.color ); + + } else { + + this.line.material.color.copy( this.light.color ); + + } + }; /** @@ -40792,7 +41221,7 @@ * @author Mugen87 / https://github.com/Mugen87 */ - function HemisphereLightHelper( light, size ) { + function HemisphereLightHelper( light, size, color ) { Object3D.call( this ); @@ -40802,17 +41231,20 @@ this.matrix = light.matrixWorld; this.matrixAutoUpdate = false; + this.color = color; + var geometry = new OctahedronBufferGeometry( size ); geometry.rotateY( Math.PI * 0.5 ); - var material = new MeshBasicMaterial( { vertexColors: VertexColors, wireframe: true } ); + this.material = new MeshBasicMaterial( { wireframe: true, fog: false } ); + if ( this.color === undefined ) this.material.vertexColors = VertexColors; var position = geometry.getAttribute( 'position' ); var colors = new Float32Array( position.count * 3 ); geometry.addAttribute( 'color', new BufferAttribute( colors, 3 ) ); - this.add( new Mesh( geometry, material ) ); + this.add( new Mesh( geometry, this.material ) ); this.update(); @@ -40839,23 +41271,31 @@ var mesh = this.children[ 0 ]; - var colors = mesh.geometry.getAttribute( 'color' ); + if ( this.color !== undefined ) { - color1.copy( this.light.color ); - color2.copy( this.light.groundColor ); + this.material.color.set( this.color ); + + } else { - for ( var i = 0, l = colors.count; i < l; i ++ ) { + var colors = mesh.geometry.getAttribute( 'color' ); - var color = ( i < ( l / 2 ) ) ? color1 : color2; + color1.copy( this.light.color ); + color2.copy( this.light.groundColor ); - colors.setXYZ( i, color.r, color.g, color.b ); + for ( var i = 0, l = colors.count; i < l; i ++ ) { + + var color = ( i < ( l / 2 ) ) ? color1 : color2; + + colors.setXYZ( i, color.r, color.g, color.b ); + + } + + colors.needsUpdate = true; } mesh.lookAt( vector.setFromMatrixPosition( this.light.matrixWorld ).negate() ); - colors.needsUpdate = true; - }; }(); @@ -40994,7 +41434,7 @@ /** * @author mrdoob / http://mrdoob.com/ * @author WestLangley / http://github.com/WestLangley - */ + */ function FaceNormalsHelper( object, size, hex, linewidth ) { @@ -41106,7 +41546,7 @@ * @author WestLangley / http://github.com/WestLangley */ - function DirectionalLightHelper( light, size ) { + function DirectionalLightHelper( light, size, color ) { Object3D.call( this ); @@ -41116,6 +41556,8 @@ this.matrix = light.matrixWorld; this.matrixAutoUpdate = false; + this.color = color; + if ( size === undefined ) size = 1; var geometry = new BufferGeometry(); @@ -41129,12 +41571,14 @@ var material = new LineBasicMaterial( { fog: false } ); - this.add( new Line( geometry, material ) ); + this.lightPlane = new Line( geometry, material ); + this.add( this.lightPlane ); geometry = new BufferGeometry(); geometry.addAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 0, 1 ], 3 ) ); - this.add( new Line( geometry, material )); + this.targetLine = new Line( geometry, material ); + this.add( this.targetLine ); this.update(); @@ -41145,13 +41589,10 @@ DirectionalLightHelper.prototype.dispose = function () { - var lightPlane = this.children[ 0 ]; - var targetLine = this.children[ 1 ]; - - lightPlane.geometry.dispose(); - lightPlane.material.dispose(); - targetLine.geometry.dispose(); - targetLine.material.dispose(); + this.lightPlane.geometry.dispose(); + this.lightPlane.material.dispose(); + this.targetLine.geometry.dispose(); + this.targetLine.material.dispose(); }; @@ -41167,14 +41608,22 @@ v2.setFromMatrixPosition( this.light.target.matrixWorld ); v3.subVectors( v2, v1 ); - var lightPlane = this.children[ 0 ]; - var targetLine = this.children[ 1 ]; + this.lightPlane.lookAt( v3 ); + + if ( this.color !== undefined ) { + + this.lightPlane.material.color.set( this.color ); + this.targetLine.material.color.set( this.color ); - lightPlane.lookAt( v3 ); - lightPlane.material.color.copy( this.light.color ); + } else { + + this.lightPlane.material.color.copy( this.light.color ); + this.targetLine.material.color.copy( this.light.color ); + + } - targetLine.lookAt( v3 ); - targetLine.scale.z = v3.length(); + this.targetLine.lookAt( v3 ); + this.targetLine.scale.z = v3.length(); }; @@ -41476,6 +41925,104 @@ }; + /** + * @author WestLangley / http://github.com/WestLangley + */ + + function Box3Helper( box, hex ) { + + this.type = 'Box3Helper'; + + this.box = box; + + var color = ( hex !== undefined ) ? hex : 0xffff00; + + var indices = new Uint16Array( [ 0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7 ] ); + + var positions = [ 1, 1, 1, - 1, 1, 1, - 1, - 1, 1, 1, - 1, 1, 1, 1, - 1, - 1, 1, - 1, - 1, - 1, - 1, 1, - 1, - 1 ]; + + var geometry = new BufferGeometry(); + + geometry.setIndex( new BufferAttribute( indices, 1 ) ); + + geometry.addAttribute( 'position', new Float32BufferAttribute( positions, 3 ) ); + + LineSegments.call( this, geometry, new LineBasicMaterial( { color: color } ) ); + + this.geometry.computeBoundingSphere(); + + } + + Box3Helper.prototype = Object.create( LineSegments.prototype ); + Box3Helper.prototype.constructor = Box3Helper; + + Box3Helper.prototype.updateMatrixWorld = function ( force ) { + + var box = this.box; + + if ( box.isEmpty() ) return; + + box.getCenter( this.position ); + + box.getSize( this.scale ); + + this.scale.multiplyScalar( 0.5 ); + + Object3D.prototype.updateMatrixWorld.call( this, force ); + + }; + + /** + * @author WestLangley / http://github.com/WestLangley + */ + + function PlaneHelper( plane, size, hex ) { + + this.type = 'PlaneHelper'; + + this.plane = plane; + + this.size = ( size === undefined ) ? 1 : size; + + var color = ( hex !== undefined ) ? hex : 0xffff00; + + var positions = [ 1, - 1, 1, - 1, 1, 1, - 1, - 1, 1, 1, 1, 1, - 1, 1, 1, - 1, - 1, 1, 1, - 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0 ]; + + var geometry = new BufferGeometry(); + geometry.addAttribute( 'position', new Float32BufferAttribute( positions, 3 ) ); + geometry.computeBoundingSphere(); + + Line.call( this, geometry, new LineBasicMaterial( { color: color } ) ); + + // + + var positions2 = [ 1, 1, 1, - 1, 1, 1, - 1, - 1, 1, 1, 1, 1, - 1, - 1, 1, 1, - 1, 1 ]; + + var geometry2 = new BufferGeometry(); + geometry2.addAttribute( 'position', new Float32BufferAttribute( positions2, 3 ) ); + geometry2.computeBoundingSphere(); + + this.add( new Mesh( geometry2, new MeshBasicMaterial( { color: color, opacity: 0.2, transparent: true, depthWrite: false } ) ) ); + + } + + PlaneHelper.prototype = Object.create( Line.prototype ); + PlaneHelper.prototype.constructor = PlaneHelper; + + PlaneHelper.prototype.updateMatrixWorld = function ( force ) { + + var scale = - this.plane.constant; + + if ( Math.abs( scale ) < 1e-8 ) scale = 1e-8; // sign does not matter + + this.scale.set( 0.5 * this.size, 0.5 * this.size, scale ); + + this.lookAt( this.plane.normal ); + + Object3D.prototype.updateMatrixWorld.call( this, force ); + + }; + /** * @author WestLangley / http://github.com/WestLangley * @author zz85 / http://github.com/zz85 @@ -41917,9 +42464,7 @@ attach: function ( child, scene, parent ) { - var matrixWorldInverse = new Matrix4(); - matrixWorldInverse.getInverse( parent.matrixWorld ); - child.applyMatrix( matrixWorldInverse ); + child.applyMatrix( new Matrix4().getInverse( parent.matrixWorld ) ); scene.remove( child ); parent.add( child ); @@ -42182,6 +42727,12 @@ }; + SkeletonHelper.prototype.update = function () { + + console.error( 'THREE.SkeletonHelper: update() no longer needs to be called.' ); + + }; + function WireframeHelper( object, hex ) { console.warn( 'THREE.WireframeHelper has been removed. Use THREE.WireframeGeometry instead.' ); @@ -42299,8 +42850,7 @@ }, multiplyVector3Array: function ( a ) { - console.warn( 'THREE.Matrix3: .multiplyVector3Array() has been renamed. Use matrix.applyToVector3Array( array ) instead.' ); - return this.applyToVector3Array( a ); + console.error( 'THREE.Matrix3: .multiplyVector3Array() has been removed.' ); }, applyToBuffer: function( buffer, offset, length ) { @@ -42369,8 +42919,7 @@ }, multiplyVector3Array: function ( a ) { - console.warn( 'THREE.Matrix4: .multiplyVector3Array() has been renamed. Use matrix.applyToVector3Array( array ) instead.' ); - return this.applyToVector3Array( a ); + console.error( 'THREE.Matrix4: .multiplyVector3Array() has been removed.' ); }, rotateAxis: function ( v ) { @@ -42893,6 +43442,20 @@ console.warn( 'THREE.Material: .wrapRGB has been removed.' ); return new Color(); + } + }, + + shading: { + get: function () { + + console.error( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' ); + + }, + set: function ( value ) { + + console.warn( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' ); + this.flatShading = ( value === FlatShading ); + } } @@ -42946,6 +43509,27 @@ }, + getMaxAnisotropy: function () { + + console.warn( 'THREE.WebGLRenderer: .getMaxAnisotropy() is now .capabilities.getMaxAnisotropy().' ); + return this.capabilities.getMaxAnisotropy(); + + }, + + getPrecision: function () { + + console.warn( 'THREE.WebGLRenderer: .getPrecision() is now .capabilities.precision.' ); + return this.capabilities.precision; + + }, + + resetGLState: function () { + + console.warn( 'THREE.WebGLRenderer: .resetGLState() is now .state.reset().' ); + return this.state.reset(); + + }, + supportsFloatTextures: function () { console.warn( 'THREE.WebGLRenderer: .supportsFloatTextures() is now .extensions.get( \'OES_texture_float\' ).' ); @@ -43257,6 +43841,15 @@ // + CubeCamera.prototype.updateCubeMap = function ( renderer, scene ) { + + console.warn( 'THREE.CubeCamera: .updateCubeMap() is now .update().' ); + return this.update( renderer, scene ); + + }; + + // + var GeometryUtils = { merge: function ( geometry1, geometry2, materialIndexOffset ) { @@ -43494,7 +44087,6 @@ exports.Vector2 = Vector2; exports.Quaternion = Quaternion; exports.Color = Color; - exports.MorphBlendMesh = MorphBlendMesh; exports.ImmediateRenderObject = ImmediateRenderObject; exports.VertexNormalsHelper = VertexNormalsHelper; exports.SpotLightHelper = SpotLightHelper; @@ -43508,6 +44100,8 @@ exports.DirectionalLightHelper = DirectionalLightHelper; exports.CameraHelper = CameraHelper; exports.BoxHelper = BoxHelper; + exports.Box3Helper = Box3Helper; + exports.PlaneHelper = PlaneHelper; exports.ArrowHelper = ArrowHelper; exports.AxisHelper = AxisHelper; exports.CatmullRomCurve3 = CatmullRomCurve3; @@ -43528,6 +44122,7 @@ exports.Curve = Curve; exports.ShapeUtils = ShapeUtils; exports.SceneUtils = SceneUtils; + exports.WebGLUtils = WebGLUtils; exports.WireframeGeometry = WireframeGeometry; exports.ParametricGeometry = ParametricGeometry; exports.ParametricBufferGeometry = ParametricBufferGeometry; @@ -43582,6 +44177,7 @@ exports.MeshNormalMaterial = MeshNormalMaterial; exports.MeshLambertMaterial = MeshLambertMaterial; exports.MeshDepthMaterial = MeshDepthMaterial; + exports.MeshDistanceMaterial = MeshDistanceMaterial; exports.MeshBasicMaterial = MeshBasicMaterial; exports.LineDashedMaterial = LineDashedMaterial; exports.LineBasicMaterial = LineBasicMaterial; diff --git a/build/three.min.js b/build/three.min.js index f02ef25d824e30..2f60dec766148d 100644 --- a/build/three.min.js +++ b/build/three.min.js @@ -1,868 +1,885 @@ // threejs.org/license -(function(l,sa){"object"===typeof exports&&"undefined"!==typeof module?sa(exports):"function"===typeof define&&define.amd?define(["exports"],sa):sa(l.THREE=l.THREE||{})})(this,function(l){function sa(){}function E(a,b){this.x=a||0;this.y=b||0}function X(a,b,c,d,e,f,g,h,k,m){Object.defineProperty(this,"id",{value:jf++});this.uuid=Y.generateUUID();this.name="";this.image=void 0!==a?a:X.DEFAULT_IMAGE;this.mipmaps=[];this.mapping=void 0!==b?b:X.DEFAULT_MAPPING;this.wrapS=void 0!==c?c:1001;this.wrapT= -void 0!==d?d:1001;this.magFilter=void 0!==e?e:1006;this.minFilter=void 0!==f?f:1008;this.anisotropy=void 0!==k?k:1;this.format=void 0!==g?g:1023;this.type=void 0!==h?h:1009;this.offset=new E(0,0);this.repeat=new E(1,1);this.generateMipmaps=!0;this.premultiplyAlpha=!1;this.flipY=!0;this.unpackAlignment=4;this.encoding=void 0!==m?m:3E3;this.version=0;this.onUpdate=null}function ga(a,b,c,d){this.x=a||0;this.y=b||0;this.z=c||0;this.w=void 0!==d?d:1}function Db(a,b,c){this.uuid=Y.generateUUID();this.width= -a;this.height=b;this.scissor=new ga(0,0,a,b);this.scissorTest=!1;this.viewport=new ga(0,0,a,b);c=c||{};void 0===c.minFilter&&(c.minFilter=1006);this.texture=new X(void 0,void 0,c.wrapS,c.wrapT,c.magFilter,c.minFilter,c.format,c.type,c.anisotropy,c.encoding);this.depthBuffer=void 0!==c.depthBuffer?c.depthBuffer:!0;this.stencilBuffer=void 0!==c.stencilBuffer?c.stencilBuffer:!0;this.depthTexture=void 0!==c.depthTexture?c.depthTexture:null}function Eb(a,b,c){Db.call(this,a,b,c);this.activeMipMapLevel= -this.activeCubeFace=0}function qa(a,b,c,d){this._x=a||0;this._y=b||0;this._z=c||0;this._w=void 0!==d?d:1}function p(a,b,c){this.x=a||0;this.y=b||0;this.z=c||0}function J(){this.elements=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1];0=d||0 0 ) {\nfloat depth = gl_FragCoord.z / gl_FragCoord.w;\nfloat fogFactor = 0.0;\nif ( fogType == 1 ) {\nfogFactor = smoothstep( fogNear, fogFar, depth );\n} else {\nconst float LOG2 = 1.442695;\nfogFactor = exp2( - fogDensity * fogDensity * depth * depth * LOG2 );\nfogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 );\n}\ngl_FragColor = mix( gl_FragColor, vec4( fogColor, gl_FragColor.w ), fogFactor );\n}\n}"].join("\n")); -w.compileShader(Q);w.compileShader(K);w.attachShader(ja,Q);w.attachShader(ja,K);w.linkProgram(ja);G=ja;y=w.getAttribLocation(G,"position");v=w.getAttribLocation(G,"uv");c=w.getUniformLocation(G,"uvOffset");d=w.getUniformLocation(G,"uvScale");e=w.getUniformLocation(G,"rotation");f=w.getUniformLocation(G,"scale");g=w.getUniformLocation(G,"color");h=w.getUniformLocation(G,"map");k=w.getUniformLocation(G,"opacity");m=w.getUniformLocation(G,"modelViewMatrix");u=w.getUniformLocation(G,"projectionMatrix"); -q=w.getUniformLocation(G,"fogType");n=w.getUniformLocation(G,"fogDensity");t=w.getUniformLocation(G,"fogNear");l=w.getUniformLocation(G,"fogFar");r=w.getUniformLocation(G,"fogColor");x=w.getUniformLocation(G,"alphaTest");ja=document.createElementNS("http://www.w3.org/1999/xhtml","canvas");ja.width=8;ja.height=8;Q=ja.getContext("2d");Q.fillStyle="white";Q.fillRect(0,0,8,8);aa=new X(ja);aa.needsUpdate=!0}w.useProgram(G);S.initAttributes();S.enableAttribute(y);S.enableAttribute(v);S.disableUnusedAttributes(); -S.disable(w.CULL_FACE);S.enable(w.BLEND);w.bindBuffer(w.ARRAY_BUFFER,W);w.vertexAttribPointer(y,2,w.FLOAT,!1,16,0);w.vertexAttribPointer(v,2,w.FLOAT,!1,16,8);w.bindBuffer(w.ELEMENT_ARRAY_BUFFER,C);w.uniformMatrix4fv(u,!1,Gb.projectionMatrix.elements);S.activeTexture(w.TEXTURE0);w.uniform1i(h,0);Q=ja=0;(K=p.fog)?(w.uniform3f(r,K.color.r,K.color.g,K.color.b),K.isFog?(w.uniform1f(t,K.near),w.uniform1f(l,K.far),w.uniform1i(q,1),Q=ja=1):K.isFogExp2&&(w.uniform1f(n,K.density),w.uniform1i(q,2),Q=ja=2)): -(w.uniform1i(q,0),Q=ja=0);for(var K=0,V=b.length;Kb&&(b=a[c]);return b}function M(){Object.defineProperty(this,"id",{value:Td++});this.uuid=Y.generateUUID();this.name="";this.type="Geometry";this.vertices=[];this.colors=[];this.faces=[];this.faceVertexUvs=[[]];this.morphTargets=[];this.morphNormals=[];this.skinWeights=[];this.skinIndices=[];this.lineDistances=[];this.boundingSphere=this.boundingBox=null;this.groupsNeedUpdate=this.lineDistancesNeedUpdate= -this.colorsNeedUpdate=this.normalsNeedUpdate=this.uvsNeedUpdate=this.verticesNeedUpdate=this.elementsNeedUpdate=!1}function I(){Object.defineProperty(this,"id",{value:Td++});this.uuid=Y.generateUUID();this.name="";this.type="BufferGeometry";this.index=null;this.attributes={};this.morphAttributes={};this.groups=[];this.boundingSphere=this.boundingBox=null;this.drawRange={start:0,count:Infinity}}function Ca(a,b){B.call(this);this.type="Mesh";this.geometry=void 0!==a?a:new I;this.material=void 0!==b? -b:new Na({color:16777215*Math.random()});this.drawMode=0;this.updateMorphTargets()}function Ib(a,b,c,d,e,f){M.call(this);this.type="BoxGeometry";this.parameters={width:a,height:b,depth:c,widthSegments:d,heightSegments:e,depthSegments:f};this.fromBufferGeometry(new kb(a,b,c,d,e,f));this.mergeVertices()}function kb(a,b,c,d,e,f){function g(a,b,c,d,e,f,g,l,W,C,G){var aa=f/W,O=g/C,ca=f/2,la=g/2,E=l/2;g=W+1;var D=C+1,B=f=0,Q,K,V=new p;for(K=0;K/gm,function(a,c){var d=T[c]; -if(void 0===d)throw Error("Can not resolve #include <"+c+">");return Vd(d)})}function Oe(a){return a.replace(/for \( int i \= (\d+)\; i < (\d+)\; i \+\+ \) \{([\s\S]+?)(?=\})\}/g,function(a,c,d,e){a="";for(c=parseInt(c);cb||a.height>b){var c=b/Math.max(a.width,a.height),d=document.createElementNS("http://www.w3.org/1999/xhtml","canvas");d.width=Math.floor(a.width*c);d.height=Math.floor(a.height*c);d.getContext("2d").drawImage(a,0,0,a.width,a.height,0,0,d.width,d.height);console.warn("THREE.WebGLRenderer: image is too big ("+ -a.width+"x"+a.height+"). Resized to "+d.width+"x"+d.height,a);return d}return a}function k(a){return Y.isPowerOfTwo(a.width)&&Y.isPowerOfTwo(a.height)}function m(b){return 1003===b||1004===b||1005===b?a.NEAREST:a.LINEAR}function u(b){b=b.target;b.removeEventListener("dispose",u);a:{var c=d.get(b);if(b.image&&c.__image__webglTextureCube)a.deleteTexture(c.__image__webglTextureCube);else{if(void 0===c.__webglInit)break a;a.deleteTexture(c.__webglTexture)}d.remove(b)}g.textures--}function q(b){b=b.target; -b.removeEventListener("dispose",q);var c=d.get(b),e=d.get(b.texture);if(b){void 0!==e.__webglTexture&&a.deleteTexture(e.__webglTexture);b.depthTexture&&b.depthTexture.dispose();if(b.isWebGLRenderTargetCube)for(e=0;6>e;e++)a.deleteFramebuffer(c.__webglFramebuffer[e]),c.__webglDepthbuffer&&a.deleteRenderbuffer(c.__webglDepthbuffer[e]);else a.deleteFramebuffer(c.__webglFramebuffer),c.__webglDepthbuffer&&a.deleteRenderbuffer(c.__webglDepthbuffer);d.remove(b.texture);d.remove(b)}g.textures--}function n(b, -m){var n=d.get(b);if(0z;z++)r[z]=q||l?l?b.image[z].image:b.image[z]:h(b.image[z],e.maxCubemapSize);var p=k(r[0]),x=f(b.format),O=f(b.type);t(a.TEXTURE_CUBE_MAP,b,p);for(z=0;6>z;z++)if(q)for(var ca,la=r[z].mipmaps,E=0,B=la.length;Eu;u++)e.__webglFramebuffer[u]=a.createFramebuffer()}else e.__webglFramebuffer=a.createFramebuffer();if(h){c.bindTexture(a.TEXTURE_CUBE_MAP,f.__webglTexture);t(a.TEXTURE_CUBE_MAP,b.texture,m);for(u=0;6>u;u++)l(e.__webglFramebuffer[u], -b,a.COLOR_ATTACHMENT0,a.TEXTURE_CUBE_MAP_POSITIVE_X+u);b.texture.generateMipmaps&&m&&a.generateMipmap(a.TEXTURE_CUBE_MAP);c.bindTexture(a.TEXTURE_CUBE_MAP,null)}else c.bindTexture(a.TEXTURE_2D,f.__webglTexture),t(a.TEXTURE_2D,b.texture,m),l(e.__webglFramebuffer,b,a.COLOR_ATTACHMENT0,a.TEXTURE_2D),b.texture.generateMipmaps&&m&&a.generateMipmap(a.TEXTURE_2D),c.bindTexture(a.TEXTURE_2D,null);if(b.depthBuffer){e=d.get(b);f=!0===b.isWebGLRenderTargetCube;if(b.depthTexture){if(f)throw Error("target.depthTexture not supported in Cube render targets"); -if(b&&b.isWebGLRenderTargetCube)throw Error("Depth Texture with cube render targets is not supported!");a.bindFramebuffer(a.FRAMEBUFFER,e.__webglFramebuffer);if(!b.depthTexture||!b.depthTexture.isDepthTexture)throw Error("renderTarget.depthTexture must be an instance of THREE.DepthTexture");d.get(b.depthTexture).__webglTexture&&b.depthTexture.image.width===b.width&&b.depthTexture.image.height===b.height||(b.depthTexture.image.width=b.width,b.depthTexture.image.height=b.height,b.depthTexture.needsUpdate= -!0);n(b.depthTexture,0);e=d.get(b.depthTexture).__webglTexture;if(1026===b.depthTexture.format)a.framebufferTexture2D(a.FRAMEBUFFER,a.DEPTH_ATTACHMENT,a.TEXTURE_2D,e,0);else if(1027===b.depthTexture.format)a.framebufferTexture2D(a.FRAMEBUFFER,a.DEPTH_STENCIL_ATTACHMENT,a.TEXTURE_2D,e,0);else throw Error("Unknown depthTexture format");}else if(f)for(e.__webglDepthbuffer=[],f=0;6>f;f++)a.bindFramebuffer(a.FRAMEBUFFER,e.__webglFramebuffer[f]),e.__webglDepthbuffer[f]=a.createRenderbuffer(),r(e.__webglDepthbuffer[f], -b);else a.bindFramebuffer(a.FRAMEBUFFER,e.__webglFramebuffer),e.__webglDepthbuffer=a.createRenderbuffer(),r(e.__webglDepthbuffer,b);a.bindFramebuffer(a.FRAMEBUFFER,null)}};this.updateRenderTargetMipmap=function(b){var e=b.texture;e.generateMipmaps&&k(b)&&1003!==e.minFilter&&1006!==e.minFilter&&(b=b&&b.isWebGLRenderTargetCube?a.TEXTURE_CUBE_MAP:a.TEXTURE_2D,e=d.get(e).__webglTexture,c.bindTexture(b,e),a.generateMipmap(b),c.bindTexture(b,null))}}function eg(){var a={};return{get:function(b){b=b.uuid; -var c=a[b];void 0===c&&(c={},a[b]=c);return c},remove:function(b){delete a[b.uuid]},clear:function(){a={}}}}function fg(a,b,c){function d(b,c,d){var e=new Uint8Array(4),f=a.createTexture();a.bindTexture(b,f);a.texParameteri(b,a.TEXTURE_MIN_FILTER,a.NEAREST);a.texParameteri(b,a.TEXTURE_MAG_FILTER,a.NEAREST);for(b=0;b=na.maxTextures&&console.warn("THREE.WebGLRenderer: Trying to use "+a+" texture units while this GPU supports only "+na.maxTextures);T+=1;return a};this.setTexture2D=function(){var a=!1;return function(b,c){b&&b.isWebGLRenderTarget&& -(a||(console.warn("THREE.WebGLRenderer.setTexture2D: don't use render targets as textures. Use their .texture property instead."),a=!0),b=b.texture);sa.setTexture2D(b,c)}}();this.setTexture=function(){var a=!1;return function(b,c){a||(console.warn("THREE.WebGLRenderer: .setTexture is deprecated, use setTexture2D instead."),a=!0);sa.setTexture2D(b,c)}}();this.setTextureCube=function(){var a=!1;return function(b,c){b&&b.isWebGLRenderTargetCube&&(a||(console.warn("THREE.WebGLRenderer.setTextureCube: don't use cube render targets as textures. Use their .texture property instead."), -a=!0),b=b.texture);b&&b.isCubeTexture||Array.isArray(b.image)&&6===b.image.length?sa.setTextureCube(b,c):sa.setTextureCubeDynamic(b,c)}}();this.getRenderTarget=function(){return Q};this.setRenderTarget=function(a){(Q=a)&&void 0===ia.get(a).__webglFramebuffer&&sa.setupRenderTarget(a);var b=a&&a.isWebGLRenderTargetCube,c;a?(c=ia.get(a),c=b?c.__webglFramebuffer[a.activeCubeFace]:c.__webglFramebuffer,P.copy(a.scissor),L=a.scissorTest,Z.copy(a.viewport)):(c=null,P.copy(ha).multiplyScalar(ka),L=Pe,Z.copy(zc).multiplyScalar(ka)); -K!==c&&(A.bindFramebuffer(A.FRAMEBUFFER,c),K=c);fa.scissor(P);fa.setScissorTest(L);fa.viewport(Z);b&&(b=ia.get(a.texture),A.framebufferTexture2D(A.FRAMEBUFFER,A.COLOR_ATTACHMENT0,A.TEXTURE_CUBE_MAP_POSITIVE_X+a.activeCubeFace,b.__webglTexture,a.activeMipMapLevel))};this.readRenderTargetPixels=function(a,b,c,d,e,f){if(!1===(a&&a.isWebGLRenderTarget))console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.");else{var g=ia.get(a).__webglFramebuffer;if(g){var h= -!1;g!==K&&(A.bindFramebuffer(A.FRAMEBUFFER,g),h=!0);try{var k=a.texture,m=k.format,n=k.type;1023!==m&&x(m)!==A.getParameter(A.IMPLEMENTATION_COLOR_READ_FORMAT)?console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format."):1009===n||x(n)===A.getParameter(A.IMPLEMENTATION_COLOR_READ_TYPE)||1015===n&&(pa.get("OES_texture_float")||pa.get("WEBGL_color_buffer_float"))||1016===n&&pa.get("EXT_color_buffer_half_float")?A.checkFramebufferStatus(A.FRAMEBUFFER)=== -A.FRAMEBUFFER_COMPLETE?0<=b&&b<=a.width-d&&0<=c&&c<=a.height-e&&A.readPixels(b,c,d,e,x(m),x(n),f):console.error("THREE.WebGLRenderer.readRenderTargetPixels: readPixels from renderTarget failed. Framebuffer not complete."):console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.")}finally{h&&A.bindFramebuffer(A.FRAMEBUFFER,K)}}}}}function Kb(a,b){this.name="";this.color=new H(a);this.density=void 0!==b?b:2.5E-4}function Lb(a, -b,c){this.name="";this.color=new H(a);this.near=void 0!==b?b:1;this.far=void 0!==c?c:1E3}function md(){B.call(this);this.type="Scene";this.overrideMaterial=this.fog=this.background=null;this.autoUpdate=!0}function Yd(a,b,c,d,e){B.call(this);this.lensFlares=[];this.positionScreen=new p;this.customUpdateCallback=void 0;void 0!==a&&this.add(a,b,c,d,e)}function cb(a){Z.call(this);this.type="SpriteMaterial";this.color=new H(16777215);this.map=null;this.rotation=0;this.lights=this.fog=!1;this.setValues(a)} -function Ac(a){B.call(this);this.type="Sprite";this.material=void 0!==a?a:new cb}function Bc(){B.call(this);this.type="LOD";Object.defineProperties(this,{levels:{enumerable:!0,value:[]}})}function Cc(a,b){a=a||[];this.bones=a.slice(0);this.boneMatrices=new Float32Array(16*this.bones.length);if(void 0===b)this.calculateInverses();else if(this.bones.length===b.length)this.boneInverses=b.slice(0);else{console.warn("THREE.Skeleton boneInverses is the wrong length.");this.boneInverses=[];for(var c=0,d= -this.bones.length;c=a.HAVE_CURRENT_DATA&&(u.needsUpdate=!0)}X.call(this,a,b,c,d,e,f,g,h,k);this.generateMipmaps=!1;var u=this;m()}function Nb(a,b,c,d,e,f,g,h,k,m,u,q){X.call(this,null,f,g,h,k,m,d,e,u,q);this.image= -{width:b,height:c};this.mipmaps=a;this.generateMipmaps=this.flipY=!1}function rd(a,b,c,d,e,f,g,h,k){X.call(this,a,b,c,d,e,f,g,h,k);this.needsUpdate=!0}function Ec(a,b,c,d,e,f,g,h,k,m){m=void 0!==m?m:1026;if(1026!==m&&1027!==m)throw Error("DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat");void 0===c&&1026===m&&(c=1012);void 0===c&&1027===m&&(c=1020);X.call(this,null,d,e,f,g,h,m,c,k);this.image={width:a,height:b};this.magFilter=void 0!==g?g:1003;this.minFilter=void 0!== -h?h:1003;this.generateMipmaps=this.flipY=!1}function Ob(a){I.call(this);this.type="WireframeGeometry";var b=[],c,d,e,f,g=[0,0],h={},k,m,u=["a","b","c"];if(a&&a.isGeometry){var q=a.faces;c=0;for(e=q.length;cd;d++)k=n[u[d]],m=n[u[(d+1)%3]],g[0]=Math.min(k,m),g[1]=Math.max(k,m),k=g[0]+","+g[1],void 0===h[k]&&(h[k]={index1:g[0],index2:g[1]})}for(k in h)c=h[k],u=a.vertices[c.index1],b.push(u.x,u.y,u.z),u=a.vertices[c.index2],b.push(u.x,u.y,u.z)}else if(a&&a.isBufferGeometry){var t, -u=new p;if(null!==a.index){q=a.attributes.position;n=a.index;t=a.groups;0===t.length&&(t=[{start:0,count:n.count,materialIndex:0}]);a=0;for(f=t.length;ad;d++)k=n.getX(c+d),m=n.getX(c+(d+1)%3),g[0]=Math.min(k,m),g[1]=Math.max(k,m),k=g[0]+","+g[1],void 0===h[k]&&(h[k]={index1:g[0],index2:g[1]});for(k in h)c=h[k],u.fromBufferAttribute(q,c.index1),b.push(u.x,u.y,u.z),u.fromBufferAttribute(q,c.index2),b.push(u.x,u.y,u.z)}else for(q=a.attributes.position, -c=0,e=q.count/3;cd;d++)h=3*c+d,u.fromBufferAttribute(q,h),b.push(u.x,u.y,u.z),h=3*c+(d+1)%3,u.fromBufferAttribute(q,h),b.push(u.x,u.y,u.z)}this.addAttribute("position",new D(b,3))}function Fc(a,b,c){M.call(this);this.type="ParametricGeometry";this.parameters={func:a,slices:b,stacks:c};this.fromBufferGeometry(new Pb(a,b,c));this.mergeVertices()}function Pb(a,b,c){I.call(this);this.type="ParametricBufferGeometry";this.parameters={func:a,slices:b,stacks:c};var d=[],e=[],f=[],g=[],h= -new p,k=new p,m=new p,u=new p,q=new p,n,t,l=b+1;for(n=0;n<=c;n++){var r=n/c;for(t=0;t<=b;t++){var x=t/b,k=a(x,r,k);e.push(k.x,k.y,k.z);0<=x-1E-5?(m=a(x-1E-5,r,m),u.subVectors(k,m)):(m=a(x+1E-5,r,m),u.subVectors(m,k));0<=r-1E-5?(m=a(x,r-1E-5,m),q.subVectors(k,m)):(m=a(x,r+1E-5,m),q.subVectors(m,k));h.crossVectors(u,q).normalize();f.push(h.x,h.y,h.z);g.push(x,r)}}for(n=0;nd&&1===a.x&&(k[b]=a.x-1);0===c.x&&0===c.z&&(k[b]=d/2/Math.PI+.5)}I.call(this);this.type="PolyhedronBufferGeometry"; -this.parameters={vertices:a,indices:b,radius:c,detail:d};c=c||1;d=d||0;var h=[],k=[];(function(a){for(var c=new p,d=new p,g=new p,h=0;he&&(.2>b&&(k[a+0]+=1),.2>c&&(k[a+2]+=1),.2>d&&(k[a+4]+=1))})();this.addAttribute("position",new D(h,3));this.addAttribute("normal",new D(h.slice(),3));this.addAttribute("uv",new D(k,2));0===d?this.computeVertexNormals(): -this.normalizeNormals()}function Hc(a,b){M.call(this);this.type="TetrahedronGeometry";this.parameters={radius:a,detail:b};this.fromBufferGeometry(new Qb(a,b));this.mergeVertices()}function Qb(a,b){ia.call(this,[1,1,1,-1,-1,1,-1,1,-1,1,-1,-1],[2,1,0,0,3,2,1,3,0,2,3,1],a,b);this.type="TetrahedronBufferGeometry";this.parameters={radius:a,detail:b}}function Ic(a,b){M.call(this);this.type="OctahedronGeometry";this.parameters={radius:a,detail:b};this.fromBufferGeometry(new mb(a,b));this.mergeVertices()} -function mb(a,b){ia.call(this,[1,0,0,-1,0,0,0,1,0,0,-1,0,0,0,1,0,0,-1],[0,2,4,0,4,3,0,3,5,0,5,2,1,2,5,1,5,3,1,3,4,1,4,2],a,b);this.type="OctahedronBufferGeometry";this.parameters={radius:a,detail:b}}function Jc(a,b){M.call(this);this.type="IcosahedronGeometry";this.parameters={radius:a,detail:b};this.fromBufferGeometry(new Rb(a,b));this.mergeVertices()}function Rb(a,b){var c=(1+Math.sqrt(5))/2;ia.call(this,[-1,c,0,1,c,0,-1,-c,0,1,-c,0,0,-1,c,0,1,c,0,-1,-c,0,1,-c,c,0,-1,c,0,1,-c,0,-1,-c,0,1],[0,11, -5,0,5,1,0,1,7,0,7,10,0,10,11,1,5,9,5,11,4,11,10,2,10,7,6,7,1,8,3,9,4,3,4,2,3,2,6,3,6,8,3,8,9,4,9,5,2,4,11,6,2,10,8,6,7,9,8,1],a,b);this.type="IcosahedronBufferGeometry";this.parameters={radius:a,detail:b}}function Kc(a,b){M.call(this);this.type="DodecahedronGeometry";this.parameters={radius:a,detail:b};this.fromBufferGeometry(new Sb(a,b));this.mergeVertices()}function Sb(a,b){var c=(1+Math.sqrt(5))/2,d=1/c;ia.call(this,[-1,-1,-1,-1,-1,1,-1,1,-1,-1,1,1,1,-1,-1,1,-1,1,1,1,-1,1,1,1,0,-d,-c,0,-d,c,0, -d,-c,0,d,c,-d,-c,0,-d,c,0,d,-c,0,d,c,0,-c,0,-d,c,0,-d,-c,0,d,c,0,d],[3,11,7,3,7,15,3,15,13,7,19,17,7,17,6,7,6,15,17,4,8,17,8,10,17,10,6,8,0,16,8,16,2,8,2,10,0,12,1,0,1,18,0,18,16,6,10,2,6,2,13,6,13,15,2,16,18,2,18,3,2,3,13,18,1,9,18,9,11,18,11,3,4,14,12,4,12,0,4,0,8,11,9,5,11,5,19,11,19,7,19,5,14,19,14,4,19,4,17,1,12,14,1,14,5,1,5,9],a,b);this.type="DodecahedronBufferGeometry";this.parameters={radius:a,detail:b}}function Lc(a,b,c,d,e,f){M.call(this);this.type="TubeGeometry";this.parameters={path:a, -tubularSegments:b,radius:c,radialSegments:d,closed:e};void 0!==f&&console.warn("THREE.TubeGeometry: taper has been removed.");a=new Tb(a,b,c,d,e);this.tangents=a.tangents;this.normals=a.normals;this.binormals=a.binormals;this.fromBufferGeometry(a);this.mergeVertices()}function Tb(a,b,c,d,e){function f(e){var f=a.getPointAt(e/b),m=g.normals[e];e=g.binormals[e];for(q=0;q<=d;q++){var u=q/d*Math.PI*2,r=Math.sin(u),u=-Math.cos(u);k.x=u*m.x+r*e.x;k.y=u*m.y+r*e.y;k.z=u*m.z+r*e.z;k.normalize();l.push(k.x, -k.y,k.z);h.x=f.x+c*k.x;h.y=f.y+c*k.y;h.z=f.z+c*k.z;n.push(h.x,h.y,h.z)}}I.call(this);this.type="TubeBufferGeometry";this.parameters={path:a,tubularSegments:b,radius:c,radialSegments:d,closed:e};b=b||64;c=c||1;d=d||8;e=e||!1;var g=a.computeFrenetFrames(b,e);this.tangents=g.tangents;this.normals=g.normals;this.binormals=g.binormals;var h=new p,k=new p,m=new E,u,q,n=[],l=[],z=[],r=[];for(u=0;up;p++)g=t[k[p]],h=t[k[(p+1)%3]],e[0]=Math.min(g,h),e[1]=Math.max(g,h),g=e[0]+","+e[1],void 0===f[g]?f[g]={index1:e[0],index2:e[1],face1:l,face2:void 0}:f[g].face2=l;for(g in f)if(e=f[g],void 0===e.face2||m[e.face1].normal.dot(m[e.face2].normal)<=d)k=u[e.index1],c.push(k.x,k.y,k.z),k=u[e.index2],c.push(k.x,k.y,k.z);this.addAttribute("position", -new D(c,3))}function ob(a,b,c,d,e,f,g,h){M.call(this);this.type="CylinderGeometry";this.parameters={radiusTop:a,radiusBottom:b,height:c,radialSegments:d,heightSegments:e,openEnded:f,thetaStart:g,thetaLength:h};this.fromBufferGeometry(new Wa(a,b,c,d,e,f,g,h));this.mergeVertices()}function Wa(a,b,c,d,e,f,g,h){function k(c){var e,f,k,r=new E,C=new p,G=0,aa=!0===c?a:b,O=!0===c?1:-1;f=z;for(e=1;e<=d;e++)l.push(0,x*O,0),n.push(0,O,0),t.push(.5,.5),z++;k=z;for(e=0;e<=d;e++){var D=e/d*h+g,B=Math.cos(D),D= -Math.sin(D);C.x=aa*D;C.y=x*O;C.z=aa*B;l.push(C.x,C.y,C.z);n.push(0,O,0);r.x=.5*B+.5;r.y=.5*D*O+.5;t.push(r.x,r.y);z++}for(e=0;ethis.duration&&this.resetDuration();this.optimize()}function Hd(a){this.manager= -void 0!==a?a:Aa;this.textures={}}function be(a){this.manager=void 0!==a?a:Aa}function gc(){this.onLoadStart=function(){};this.onLoadProgress=function(){};this.onLoadComplete=function(){}}function ce(a){"boolean"===typeof a&&(console.warn("THREE.JSONLoader: showStatus parameter has been removed from constructor."),a=void 0);this.manager=void 0!==a?a:Aa;this.withCredentials=!1}function Re(a){this.manager=void 0!==a?a:Aa;this.texturePath=""}function Se(a,b,c,d,e){b=.5*(d-b);e=.5*(e-c);var f=a*a;return(2* -c-2*d+b+e)*a*f+(-3*c+3*d-2*b-e)*f+b*a+c}function xb(a,b,c,d){var e=1-a;return e*e*b+2*(1-a)*a*c+a*a*d}function yb(a,b,c,d,e){var f=1-a,g=1-a;return f*f*f*b+3*g*g*a*c+3*(1-a)*a*a*d+a*a*a*e}function na(){this.arcLengthDivisions=200}function Sa(a,b){this.arcLengthDivisions=200;this.v1=a;this.v2=b}function Yc(){this.arcLengthDivisions=200;this.curves=[];this.autoClose=!1}function Xa(a,b,c,d,e,f,g,h){this.arcLengthDivisions=200;this.aX=a;this.aY=b;this.xRadius=c;this.yRadius=d;this.aStartAngle=e;this.aEndAngle= -f;this.aClockwise=g;this.aRotation=h||0}function zb(a){this.arcLengthDivisions=200;this.points=void 0===a?[]:a}function hc(a,b,c,d){this.arcLengthDivisions=200;this.v0=a;this.v1=b;this.v2=c;this.v3=d}function ic(a,b,c){this.arcLengthDivisions=200;this.v0=a;this.v1=b;this.v2=c}function Zc(a){Yc.call(this);this.currentPoint=new E;a&&this.fromPoints(a)}function Ab(){Zc.apply(this,arguments);this.holes=[]}function de(){this.subPaths=[];this.currentPath=null}function ee(a){this.data=a}function Te(a){this.manager= -void 0!==a?a:Aa}function fe(a){this.manager=void 0!==a?a:Aa}function Ue(){this.type="StereoCamera";this.aspect=1;this.eyeSep=.064;this.cameraL=new xa;this.cameraL.layers.enable(1);this.cameraL.matrixAutoUpdate=!1;this.cameraR=new xa;this.cameraR.layers.enable(2);this.cameraR.matrixAutoUpdate=!1}function Id(a,b,c){B.call(this);this.type="CubeCamera";var d=new xa(90,1,a,b);d.up.set(0,-1,0);d.lookAt(new p(1,0,0));this.add(d);var e=new xa(90,1,a,b);e.up.set(0,-1,0);e.lookAt(new p(-1,0,0));this.add(e); -var f=new xa(90,1,a,b);f.up.set(0,0,1);f.lookAt(new p(0,1,0));this.add(f);var g=new xa(90,1,a,b);g.up.set(0,0,-1);g.lookAt(new p(0,-1,0));this.add(g);var h=new xa(90,1,a,b);h.up.set(0,-1,0);h.lookAt(new p(0,0,1));this.add(h);var k=new xa(90,1,a,b);k.up.set(0,-1,0);k.lookAt(new p(0,0,-1));this.add(k);this.renderTarget=new Eb(c,c,{format:1022,magFilter:1006,minFilter:1006});this.renderTarget.texture.name="CubeCamera";this.updateCubeMap=function(a,b){null===this.parent&&this.updateMatrixWorld();var c= -this.renderTarget,n=c.texture.generateMipmaps;c.texture.generateMipmaps=!1;c.activeCubeFace=0;a.render(b,d,c);c.activeCubeFace=1;a.render(b,e,c);c.activeCubeFace=2;a.render(b,f,c);c.activeCubeFace=3;a.render(b,g,c);c.activeCubeFace=4;a.render(b,h,c);c.texture.generateMipmaps=n;c.activeCubeFace=5;a.render(b,k,c);a.setRenderTarget(null)}}function ge(a){xa.call(this);this.enabled=!1;this.cameras=a||[]}function he(){B.call(this);this.type="AudioListener";this.context=ie.getContext();this.gain=this.context.createGain(); -this.gain.connect(this.context.destination);this.filter=null}function jc(a){B.call(this);this.type="Audio";this.context=a.context;this.gain=this.context.createGain();this.gain.connect(a.getInput());this.autoplay=!1;this.buffer=null;this.loop=!1;this.startTime=0;this.playbackRate=1;this.isPlaying=!1;this.hasPlaybackControl=!0;this.sourceType="empty";this.filters=[]}function je(a){jc.call(this,a);this.panner=this.context.createPanner();this.panner.connect(this.gain)}function ke(a,b){this.analyser=a.context.createAnalyser(); -this.analyser.fftSize=void 0!==b?b:2048;this.data=new Uint8Array(this.analyser.frequencyBinCount);a.getOutput().connect(this.analyser)}function le(a,b,c){this.binding=a;this.valueSize=c;a=Float64Array;switch(b){case "quaternion":b=this._slerp;break;case "string":case "bool":a=Array;b=this._select;break;default:b=this._lerp}this.buffer=new a(4*c);this._mixBufferRegion=b;this.referenceCount=this.useCount=this.cumulativeWeight=0}function Ve(a,b,c){c=c||oa.parseTrackName(b);this._targetGroup=a;this._bindings= -a.subscribe_(b,c)}function oa(a,b,c){this.path=b;this.parsedPath=c||oa.parseTrackName(b);this.node=oa.findNode(a,this.parsedPath.nodeName)||a;this.rootNode=a}function We(a){this.uuid=Y.generateUUID();this._objects=Array.prototype.slice.call(arguments);this.nCachedObjects_=0;var b={};this._indicesByUUID=b;for(var c=0,d=arguments.length;c!==d;++c)b[arguments[c].uuid]=c;this._paths=[];this._parsedPaths=[];this._bindings=[];this._bindingsIndicesByPath={};var e=this;this.stats={objects:{get total(){return e._objects.length}, +(function(m,sa){"object"===typeof exports&&"undefined"!==typeof module?sa(exports):"function"===typeof define&&define.amd?define(["exports"],sa):sa(m.THREE=m.THREE||{})})(this,function(m){function sa(){}function D(a,b){this.x=a||0;this.y=b||0}function K(){this.elements=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1];0=d||0 0 ) {\nfloat fogFactor = 0.0;\nif ( fogType == 1 ) {\nfogFactor = smoothstep( fogNear, fogFar, fogDepth );\n} else {\nconst float LOG2 = 1.442695;\nfogFactor = exp2( - fogDensity * fogDensity * fogDepth * fogDepth * LOG2 );\nfogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 );\n}\ngl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n}\n}"].join("\n")); +b.compileShader(Fa);b.compileShader(y);b.attachShader(N,Fa);b.attachShader(N,y);b.linkProgram(N);aa=N;C=b.getAttribLocation(aa,"position");J=b.getAttribLocation(aa,"uv");f=b.getUniformLocation(aa,"uvOffset");g=b.getUniformLocation(aa,"uvScale");h=b.getUniformLocation(aa,"rotation");k=b.getUniformLocation(aa,"scale");l=b.getUniformLocation(aa,"color");q=b.getUniformLocation(aa,"map");n=b.getUniformLocation(aa,"opacity");u=b.getUniformLocation(aa,"modelViewMatrix");r=b.getUniformLocation(aa,"projectionMatrix"); +m=b.getUniformLocation(aa,"fogType");t=b.getUniformLocation(aa,"fogDensity");w=b.getUniformLocation(aa,"fogNear");x=b.getUniformLocation(aa,"fogFar");A=b.getUniformLocation(aa,"fogColor");b.getUniformLocation(aa,"fogDepth");I=b.getUniformLocation(aa,"alphaTest");N=document.createElementNS("http://www.w3.org/1999/xhtml","canvas");N.width=8;N.height=8;Fa=N.getContext("2d");Fa.fillStyle="white";Fa.fillRect(0,0,8,8);z=new pc(N)}c.useProgram(aa);c.initAttributes();c.enableAttribute(C);c.enableAttribute(J); +c.disableUnusedAttributes();c.disable(b.CULL_FACE);c.enable(b.BLEND);b.bindBuffer(b.ARRAY_BUFFER,ja);b.vertexAttribPointer(C,2,b.FLOAT,!1,16,0);b.vertexAttribPointer(J,2,b.FLOAT,!1,16,8);b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,la);b.uniformMatrix4fv(r,!1,U.projectionMatrix.elements);c.activeTexture(b.TEXTURE0);b.uniform1i(q,0);Fa=N=0;(y=p.fog)?(b.uniform3f(A,y.color.r,y.color.g,y.color.b),y.isFog?(b.uniform1f(w,y.near),b.uniform1f(x,y.far),b.uniform1i(m,1),Fa=N=1):y.isFogExp2&&(b.uniform1f(t,y.density), +b.uniform1i(m,2),Fa=N=2)):(b.uniform1i(m,0),Fa=N=0);for(var D=0,ka=v.length;Db&&(b=a[c]);return b}function E(){Object.defineProperty(this,"id",{value:Rd++}); +this.uuid=R.generateUUID();this.name="";this.type="BufferGeometry";this.index=null;this.attributes={};this.morphAttributes={};this.groups=[];this.boundingSphere=this.boundingBox=null;this.drawRange={start:0,count:Infinity}}function Fb(a,b,c,d,e,f){L.call(this);this.type="BoxGeometry";this.parameters={width:a,height:b,depth:c,widthSegments:d,heightSegments:e,depthSegments:f};this.fromBufferGeometry(new gb(a,b,c,d,e,f));this.mergeVertices()}function gb(a,b,c,d,e,f){function g(a,b,c,d,e,f,g,m,xa,ja, +la){var A=f/xa,v=g/ja,t=f/2,w=g/2,I=m/2;g=xa+1;var C=ja+1,x=f=0,J,y,z=new p;for(y=0;yl;l++){if(n=d[l])if(h=n[0],n=n[1]){q&&e.addAttribute("morphTarget"+l,q[h]);f&&e.addAttribute("morphNormal"+l,f[h]);c[l]=n;continue}c[l]=0}g.getUniforms().setValue(a,"morphTargetInfluences",c)}}}function Vf(a,b,c){var d,e,f;this.setMode=function(a){d=a};this.setIndex=function(a){e=a.type; +f=a.bytesPerElement};this.render=function(b,h){a.drawElements(d,h,e,b*f);c.calls++;c.vertices+=h;d===a.TRIANGLES?c.faces+=h/3:d===a.POINTS&&(c.points+=h)};this.renderInstances=function(g,h,k){var l=b.get("ANGLE_instanced_arrays");null===l?console.error("THREE.WebGLIndexedBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays."):(l.drawElementsInstancedANGLE(d,k,e,h*f,g.maxInstancedCount),c.calls++,c.vertices+=k*g.maxInstancedCount,d===a.TRIANGLES? +c.faces+=g.maxInstancedCount*k/3:d===a.POINTS&&(c.points+=g.maxInstancedCount*k))}}function Wf(a,b,c){var d;this.setMode=function(a){d=a};this.render=function(b,f){a.drawArrays(d,b,f);c.calls++;c.vertices+=f;d===a.TRIANGLES?c.faces+=f/3:d===a.POINTS&&(c.points+=f)};this.renderInstances=function(e,f,g){var h=b.get("ANGLE_instanced_arrays");if(null===h)console.error("THREE.WebGLBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.");else{var k= +e.attributes.position;k.isInterleavedBufferAttribute?(g=k.data.count,h.drawArraysInstancedANGLE(d,0,g,e.maxInstancedCount)):h.drawArraysInstancedANGLE(d,f,g,e.maxInstancedCount);c.calls++;c.vertices+=g*e.maxInstancedCount;d===a.TRIANGLES?c.faces+=e.maxInstancedCount*g/3:d===a.POINTS&&(c.points+=e.maxInstancedCount*g)}}}function Xf(a,b,c){function d(a){a=a.target;var g=e[a.id];null!==g.index&&b.remove(g.index);for(var k in g.attributes)b.remove(g.attributes[k]);a.removeEventListener("dispose",d);delete e[a.id]; +if(k=f[a.id])b.remove(k),delete f[a.id];if(k=f[g.id])b.remove(k),delete f[g.id];c.geometries--}var e={},f={};return{get:function(a,b){var f=e[b.id];if(f)return f;b.addEventListener("dispose",d);b.isBufferGeometry?f=b:b.isGeometry&&(void 0===b._bufferGeometry&&(b._bufferGeometry=(new E).setFromObject(a)),f=b._bufferGeometry);e[b.id]=f;c.geometries++;return f},update:function(c){var d=c.index,e=c.attributes;null!==d&&b.update(d,a.ELEMENT_ARRAY_BUFFER);for(var f in e)b.update(e[f],a.ARRAY_BUFFER);c= +c.morphAttributes;for(f in c)for(var d=c[f],e=0,g=d.length;e/gm,function(a,c){a=S[c];if(void 0===a)throw Error("Can not resolve #include <"+c+">");return Ud(a)})}function Oe(a){return a.replace(/for \( int i \= (\d+)\; i < (\d+)\; i \+\+ \) \{([\s\S]+?)(?=\})\}/g, +function(a,c,d,e){a="";for(c=parseInt(c);cb||a.height>b){b/=Math.max(a.width,a.height);var c=document.createElementNS("http://www.w3.org/1999/xhtml","canvas");c.width=Math.floor(a.width*b);c.height=Math.floor(a.height*b);c.getContext("2d").drawImage(a, +0,0,a.width,a.height,0,0,c.width,c.height);console.warn("THREE.WebGLRenderer: image is too big ("+a.width+"x"+a.height+"). Resized to "+c.width+"x"+c.height,a);return c}return a}function k(a){return R.isPowerOfTwo(a.width)&&R.isPowerOfTwo(a.height)}function l(a,b){return a.generateMipmaps&&b&&1003!==a.minFilter&&1006!==a.minFilter}function q(b){return 1003===b||1004===b||1005===b?a.NEAREST:a.LINEAR}function n(b){b=b.target;b.removeEventListener("dispose",n);a:{var c=d.get(b);if(b.image&&c.__image__webglTextureCube)a.deleteTexture(c.__image__webglTextureCube); +else{if(void 0===c.__webglInit)break a;a.deleteTexture(c.__webglTexture)}d.remove(b)}g.textures--}function u(b){b=b.target;b.removeEventListener("dispose",u);var c=d.get(b),e=d.get(b.texture);if(b){void 0!==e.__webglTexture&&a.deleteTexture(e.__webglTexture);b.depthTexture&&b.depthTexture.dispose();if(b.isWebGLRenderTargetCube)for(e=0;6>e;e++)a.deleteFramebuffer(c.__webglFramebuffer[e]),c.__webglDepthbuffer&&a.deleteRenderbuffer(c.__webglDepthbuffer[e]);else a.deleteFramebuffer(c.__webglFramebuffer), +c.__webglDepthbuffer&&a.deleteRenderbuffer(c.__webglDepthbuffer);d.remove(b.texture);d.remove(b)}g.textures--}function r(b,q){var u=d.get(b);if(0p;p++)v[p]=q||r?r?b.image[p].image:b.image[p]:h(b.image[p],e.maxCubemapSize); +var t=k(v[0]),w=f.convert(b.format),A=f.convert(b.type);m(a.TEXTURE_CUBE_MAP,b,t);for(p=0;6>p;p++)if(q)for(var x,I=v[p].mipmaps,y=0,z=I.length;yq;q++)e.__webglFramebuffer[q]=a.createFramebuffer()}else e.__webglFramebuffer=a.createFramebuffer();if(h){c.bindTexture(a.TEXTURE_CUBE_MAP,f.__webglTexture);m(a.TEXTURE_CUBE_MAP,b.texture,n);for(q=0;6>q;q++)p(e.__webglFramebuffer[q],b,a.COLOR_ATTACHMENT0,a.TEXTURE_CUBE_MAP_POSITIVE_X+q); +l(b.texture,n)&&a.generateMipmap(a.TEXTURE_CUBE_MAP);c.bindTexture(a.TEXTURE_CUBE_MAP,null)}else c.bindTexture(a.TEXTURE_2D,f.__webglTexture),m(a.TEXTURE_2D,b.texture,n),p(e.__webglFramebuffer,b,a.COLOR_ATTACHMENT0,a.TEXTURE_2D),l(b.texture,n)&&a.generateMipmap(a.TEXTURE_2D),c.bindTexture(a.TEXTURE_2D,null);if(b.depthBuffer){e=d.get(b);f=!0===b.isWebGLRenderTargetCube;if(b.depthTexture){if(f)throw Error("target.depthTexture not supported in Cube render targets");if(b&&b.isWebGLRenderTargetCube)throw Error("Depth Texture with cube render targets is not supported"); +a.bindFramebuffer(a.FRAMEBUFFER,e.__webglFramebuffer);if(!b.depthTexture||!b.depthTexture.isDepthTexture)throw Error("renderTarget.depthTexture must be an instance of THREE.DepthTexture");d.get(b.depthTexture).__webglTexture&&b.depthTexture.image.width===b.width&&b.depthTexture.image.height===b.height||(b.depthTexture.image.width=b.width,b.depthTexture.image.height=b.height,b.depthTexture.needsUpdate=!0);r(b.depthTexture,0);e=d.get(b.depthTexture).__webglTexture;if(1026===b.depthTexture.format)a.framebufferTexture2D(a.FRAMEBUFFER, +a.DEPTH_ATTACHMENT,a.TEXTURE_2D,e,0);else if(1027===b.depthTexture.format)a.framebufferTexture2D(a.FRAMEBUFFER,a.DEPTH_STENCIL_ATTACHMENT,a.TEXTURE_2D,e,0);else throw Error("Unknown depthTexture format");}else if(f)for(e.__webglDepthbuffer=[],f=0;6>f;f++)a.bindFramebuffer(a.FRAMEBUFFER,e.__webglFramebuffer[f]),e.__webglDepthbuffer[f]=a.createRenderbuffer(),w(e.__webglDepthbuffer[f],b);else a.bindFramebuffer(a.FRAMEBUFFER,e.__webglFramebuffer),e.__webglDepthbuffer=a.createRenderbuffer(),w(e.__webglDepthbuffer, +b);a.bindFramebuffer(a.FRAMEBUFFER,null)}};this.updateRenderTargetMipmap=function(b){var e=b.texture,f=k(b);l(e,f)&&(b=b.isWebGLRenderTargetCube?a.TEXTURE_CUBE_MAP:a.TEXTURE_2D,e=d.get(e).__webglTexture,c.bindTexture(b,e),a.generateMipmap(b),c.bindTexture(b,null))}}function jg(){var a={};return{get:function(b){b=b.uuid;var c=a[b];void 0===c&&(c={},a[b]=c);return c},remove:function(b){delete a[b.uuid]},clear:function(){a={}}}}function kg(a,b,c){function d(b,c,d){var e=new Uint8Array(4),f=a.createTexture(); +a.bindTexture(b,f);a.texParameteri(b,a.TEXTURE_MIN_FILTER,a.NEAREST);a.texParameteri(b,a.TEXTURE_MAG_FILTER,a.NEAREST);for(b=0;b=V.maxTextures&&console.warn("THREE.WebGLRenderer: Trying to use "+a+" texture units while this GPU supports only "+V.maxTextures);G+=1;return a};this.setTexture2D=function(){var a=!1;return function(b,c){b&&b.isWebGLRenderTarget&&(a||(console.warn("THREE.WebGLRenderer.setTexture2D: don't use render targets as textures. Use their .texture property instead."), +a=!0),b=b.texture);ca.setTexture2D(b,c)}}();this.setTexture=function(){var a=!1;return function(b,c){a||(console.warn("THREE.WebGLRenderer: .setTexture is deprecated, use setTexture2D instead."),a=!0);ca.setTexture2D(b,c)}}();this.setTextureCube=function(){var a=!1;return function(b,c){b&&b.isWebGLRenderTargetCube&&(a||(console.warn("THREE.WebGLRenderer.setTextureCube: don't use cube render targets as textures. Use their .texture property instead."),a=!0),b=b.texture);b&&b.isCubeTexture||Array.isArray(b.image)&& +6===b.image.length?ca.setTextureCube(b,c):ca.setTextureCubeDynamic(b,c)}}();this.getRenderTarget=function(){return ka};this.setRenderTarget=function(a){(ka=a)&&void 0===Y.get(a).__webglFramebuffer&&ca.setupRenderTarget(a);var b=null,c=!1;a?(b=Y.get(a).__webglFramebuffer,a.isWebGLRenderTargetCube&&(b=b[a.activeCubeFace],c=!0),S.copy(a.viewport),X.copy(a.scissor),T=a.scissorTest):(S.copy(ea).multiplyScalar(O),X.copy(fa).multiplyScalar(O),T=ga);N!==b&&(F.bindFramebuffer(F.FRAMEBUFFER,b),N=b);Z.viewport(S); +Z.scissor(X);Z.setScissorTest(T);c&&(c=Y.get(a.texture),F.framebufferTexture2D(F.FRAMEBUFFER,F.COLOR_ATTACHMENT0,F.TEXTURE_CUBE_MAP_POSITIVE_X+a.activeCubeFace,c.__webglTexture,a.activeMipMapLevel))};this.readRenderTargetPixels=function(a,b,c,d,e,f){if(a&&a.isWebGLRenderTarget){var g=Y.get(a).__webglFramebuffer;if(g){var h=!1;g!==N&&(F.bindFramebuffer(F.FRAMEBUFFER,g),h=!0);try{var l=a.texture,k=l.format,q=l.type;1023!==k&&ra.convert(k)!==F.getParameter(F.IMPLEMENTATION_COLOR_READ_FORMAT)?console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format."): +1009===q||ra.convert(q)===F.getParameter(F.IMPLEMENTATION_COLOR_READ_TYPE)||1015===q&&(ia.get("OES_texture_float")||ia.get("WEBGL_color_buffer_float"))||1016===q&&ia.get("EXT_color_buffer_half_float")?F.checkFramebufferStatus(F.FRAMEBUFFER)===F.FRAMEBUFFER_COMPLETE?0<=b&&b<=a.width-d&&0<=c&&c<=a.height-e&&F.readPixels(b,c,d,e,ra.convert(k),ra.convert(q),f):console.error("THREE.WebGLRenderer.readRenderTargetPixels: readPixels from renderTarget failed. Framebuffer not complete."):console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.")}finally{h&& +F.bindFramebuffer(F.FRAMEBUFFER,N)}}}else console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.")}}function Ib(a,b){this.name="";this.color=new H(a);this.density=void 0!==b?b:2.5E-4}function Jb(a,b,c){this.name="";this.color=new H(a);this.near=void 0!==b?b:1;this.far=void 0!==c?c:1E3}function nd(){z.call(this);this.type="Scene";this.overrideMaterial=this.fog=this.background=null;this.autoUpdate=!0}function Zd(a,b,c,d,e){z.call(this);this.lensFlares= +[];this.positionScreen=new p;this.customUpdateCallback=void 0;void 0!==a&&this.add(a,b,c,d,e)}function $a(a){P.call(this);this.type="SpriteMaterial";this.color=new H(16777215);this.map=null;this.rotation=0;this.lights=this.fog=!1;this.setValues(a)}function yc(a){z.call(this);this.type="Sprite";this.material=void 0!==a?a:new $a}function zc(){z.call(this);this.type="LOD";Object.defineProperties(this,{levels:{enumerable:!0,value:[]}})}function Ac(a,b){a=a||[];this.bones=a.slice(0);this.boneMatrices= +new Float32Array(16*this.bones.length);if(void 0===b)this.calculateInverses();else if(this.bones.length===b.length)this.boneInverses=b.slice(0);else for(console.warn("THREE.Skeleton boneInverses is the wrong length."),this.boneInverses=[],a=0,b=this.bones.length;a=a.HAVE_CURRENT_DATA&&(q.needsUpdate=!0);requestAnimationFrame(l)}O.call(this,a,b,c,d,e,f,g,h,k);this.generateMipmaps=!1;var q=this;requestAnimationFrame(l)}function Lb(a,b,c,d,e,f,g,h,k,l,q,n){O.call(this,null,f,g,h,k,l,d,e,q,n);this.image={width:b,height:c};this.mipmaps=a;this.generateMipmaps=this.flipY=!1}function Cc(a,b,c,d,e,f,g,h,k,l){l=void 0!==l?l:1026;if(1026!==l&&1027!==l)throw Error("DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat"); +void 0===c&&1026===l&&(c=1012);void 0===c&&1027===l&&(c=1020);O.call(this,null,d,e,f,g,h,l,c,k);this.image={width:a,height:b};this.magFilter=void 0!==g?g:1003;this.minFilter=void 0!==h?h:1003;this.generateMipmaps=this.flipY=!1}function Mb(a){E.call(this);this.type="WireframeGeometry";var b=[],c,d,e,f=[0,0],g={},h=["a","b","c"];if(a&&a.isGeometry){var k=a.faces;var l=0;for(d=k.length;lc;c++){var n=q[h[c]];var u=q[h[(c+1)%3]];f[0]=Math.min(n,u);f[1]=Math.max(n,u);n=f[0]+ +","+f[1];void 0===g[n]&&(g[n]={index1:f[0],index2:f[1]})}}for(n in g)l=g[n],h=a.vertices[l.index1],b.push(h.x,h.y,h.z),h=a.vertices[l.index2],b.push(h.x,h.y,h.z)}else if(a&&a.isBufferGeometry){var h=new p;if(null!==a.index){k=a.attributes.position;q=a.index;var r=a.groups;0===r.length&&(r=[{start:0,count:q.count,materialIndex:0}]);a=0;for(e=r.length;ac;c++)n=q.getX(l+c),u=q.getX(l+(c+1)%3),f[0]=Math.min(n,u),f[1]=Math.max(n,u),n=f[0]+ +","+f[1],void 0===g[n]&&(g[n]={index1:f[0],index2:f[1]});for(n in g)l=g[n],h.fromBufferAttribute(k,l.index1),b.push(h.x,h.y,h.z),h.fromBufferAttribute(k,l.index2),b.push(h.x,h.y,h.z)}else for(k=a.attributes.position,l=0,d=k.count/3;lc;c++)g=3*l+c,h.fromBufferAttribute(k,g),b.push(h.x,h.y,h.z),g=3*l+(c+1)%3,h.fromBufferAttribute(k,g),b.push(h.x,h.y,h.z)}this.addAttribute("position",new y(b,3))}function Dc(a,b,c){L.call(this);this.type="ParametricGeometry";this.parameters={func:a,slices:b, +stacks:c};this.fromBufferGeometry(new Nb(a,b,c));this.mergeVertices()}function Nb(a,b,c){E.call(this);this.type="ParametricBufferGeometry";this.parameters={func:a,slices:b,stacks:c};var d=[],e=[],f=[],g=[],h=new p,k=new p,l=new p,q=new p,n=new p,u,r,m=b+1;for(u=0;u<=c;u++){var t=u/c;for(r=0;r<=b;r++){var w=r/b,k=a(w,t,k);e.push(k.x,k.y,k.z);0<=w-1E-5?(l=a(w-1E-5,t,l),q.subVectors(k,l)):(l=a(w+1E-5,t,l),q.subVectors(l,k));0<=t-1E-5?(l=a(w,t-1E-5,l),n.subVectors(k,l)):(l=a(w,t+1E-5,l),n.subVectors(l, +k));h.crossVectors(q,n).normalize();f.push(h.x,h.y,h.z);g.push(w,t)}}for(u=0;ud&&1===a.x&&(k[b]=a.x-1);0===c.x&&0===c.z&&(k[b]=d/2/Math.PI+.5)}E.call(this);this.type="PolyhedronBufferGeometry";this.parameters={vertices:a,indices:b,radius:c,detail:d};c=c||1;d=d||0;var h=[],k=[];(function(a){for(var c=new p,d=new p,g=new p,h=0;he&&(.2>b&&(k[a+0]+=1),.2>c&&(k[a+2]+=1),.2>d&&(k[a+4]+=1))})();this.addAttribute("position",new y(h,3));this.addAttribute("normal",new y(h.slice(),3));this.addAttribute("uv",new y(k,2));0===d?this.computeVertexNormals():this.normalizeNormals()}function Fc(a,b){L.call(this);this.type="TetrahedronGeometry";this.parameters={radius:a,detail:b};this.fromBufferGeometry(new Ob(a,b));this.mergeVertices()}function Ob(a,b){na.call(this,[1,1,1,-1,-1,1,-1,1,-1,1,-1,-1],[2,1,0,0,3,2,1,3,0,2,3,1],a,b); +this.type="TetrahedronBufferGeometry";this.parameters={radius:a,detail:b}}function Gc(a,b){L.call(this);this.type="OctahedronGeometry";this.parameters={radius:a,detail:b};this.fromBufferGeometry(new kb(a,b));this.mergeVertices()}function kb(a,b){na.call(this,[1,0,0,-1,0,0,0,1,0,0,-1,0,0,0,1,0,0,-1],[0,2,4,0,4,3,0,3,5,0,5,2,1,2,5,1,5,3,1,3,4,1,4,2],a,b);this.type="OctahedronBufferGeometry";this.parameters={radius:a,detail:b}}function Hc(a,b){L.call(this);this.type="IcosahedronGeometry";this.parameters= +{radius:a,detail:b};this.fromBufferGeometry(new Pb(a,b));this.mergeVertices()}function Pb(a,b){var c=(1+Math.sqrt(5))/2;na.call(this,[-1,c,0,1,c,0,-1,-c,0,1,-c,0,0,-1,c,0,1,c,0,-1,-c,0,1,-c,c,0,-1,c,0,1,-c,0,-1,-c,0,1],[0,11,5,0,5,1,0,1,7,0,7,10,0,10,11,1,5,9,5,11,4,11,10,2,10,7,6,7,1,8,3,9,4,3,4,2,3,2,6,3,6,8,3,8,9,4,9,5,2,4,11,6,2,10,8,6,7,9,8,1],a,b);this.type="IcosahedronBufferGeometry";this.parameters={radius:a,detail:b}}function Ic(a,b){L.call(this);this.type="DodecahedronGeometry";this.parameters= +{radius:a,detail:b};this.fromBufferGeometry(new Qb(a,b));this.mergeVertices()}function Qb(a,b){var c=(1+Math.sqrt(5))/2,d=1/c;na.call(this,[-1,-1,-1,-1,-1,1,-1,1,-1,-1,1,1,1,-1,-1,1,-1,1,1,1,-1,1,1,1,0,-d,-c,0,-d,c,0,d,-c,0,d,c,-d,-c,0,-d,c,0,d,-c,0,d,c,0,-c,0,-d,c,0,-d,-c,0,d,c,0,d],[3,11,7,3,7,15,3,15,13,7,19,17,7,17,6,7,6,15,17,4,8,17,8,10,17,10,6,8,0,16,8,16,2,8,2,10,0,12,1,0,1,18,0,18,16,6,10,2,6,2,13,6,13,15,2,16,18,2,18,3,2,3,13,18,1,9,18,9,11,18,11,3,4,14,12,4,12,0,4,0,8,11,9,5,11,5,19,11, +19,7,19,5,14,19,14,4,19,4,17,1,12,14,1,14,5,1,5,9],a,b);this.type="DodecahedronBufferGeometry";this.parameters={radius:a,detail:b}}function Jc(a,b,c,d,e,f){L.call(this);this.type="TubeGeometry";this.parameters={path:a,tubularSegments:b,radius:c,radialSegments:d,closed:e};void 0!==f&&console.warn("THREE.TubeGeometry: taper has been removed.");a=new Rb(a,b,c,d,e);this.tangents=a.tangents;this.normals=a.normals;this.binormals=a.binormals;this.fromBufferGeometry(a);this.mergeVertices()}function Rb(a, +b,c,d,e){function f(e){var f=a.getPointAt(e/b),l=g.normals[e];e=g.binormals[e];for(n=0;n<=d;n++){var q=n/d*Math.PI*2,r=Math.sin(q),q=-Math.cos(q);k.x=q*l.x+r*e.x;k.y=q*l.y+r*e.y;k.z=q*l.z+r*e.z;k.normalize();m.push(k.x,k.y,k.z);h.x=f.x+c*k.x;h.y=f.y+c*k.y;h.z=f.z+c*k.z;u.push(h.x,h.y,h.z)}}E.call(this);this.type="TubeBufferGeometry";this.parameters={path:a,tubularSegments:b,radius:c,radialSegments:d,closed:e};b=b||64;c=c||1;d=d||8;e=e||!1;var g=a.computeFrenetFrames(b,e);this.tangents=g.tangents; +this.normals=g.normals;this.binormals=g.binormals;var h=new p,k=new p,l=new D,q,n,u=[],m=[],v=[],t=[];for(q=0;qq;q++){var n=l[f[q]];var u=l[f[(q+1)%3]];d[0]=Math.min(n,u);d[1]=Math.max(n,u);n=d[0]+","+d[1];void 0=== +e[n]?e[n]={index1:d[0],index2:d[1],face1:h,face2:void 0}:e[n].face2=h}for(n in e)if(d=e[n],void 0===d.face2||g[d.face1].normal.dot(g[d.face2].normal)<=b)f=a[d.index1],c.push(f.x,f.y,f.z),f=a[d.index2],c.push(f.x,f.y,f.z);this.addAttribute("position",new y(c,3))}function mb(a,b,c,d,e,f,g,h){L.call(this);this.type="CylinderGeometry";this.parameters={radiusTop:a,radiusBottom:b,height:c,radialSegments:d,heightSegments:e,openEnded:f,thetaStart:g,thetaLength:h};this.fromBufferGeometry(new Ta(a,b,c,d,e, +f,g,h));this.mergeVertices()}function Ta(a,b,c,d,e,f,g,h){function k(c){var e,f=new D,k=new p,r=0,t=!0===c?a:b,A=!0===c?1:-1;var y=v;for(e=1;e<=d;e++)n.push(0,w*A,0),u.push(0,A,0),m.push(.5,.5),v++;var z=v;for(e=0;e<=d;e++){var B=e/d*h+g,M=Math.cos(B),B=Math.sin(B);k.x=t*B;k.y=w*A;k.z=t*M;n.push(k.x,k.y,k.z);u.push(0,A,0);f.x=.5*M+.5;f.y=.5*B*A+.5;m.push(f.x,f.y);v++}for(e=0;ethis.duration&&this.resetDuration();this.optimize()}function Hd(a){this.manager=void 0!==a?a:va;this.textures={}}function ce(a){this.manager= +void 0!==a?a:va}function ec(){this.onLoadStart=function(){};this.onLoadProgress=function(){};this.onLoadComplete=function(){}}function de(a){"boolean"===typeof a&&(console.warn("THREE.JSONLoader: showStatus parameter has been removed from constructor."),a=void 0);this.manager=void 0!==a?a:va;this.withCredentials=!1}function Re(a){this.manager=void 0!==a?a:va;this.texturePath=""}function Se(a,b,c,d,e){b=.5*(d-b);e=.5*(e-c);var f=a*a;return(2*c-2*d+b+e)*a*f+(-3*c+3*d-2*b-e)*f+b*a+c}function vb(a,b, +c,d){var e=1-a;return e*e*b+2*(1-a)*a*c+a*a*d}function wb(a,b,c,d,e){var f=1-a,g=1-a;return f*f*f*b+3*g*g*a*c+3*(1-a)*a*a*d+a*a*a*e}function pa(){this.arcLengthDivisions=200}function Oa(a,b){this.arcLengthDivisions=200;this.v1=a;this.v2=b}function Wc(){this.arcLengthDivisions=200;this.curves=[];this.autoClose=!1}function Ua(a,b,c,d,e,f,g,h){this.arcLengthDivisions=200;this.aX=a;this.aY=b;this.xRadius=c;this.yRadius=d;this.aStartAngle=e;this.aEndAngle=f;this.aClockwise=g;this.aRotation=h||0}function xb(a){this.arcLengthDivisions= +200;this.points=void 0===a?[]:a}function fc(a,b,c,d){this.arcLengthDivisions=200;this.v0=a;this.v1=b;this.v2=c;this.v3=d}function gc(a,b,c){this.arcLengthDivisions=200;this.v0=a;this.v1=b;this.v2=c}function Xc(a){Wc.call(this);this.currentPoint=new D;a&&this.fromPoints(a)}function yb(){Xc.apply(this,arguments);this.holes=[]}function ee(){this.subPaths=[];this.currentPath=null}function fe(a){this.data=a}function Te(a){this.manager=void 0!==a?a:va}function ge(a){this.manager=void 0!==a?a:va}function Ue(){this.type= +"StereoCamera";this.aspect=1;this.eyeSep=.064;this.cameraL=new ha;this.cameraL.layers.enable(1);this.cameraL.matrixAutoUpdate=!1;this.cameraR=new ha;this.cameraR.layers.enable(2);this.cameraR.matrixAutoUpdate=!1}function Yc(a,b,c){z.call(this);this.type="CubeCamera";var d=new ha(90,1,a,b);d.up.set(0,-1,0);d.lookAt(new p(1,0,0));this.add(d);var e=new ha(90,1,a,b);e.up.set(0,-1,0);e.lookAt(new p(-1,0,0));this.add(e);var f=new ha(90,1,a,b);f.up.set(0,0,1);f.lookAt(new p(0,1,0));this.add(f);var g=new ha(90, +1,a,b);g.up.set(0,0,-1);g.lookAt(new p(0,-1,0));this.add(g);var h=new ha(90,1,a,b);h.up.set(0,-1,0);h.lookAt(new p(0,0,1));this.add(h);var k=new ha(90,1,a,b);k.up.set(0,-1,0);k.lookAt(new p(0,0,-1));this.add(k);this.renderTarget=new Cb(c,c,{format:1022,magFilter:1006,minFilter:1006});this.renderTarget.texture.name="CubeCamera";this.update=function(a,b){null===this.parent&&this.updateMatrixWorld();var c=this.renderTarget,l=c.texture.generateMipmaps;c.texture.generateMipmaps=!1;c.activeCubeFace=0;a.render(b, +d,c);c.activeCubeFace=1;a.render(b,e,c);c.activeCubeFace=2;a.render(b,f,c);c.activeCubeFace=3;a.render(b,g,c);c.activeCubeFace=4;a.render(b,h,c);c.texture.generateMipmaps=l;c.activeCubeFace=5;a.render(b,k,c);a.setRenderTarget(null)};this.clear=function(a,b,c,d){for(var e=this.renderTarget,f=0;6>f;f++)e.activeCubeFace=f,a.setRenderTarget(e),a.clear(b,c,d);a.setRenderTarget(null)}}function he(){z.call(this);this.type="AudioListener";this.context=ie.getContext();this.gain=this.context.createGain();this.gain.connect(this.context.destination); +this.filter=null}function hc(a){z.call(this);this.type="Audio";this.context=a.context;this.gain=this.context.createGain();this.gain.connect(a.getInput());this.autoplay=!1;this.buffer=null;this.loop=!1;this.startTime=0;this.playbackRate=1;this.isPlaying=!1;this.hasPlaybackControl=!0;this.sourceType="empty";this.filters=[]}function je(a){hc.call(this,a);this.panner=this.context.createPanner();this.panner.connect(this.gain)}function ke(a,b){this.analyser=a.context.createAnalyser();this.analyser.fftSize= +void 0!==b?b:2048;this.data=new Uint8Array(this.analyser.frequencyBinCount);a.getOutput().connect(this.analyser)}function le(a,b,c){this.binding=a;this.valueSize=c;a=Float64Array;switch(b){case "quaternion":b=this._slerp;break;case "string":case "bool":a=Array;b=this._select;break;default:b=this._lerp}this.buffer=new a(4*c);this._mixBufferRegion=b;this.referenceCount=this.useCount=this.cumulativeWeight=0}function Ve(a,b,c){c=c||Y.parseTrackName(b);this._targetGroup=a;this._bindings=a.subscribe_(b, +c)}function Y(a,b,c){this.path=b;this.parsedPath=c||Y.parseTrackName(b);this.node=Y.findNode(a,this.parsedPath.nodeName)||a;this.rootNode=a}function We(a){this.uuid=R.generateUUID();this._objects=Array.prototype.slice.call(arguments);this.nCachedObjects_=0;var b={};this._indicesByUUID=b;for(var c=0,d=arguments.length;c!==d;++c)b[arguments[c].uuid]=c;this._paths=[];this._parsedPaths=[];this._bindings=[];this._bindingsIndicesByPath={};var e=this;this.stats={objects:{get total(){return e._objects.length}, get inUse(){return this.total-e.nCachedObjects_}},get bindingsPerObject(){return e._bindings.length}}}function Xe(a,b,c){this._mixer=a;this._clip=b;this._localRoot=c||null;a=b.tracks;b=a.length;c=Array(b);for(var d={endingStart:2400,endingEnd:2400},e=0;e!==b;++e){var f=a[e].createInterpolant(null);c[e]=f;f.settings=d}this._interpolantSettings=d;this._interpolants=c;this._propertyBindings=Array(b);this._weightInterpolant=this._timeScaleInterpolant=this._byClipCacheIndex=this._cacheIndex=null;this.loop= -2201;this._loopCount=-1;this._startTime=null;this.time=0;this._effectiveWeight=this.weight=this._effectiveTimeScale=this.timeScale=1;this.repetitions=Infinity;this.paused=!1;this.enabled=!0;this.clampWhenFinished=!1;this.zeroSlopeAtEnd=this.zeroSlopeAtStart=!0}function Ye(a){this._root=a;this._initMemoryManager();this.time=this._accuIndex=0;this.timeScale=1}function Jd(a,b){"string"===typeof a&&(console.warn("THREE.Uniform: Type parameter is no longer needed."),a=b);this.value=a}function me(){I.call(this); -this.type="InstancedBufferGeometry";this.maxInstancedCount=void 0}function ne(a,b,c,d){this.uuid=Y.generateUUID();this.data=a;this.itemSize=b;this.offset=c;this.normalized=!0===d}function kc(a,b){this.uuid=Y.generateUUID();this.array=a;this.stride=b;this.count=void 0!==a?a.length/b:0;this.dynamic=!1;this.updateRange={offset:0,count:-1};this.onUploadCallback=function(){};this.version=0}function oe(a,b,c){kc.call(this,a,b);this.meshPerAttribute=c||1}function pe(a,b,c){L.call(this,a,b);this.meshPerAttribute= -c||1}function Ze(a,b,c,d){this.ray=new hb(a,b);this.near=c||0;this.far=d||Infinity;this.params={Mesh:{},Line:{},LOD:{},Points:{threshold:1},Sprite:{}};Object.defineProperties(this.params,{PointCloud:{get:function(){console.warn("THREE.Raycaster: params.PointCloud has been renamed to params.Points.");return this.Points}}})}function $e(a,b){return a.distance-b.distance}function qe(a,b,c,d){if(!1!==a.visible&&(a.raycast(b,c),!0===d)){a=a.children;d=0;for(var e=a.length;dc;c++,d++){var e=c/32*Math.PI*2,f=d/32*Math.PI*2;b.push(Math.cos(e),Math.sin(e),1,Math.cos(f),Math.sin(f),1)}a.addAttribute("position",new D(b,3));b=new ha({fog:!1});this.cone=new da(a,b);this.add(this.cone);this.update()}function mc(a){this.bones=this.getBoneList(a);for(var b=new I,c=[],d=[],e=new H(0,0,1),f=new H(0,1,0),g=0;ga.length&&console.warn("THREE.CatmullRomCurve3: Points array needs at least two entries.");this.points=a||[];this.closed=!1}function ed(a,b,c,d){this.arcLengthDivisions=200;this.v0=a;this.v1=b;this.v2=c;this.v3=d}function fd(a,b,c){this.arcLengthDivisions=200;this.v0=a;this.v1=b;this.v2=c} -function gd(a,b){this.arcLengthDivisions=200;this.v1=a;this.v2=b}function Nd(a,b,c,d,e,f){Xa.call(this,a,b,c,c,d,e,f)}function df(a){console.warn("THREE.ClosedSplineCurve3 has been deprecated. Use THREE.CatmullRomCurve3 instead.");Ja.call(this,a);this.type="catmullrom";this.closed=!0}function ef(a){console.warn("THREE.SplineCurve3 has been deprecated. Use THREE.CatmullRomCurve3 instead.");Ja.call(this,a);this.type="catmullrom"}function te(a){console.warn("THREE.Spline has been removed. Use THREE.CatmullRomCurve3 instead."); -Ja.call(this,a);this.type="catmullrom"}void 0===Number.EPSILON&&(Number.EPSILON=Math.pow(2,-52));void 0===Number.isInteger&&(Number.isInteger=function(a){return"number"===typeof a&&isFinite(a)&&Math.floor(a)===a});void 0===Math.sign&&(Math.sign=function(a){return 0>a?-1:0e;e++)8===e||13===e||18===e||23===e?b[e]="-":14===e?b[e]="4":(2>=c&&(c=33554432+16777216*Math.random()|0),d=c&15,c>>=4,b[e]=a[19===e?d&3|8:d]);return b.join("")}}(),clamp:function(a,b,c){return Math.max(b,Math.min(c,a))},euclideanModulo:function(a,b){return(a%b+b)%b},mapLinear:function(a,b,c,d,e){return d+(a-b)*(e-d)/(c-b)},lerp:function(a,b,c){return(1-c)*a+c*b},smoothstep:function(a,b,c){if(a<=b)return 0;if(a>=c)return 1;a=(a-b)/(c-b);return a* -a*(3-2*a)},smootherstep:function(a,b,c){if(a<=b)return 0;if(a>=c)return 1;a=(a-b)/(c-b);return a*a*a*(a*(6*a-15)+10)},randInt:function(a,b){return a+Math.floor(Math.random()*(b-a+1))},randFloat:function(a,b){return a+Math.random()*(b-a)},randFloatSpread:function(a){return a*(.5-Math.random())},degToRad:function(a){return a*Y.DEG2RAD},radToDeg:function(a){return a*Y.RAD2DEG},isPowerOfTwo:function(a){return 0===(a&a-1)&&0!==a},nearestPowerOfTwo:function(a){return Math.pow(2,Math.round(Math.log(a)/Math.LN2))}, -nextPowerOfTwo:function(a){a--;a|=a>>1;a|=a>>2;a|=a>>4;a|=a>>8;a|=a>>16;a++;return a}};Object.defineProperties(E.prototype,{width:{get:function(){return this.x},set:function(a){this.x=a}},height:{get:function(){return this.y},set:function(a){this.y=a}}});Object.assign(E.prototype,{isVector2:!0,set:function(a,b){this.x=a;this.y=b;return this},setScalar:function(a){this.y=this.x=a;return this},setX:function(a){this.x=a;return this},setY:function(a){this.y=a;return this},setComponent:function(a,b){switch(a){case 0:this.x= -b;break;case 1:this.y=b;break;default:throw Error("index is out of range: "+a);}return this},getComponent:function(a){switch(a){case 0:return this.x;case 1:return this.y;default:throw Error("index is out of range: "+a);}},clone:function(){return new this.constructor(this.x,this.y)},copy:function(a){this.x=a.x;this.y=a.y;return this},add:function(a,b){if(void 0!==b)return console.warn("THREE.Vector2: .add() now only accepts one argument. Use .addVectors( a, b ) instead."),this.addVectors(a,b);this.x+= -a.x;this.y+=a.y;return this},addScalar:function(a){this.x+=a;this.y+=a;return this},addVectors:function(a,b){this.x=a.x+b.x;this.y=a.y+b.y;return this},addScaledVector:function(a,b){this.x+=a.x*b;this.y+=a.y*b;return this},sub:function(a,b){if(void 0!==b)return console.warn("THREE.Vector2: .sub() now only accepts one argument. Use .subVectors( a, b ) instead."),this.subVectors(a,b);this.x-=a.x;this.y-=a.y;return this},subScalar:function(a){this.x-=a;this.y-=a;return this},subVectors:function(a,b){this.x= -a.x-b.x;this.y=a.y-b.y;return this},multiply:function(a){this.x*=a.x;this.y*=a.y;return this},multiplyScalar:function(a){this.x*=a;this.y*=a;return this},divide:function(a){this.x/=a.x;this.y/=a.y;return this},divideScalar:function(a){return this.multiplyScalar(1/a)},min:function(a){this.x=Math.min(this.x,a.x);this.y=Math.min(this.y,a.y);return this},max:function(a){this.x=Math.max(this.x,a.x);this.y=Math.max(this.y,a.y);return this},clamp:function(a,b){this.x=Math.max(a.x,Math.min(b.x,this.x));this.y= -Math.max(a.y,Math.min(b.y,this.y));return this},clampScalar:function(){var a=new E,b=new E;return function(c,d){a.set(c,c);b.set(d,d);return this.clamp(a,b)}}(),clampLength:function(a,b){var c=this.length();return this.multiplyScalar(Math.max(a,Math.min(b,c))/c)},floor:function(){this.x=Math.floor(this.x);this.y=Math.floor(this.y);return this},ceil:function(){this.x=Math.ceil(this.x);this.y=Math.ceil(this.y);return this},round:function(){this.x=Math.round(this.x);this.y=Math.round(this.y);return this}, -roundToZero:function(){this.x=0>this.x?Math.ceil(this.x):Math.floor(this.x);this.y=0>this.y?Math.ceil(this.y):Math.floor(this.y);return this},negate:function(){this.x=-this.x;this.y=-this.y;return this},dot:function(a){return this.x*a.x+this.y*a.y},lengthSq:function(){return this.x*this.x+this.y*this.y},length:function(){return Math.sqrt(this.x*this.x+this.y*this.y)},lengthManhattan:function(){return Math.abs(this.x)+Math.abs(this.y)},normalize:function(){return this.divideScalar(this.length())}, -angle:function(){var a=Math.atan2(this.y,this.x);0>a&&(a+=2*Math.PI);return a},distanceTo:function(a){return Math.sqrt(this.distanceToSquared(a))},distanceToSquared:function(a){var b=this.x-a.x;a=this.y-a.y;return b*b+a*a},distanceToManhattan:function(a){return Math.abs(this.x-a.x)+Math.abs(this.y-a.y)},setLength:function(a){return this.multiplyScalar(a/this.length())},lerp:function(a,b){this.x+=(a.x-this.x)*b;this.y+=(a.y-this.y)*b;return this},lerpVectors:function(a,b,c){return this.subVectors(b, -a).multiplyScalar(c).add(a)},equals:function(a){return a.x===this.x&&a.y===this.y},fromArray:function(a,b){void 0===b&&(b=0);this.x=a[b];this.y=a[b+1];return this},toArray:function(a,b){void 0===a&&(a=[]);void 0===b&&(b=0);a[b]=this.x;a[b+1]=this.y;return a},fromBufferAttribute:function(a,b,c){void 0!==c&&console.warn("THREE.Vector2: offset has been removed from .fromBufferAttribute().");this.x=a.getX(b);this.y=a.getY(b);return this},rotateAround:function(a,b){var c=Math.cos(b),d=Math.sin(b),e=this.x- -a.x,f=this.y-a.y;this.x=e*c-f*d+a.x;this.y=e*d+f*c+a.y;return this}});var jf=0;X.DEFAULT_IMAGE=void 0;X.DEFAULT_MAPPING=300;Object.defineProperty(X.prototype,"needsUpdate",{set:function(a){!0===a&&this.version++}});Object.assign(X.prototype,sa.prototype,{constructor:X,isTexture:!0,clone:function(){return(new this.constructor).copy(this)},copy:function(a){this.name=a.name;this.image=a.image;this.mipmaps=a.mipmaps.slice(0);this.mapping=a.mapping;this.wrapS=a.wrapS;this.wrapT=a.wrapT;this.magFilter= -a.magFilter;this.minFilter=a.minFilter;this.anisotropy=a.anisotropy;this.format=a.format;this.type=a.type;this.offset.copy(a.offset);this.repeat.copy(a.repeat);this.generateMipmaps=a.generateMipmaps;this.premultiplyAlpha=a.premultiplyAlpha;this.flipY=a.flipY;this.unpackAlignment=a.unpackAlignment;this.encoding=a.encoding;return this},toJSON:function(a){if(void 0!==a.textures[this.uuid])return a.textures[this.uuid];var b={metadata:{version:4.5,type:"Texture",generator:"Texture.toJSON"},uuid:this.uuid, -name:this.name,mapping:this.mapping,repeat:[this.repeat.x,this.repeat.y],offset:[this.offset.x,this.offset.y],wrap:[this.wrapS,this.wrapT],minFilter:this.minFilter,magFilter:this.magFilter,anisotropy:this.anisotropy,flipY:this.flipY};if(void 0!==this.image){var c=this.image;void 0===c.uuid&&(c.uuid=Y.generateUUID());if(void 0===a.images[c.uuid]){var d=a.images,e=c.uuid,f=c.uuid,g;void 0!==c.toDataURL?g=c:(g=document.createElementNS("http://www.w3.org/1999/xhtml","canvas"),g.width=c.width,g.height= -c.height,g.getContext("2d").drawImage(c,0,0,c.width,c.height));g=2048a.x||1a.x?0:1;break;case 1002:a.x=1===Math.abs(Math.floor(a.x)% -2)?Math.ceil(a.x)-a.x:a.x-Math.floor(a.x)}if(0>a.y||1a.y?0:1;break;case 1002:a.y=1===Math.abs(Math.floor(a.y)%2)?Math.ceil(a.y)-a.y:a.y-Math.floor(a.y)}this.flipY&&(a.y=1-a.y)}}});Object.assign(ga.prototype,{isVector4:!0,set:function(a,b,c,d){this.x=a;this.y=b;this.z=c;this.w=d;return this},setScalar:function(a){this.w=this.z=this.y=this.x=a;return this},setX:function(a){this.x=a;return this},setY:function(a){this.y=a;return this}, -setZ:function(a){this.z=a;return this},setW:function(a){this.w=a;return this},setComponent:function(a,b){switch(a){case 0:this.x=b;break;case 1:this.y=b;break;case 2:this.z=b;break;case 3:this.w=b;break;default:throw Error("index is out of range: "+a);}return this},getComponent:function(a){switch(a){case 0:return this.x;case 1:return this.y;case 2:return this.z;case 3:return this.w;default:throw Error("index is out of range: "+a);}},clone:function(){return new this.constructor(this.x,this.y,this.z, -this.w)},copy:function(a){this.x=a.x;this.y=a.y;this.z=a.z;this.w=void 0!==a.w?a.w:1;return this},add:function(a,b){if(void 0!==b)return console.warn("THREE.Vector4: .add() now only accepts one argument. Use .addVectors( a, b ) instead."),this.addVectors(a,b);this.x+=a.x;this.y+=a.y;this.z+=a.z;this.w+=a.w;return this},addScalar:function(a){this.x+=a;this.y+=a;this.z+=a;this.w+=a;return this},addVectors:function(a,b){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},addScaledVector:function(a, -b){this.x+=a.x*b;this.y+=a.y*b;this.z+=a.z*b;this.w+=a.w*b;return this},sub:function(a,b){if(void 0!==b)return console.warn("THREE.Vector4: .sub() now only accepts one argument. Use .subVectors( a, b ) instead."),this.subVectors(a,b);this.x-=a.x;this.y-=a.y;this.z-=a.z;this.w-=a.w;return this},subScalar:function(a){this.x-=a;this.y-=a;this.z-=a;this.w-=a;return this},subVectors:function(a,b){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},multiplyScalar:function(a){this.x*= -a;this.y*=a;this.z*=a;this.w*=a;return this},applyMatrix4:function(a){var b=this.x,c=this.y,d=this.z,e=this.w;a=a.elements;this.x=a[0]*b+a[4]*c+a[8]*d+a[12]*e;this.y=a[1]*b+a[5]*c+a[9]*d+a[13]*e;this.z=a[2]*b+a[6]*c+a[10]*d+a[14]*e;this.w=a[3]*b+a[7]*c+a[11]*d+a[15]*e;return this},divideScalar:function(a){return this.multiplyScalar(1/a)},setAxisAngleFromQuaternion:function(a){this.w=2*Math.acos(a.w);var b=Math.sqrt(1-a.w*a.w);1E-4>b?(this.x=1,this.z=this.y=0):(this.x=a.x/b,this.y=a.y/b,this.z=a.z/ -b);return this},setAxisAngleFromRotationMatrix:function(a){var b,c,d;a=a.elements;var e=a[0];d=a[4];var f=a[8],g=a[1],h=a[5],k=a[9];c=a[2];b=a[6];var m=a[10];if(.01>Math.abs(d-g)&&.01>Math.abs(f-c)&&.01>Math.abs(k-b)){if(.1>Math.abs(d+g)&&.1>Math.abs(f+c)&&.1>Math.abs(k+b)&&.1>Math.abs(e+h+m-3))return this.set(1,0,0,0),this;a=Math.PI;e=(e+1)/2;h=(h+1)/2;m=(m+1)/2;d=(d+g)/4;f=(f+c)/4;k=(k+b)/4;e>h&&e>m?.01>e?(b=0,d=c=.707106781):(b=Math.sqrt(e),c=d/b,d=f/b):h>m?.01>h?(b=.707106781,c=0,d=.707106781): -(c=Math.sqrt(h),b=d/c,d=k/c):.01>m?(c=b=.707106781,d=0):(d=Math.sqrt(m),b=f/d,c=k/d);this.set(b,c,d,a);return this}a=Math.sqrt((b-k)*(b-k)+(f-c)*(f-c)+(g-d)*(g-d));.001>Math.abs(a)&&(a=1);this.x=(b-k)/a;this.y=(f-c)/a;this.z=(g-d)/a;this.w=Math.acos((e+h+m-1)/2);return this},min:function(a){this.x=Math.min(this.x,a.x);this.y=Math.min(this.y,a.y);this.z=Math.min(this.z,a.z);this.w=Math.min(this.w,a.w);return this},max:function(a){this.x=Math.max(this.x,a.x);this.y=Math.max(this.y,a.y);this.z=Math.max(this.z, -a.z);this.w=Math.max(this.w,a.w);return this},clamp:function(a,b){this.x=Math.max(a.x,Math.min(b.x,this.x));this.y=Math.max(a.y,Math.min(b.y,this.y));this.z=Math.max(a.z,Math.min(b.z,this.z));this.w=Math.max(a.w,Math.min(b.w,this.w));return this},clampScalar:function(){var a=new ga,b=new ga;return function(c,d){a.set(c,c,c,c);b.set(d,d,d,d);return this.clamp(a,b)}}(),floor:function(){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}, -ceil:function(){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},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);return this},roundToZero:function(){this.x=0>this.x?Math.ceil(this.x):Math.floor(this.x);this.y=0>this.y?Math.ceil(this.y):Math.floor(this.y);this.z=0>this.z?Math.ceil(this.z):Math.floor(this.z);this.w=0>this.w?Math.ceil(this.w):Math.floor(this.w);return this}, -negate:function(){this.x=-this.x;this.y=-this.y;this.z=-this.z;this.w=-this.w;return this},dot:function(a){return this.x*a.x+this.y*a.y+this.z*a.z+this.w*a.w},lengthSq:function(){return this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w},length:function(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w)},lengthManhattan:function(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)+Math.abs(this.w)},normalize:function(){return this.divideScalar(this.length())}, -setLength:function(a){return this.multiplyScalar(a/this.length())},lerp:function(a,b){this.x+=(a.x-this.x)*b;this.y+=(a.y-this.y)*b;this.z+=(a.z-this.z)*b;this.w+=(a.w-this.w)*b;return this},lerpVectors:function(a,b,c){return this.subVectors(b,a).multiplyScalar(c).add(a)},equals:function(a){return a.x===this.x&&a.y===this.y&&a.z===this.z&&a.w===this.w},fromArray:function(a,b){void 0===b&&(b=0);this.x=a[b];this.y=a[b+1];this.z=a[b+2];this.w=a[b+3];return this},toArray:function(a,b){void 0===a&&(a= -[]);void 0===b&&(b=0);a[b]=this.x;a[b+1]=this.y;a[b+2]=this.z;a[b+3]=this.w;return a},fromBufferAttribute:function(a,b,c){void 0!==c&&console.warn("THREE.Vector4: offset has been removed from .fromBufferAttribute().");this.x=a.getX(b);this.y=a.getY(b);this.z=a.getZ(b);this.w=a.getW(b);return this}});Object.assign(Db.prototype,sa.prototype,{isWebGLRenderTarget:!0,setSize:function(a,b){if(this.width!==a||this.height!==b)this.width=a,this.height=b,this.dispose();this.viewport.set(0,0,a,b);this.scissor.set(0, -0,a,b)},clone:function(){return(new this.constructor).copy(this)},copy:function(a){this.width=a.width;this.height=a.height;this.viewport.copy(a.viewport);this.texture=a.texture.clone();this.depthBuffer=a.depthBuffer;this.stencilBuffer=a.stencilBuffer;this.depthTexture=a.depthTexture;return this},dispose:function(){this.dispatchEvent({type:"dispose"})}});Eb.prototype=Object.create(Db.prototype);Eb.prototype.constructor=Eb;Eb.prototype.isWebGLRenderTargetCube=!0;Object.assign(qa,{slerp:function(a,b, -c,d){return c.copy(a).slerp(b,d)},slerpFlat:function(a,b,c,d,e,f,g){var h=c[d+0],k=c[d+1],m=c[d+2];c=c[d+3];d=e[f+0];var u=e[f+1],l=e[f+2];e=e[f+3];if(c!==e||h!==d||k!==u||m!==l){f=1-g;var n=h*d+k*u+m*l+c*e,t=0<=n?1:-1,p=1-n*n;p>Number.EPSILON&&(p=Math.sqrt(p),n=Math.atan2(p,n*t),f=Math.sin(f*n)/p,g=Math.sin(g*n)/p);t*=g;h=h*f+d*t;k=k*f+u*t;m=m*f+l*t;c=c*f+e*t;f===1-g&&(g=1/Math.sqrt(h*h+k*k+m*m+c*c),h*=g,k*=g,m*=g,c*=g)}a[b]=h;a[b+1]=k;a[b+2]=m;a[b+3]=c}});Object.defineProperties(qa.prototype,{x:{get:function(){return this._x}, -set:function(a){this._x=a;this.onChangeCallback()}},y:{get:function(){return this._y},set:function(a){this._y=a;this.onChangeCallback()}},z:{get:function(){return this._z},set:function(a){this._z=a;this.onChangeCallback()}},w:{get:function(){return this._w},set:function(a){this._w=a;this.onChangeCallback()}}});Object.assign(qa.prototype,{set:function(a,b,c,d){this._x=a;this._y=b;this._z=c;this._w=d;this.onChangeCallback();return this},clone:function(){return new this.constructor(this._x,this._y,this._z, -this._w)},copy:function(a){this._x=a.x;this._y=a.y;this._z=a.z;this._w=a.w;this.onChangeCallback();return this},setFromEuler:function(a,b){if(!1===(a&&a.isEuler))throw Error("THREE.Quaternion: .setFromEuler() now expects an Euler rotation rather than a Vector3 and order.");var c=a._x,d=a._y,e=a._z,f=a.order,g=Math.cos,h=Math.sin,k=g(c/2),m=g(d/2),g=g(e/2),c=h(c/2),d=h(d/2),e=h(e/2);"XYZ"===f?(this._x=c*m*g+k*d*e,this._y=k*d*g-c*m*e,this._z=k*m*e+c*d*g,this._w=k*m*g-c*d*e):"YXZ"===f?(this._x=c*m*g+ -k*d*e,this._y=k*d*g-c*m*e,this._z=k*m*e-c*d*g,this._w=k*m*g+c*d*e):"ZXY"===f?(this._x=c*m*g-k*d*e,this._y=k*d*g+c*m*e,this._z=k*m*e+c*d*g,this._w=k*m*g-c*d*e):"ZYX"===f?(this._x=c*m*g-k*d*e,this._y=k*d*g+c*m*e,this._z=k*m*e-c*d*g,this._w=k*m*g+c*d*e):"YZX"===f?(this._x=c*m*g+k*d*e,this._y=k*d*g+c*m*e,this._z=k*m*e-c*d*g,this._w=k*m*g-c*d*e):"XZY"===f&&(this._x=c*m*g-k*d*e,this._y=k*d*g-c*m*e,this._z=k*m*e+c*d*g,this._w=k*m*g+c*d*e);if(!1!==b)this.onChangeCallback();return this},setFromAxisAngle:function(a, -b){var c=b/2,d=Math.sin(c);this._x=a.x*d;this._y=a.y*d;this._z=a.z*d;this._w=Math.cos(c);this.onChangeCallback();return this},setFromRotationMatrix:function(a){var b=a.elements,c=b[0];a=b[4];var d=b[8],e=b[1],f=b[5],g=b[9],h=b[2],k=b[6],b=b[10],m=c+f+b;0f&&c>b?(c=2*Math.sqrt(1+c-f-b),this._w=(k-g)/c,this._x=.25*c,this._y=(a+e)/c,this._z=(d+h)/c):f>b?(c=2*Math.sqrt(1+f-c-b),this._w=(d-h)/c,this._x=(a+e)/c,this._y= +2201;this._loopCount=-1;this._startTime=null;this.time=0;this._effectiveWeight=this.weight=this._effectiveTimeScale=this.timeScale=1;this.repetitions=Infinity;this.paused=!1;this.enabled=!0;this.clampWhenFinished=!1;this.zeroSlopeAtEnd=this.zeroSlopeAtStart=!0}function Ye(a){this._root=a;this._initMemoryManager();this.time=this._accuIndex=0;this.timeScale=1}function Id(a,b){"string"===typeof a&&(console.warn("THREE.Uniform: Type parameter is no longer needed."),a=b);this.value=a}function me(){E.call(this); +this.type="InstancedBufferGeometry";this.maxInstancedCount=void 0}function ne(a,b,c,d){this.uuid=R.generateUUID();this.data=a;this.itemSize=b;this.offset=c;this.normalized=!0===d}function ic(a,b){this.uuid=R.generateUUID();this.array=a;this.stride=b;this.count=void 0!==a?a.length/b:0;this.dynamic=!1;this.updateRange={offset:0,count:-1};this.onUploadCallback=function(){};this.version=0}function oe(a,b,c){ic.call(this,a,b);this.meshPerAttribute=c||1}function pe(a,b,c){Q.call(this,a,b);this.meshPerAttribute= +c||1}function Ze(a,b,c,d){this.ray=new ib(a,b);this.near=c||0;this.far=d||Infinity;this.params={Mesh:{},Line:{},LOD:{},Points:{threshold:1},Sprite:{}};Object.defineProperties(this.params,{PointCloud:{get:function(){console.warn("THREE.Raycaster: params.PointCloud has been renamed to params.Points.");return this.Points}}})}function $e(a,b){return a.distance-b.distance}function qe(a,b,c,d){if(!1!==a.visible&&(a.raycast(b,c),!0===d)){a=a.children;d=0;for(var e=a.length;dc;c++,d++){var e=c/32*Math.PI*2,f=d/32*Math.PI*2;b.push(Math.cos(e), +Math.sin(e),1,Math.cos(f),Math.sin(f),1)}a.addAttribute("position",new y(b,3));b=new X({fog:!1});this.cone=new T(a,b);this.add(this.cone);this.update()}function df(a){var b=[];a&&a.isBone&&b.push(a);for(var c=0;ca.length&&console.warn("THREE.CatmullRomCurve3: Points array needs at least two entries.");this.points=a||[];this.closed=!1}function fd(a,b,c,d){this.arcLengthDivisions=200;this.v0=a;this.v1=b;this.v2=c;this.v3=d}function gd(a,b,c){this.arcLengthDivisions=200;this.v0=a;this.v1=b;this.v2=c}function hd(a,b){this.arcLengthDivisions=200;this.v1=a;this.v2=b}function Md(a,b,c,d,e,f){Ua.call(this,a,b,c,c,d,e,f)}function ef(a){console.warn("THREE.ClosedSplineCurve3 has been deprecated. Use THREE.CatmullRomCurve3 instead."); +Ja.call(this,a);this.type="catmullrom";this.closed=!0}function ff(a){console.warn("THREE.SplineCurve3 has been deprecated. Use THREE.CatmullRomCurve3 instead.");Ja.call(this,a);this.type="catmullrom"}function te(a){console.warn("THREE.Spline has been removed. Use THREE.CatmullRomCurve3 instead.");Ja.call(this,a);this.type="catmullrom"}void 0===Number.EPSILON&&(Number.EPSILON=Math.pow(2,-52));void 0===Number.isInteger&&(Number.isInteger=function(a){return"number"===typeof a&&isFinite(a)&&Math.floor(a)=== +a});void 0===Math.sign&&(Math.sign=function(a){return 0>a?-1:0e;e++)8===e||13===e||18===e||23===e?b[e]="-":14===e?b[e]="4":(2>=c&&(c=33554432+16777216*Math.random()|0),d=c&15,c>>=4,b[e]=a[19===e?d&3|8:d]);return b.join("")}}(), +clamp:function(a,b,c){return Math.max(b,Math.min(c,a))},euclideanModulo:function(a,b){return(a%b+b)%b},mapLinear:function(a,b,c,d,e){return d+(a-b)*(e-d)/(c-b)},lerp:function(a,b,c){return(1-c)*a+c*b},smoothstep:function(a,b,c){if(a<=b)return 0;if(a>=c)return 1;a=(a-b)/(c-b);return a*a*(3-2*a)},smootherstep:function(a,b,c){if(a<=b)return 0;if(a>=c)return 1;a=(a-b)/(c-b);return a*a*a*(a*(6*a-15)+10)},randInt:function(a,b){return a+Math.floor(Math.random()*(b-a+1))},randFloat:function(a,b){return a+ +Math.random()*(b-a)},randFloatSpread:function(a){return a*(.5-Math.random())},degToRad:function(a){return a*R.DEG2RAD},radToDeg:function(a){return a*R.RAD2DEG},isPowerOfTwo:function(a){return 0===(a&a-1)&&0!==a},nearestPowerOfTwo:function(a){return Math.pow(2,Math.round(Math.log(a)/Math.LN2))},nextPowerOfTwo:function(a){a--;a|=a>>1;a|=a>>2;a|=a>>4;a|=a>>8;a|=a>>16;a++;return a}};Object.defineProperties(D.prototype,{width:{get:function(){return this.x},set:function(a){this.x=a}},height:{get:function(){return this.y}, +set:function(a){this.y=a}}});Object.assign(D.prototype,{isVector2:!0,set:function(a,b){this.x=a;this.y=b;return this},setScalar:function(a){this.y=this.x=a;return this},setX:function(a){this.x=a;return this},setY:function(a){this.y=a;return this},setComponent:function(a,b){switch(a){case 0:this.x=b;break;case 1:this.y=b;break;default:throw Error("index is out of range: "+a);}return this},getComponent:function(a){switch(a){case 0:return this.x;case 1:return this.y;default:throw Error("index is out of range: "+ +a);}},clone:function(){return new this.constructor(this.x,this.y)},copy:function(a){this.x=a.x;this.y=a.y;return this},add:function(a,b){if(void 0!==b)return console.warn("THREE.Vector2: .add() now only accepts one argument. Use .addVectors( a, b ) instead."),this.addVectors(a,b);this.x+=a.x;this.y+=a.y;return this},addScalar:function(a){this.x+=a;this.y+=a;return this},addVectors:function(a,b){this.x=a.x+b.x;this.y=a.y+b.y;return this},addScaledVector:function(a,b){this.x+=a.x*b;this.y+=a.y*b;return this}, +sub:function(a,b){if(void 0!==b)return console.warn("THREE.Vector2: .sub() now only accepts one argument. Use .subVectors( a, b ) instead."),this.subVectors(a,b);this.x-=a.x;this.y-=a.y;return this},subScalar:function(a){this.x-=a;this.y-=a;return this},subVectors:function(a,b){this.x=a.x-b.x;this.y=a.y-b.y;return this},multiply:function(a){this.x*=a.x;this.y*=a.y;return this},multiplyScalar:function(a){this.x*=a;this.y*=a;return this},divide:function(a){this.x/=a.x;this.y/=a.y;return this},divideScalar:function(a){return this.multiplyScalar(1/ +a)},applyMatrix3:function(a){var b=this.x,c=this.y;a=a.elements;this.x=a[0]*b+a[3]*c+a[6];this.y=a[1]*b+a[4]*c+a[7];return this},min:function(a){this.x=Math.min(this.x,a.x);this.y=Math.min(this.y,a.y);return this},max:function(a){this.x=Math.max(this.x,a.x);this.y=Math.max(this.y,a.y);return this},clamp:function(a,b){this.x=Math.max(a.x,Math.min(b.x,this.x));this.y=Math.max(a.y,Math.min(b.y,this.y));return this},clampScalar:function(){var a=new D,b=new D;return function(c,d){a.set(c,c);b.set(d,d); +return this.clamp(a,b)}}(),clampLength:function(a,b){var c=this.length();return this.divideScalar(c||1).multiplyScalar(Math.max(a,Math.min(b,c)))},floor:function(){this.x=Math.floor(this.x);this.y=Math.floor(this.y);return this},ceil:function(){this.x=Math.ceil(this.x);this.y=Math.ceil(this.y);return this},round:function(){this.x=Math.round(this.x);this.y=Math.round(this.y);return this},roundToZero:function(){this.x=0>this.x?Math.ceil(this.x):Math.floor(this.x);this.y=0>this.y?Math.ceil(this.y):Math.floor(this.y); +return this},negate:function(){this.x=-this.x;this.y=-this.y;return this},dot:function(a){return this.x*a.x+this.y*a.y},lengthSq:function(){return this.x*this.x+this.y*this.y},length:function(){return Math.sqrt(this.x*this.x+this.y*this.y)},lengthManhattan:function(){return Math.abs(this.x)+Math.abs(this.y)},normalize:function(){return this.divideScalar(this.length()||1)},angle:function(){var a=Math.atan2(this.y,this.x);0>a&&(a+=2*Math.PI);return a},distanceTo:function(a){return Math.sqrt(this.distanceToSquared(a))}, +distanceToSquared:function(a){var b=this.x-a.x;a=this.y-a.y;return b*b+a*a},distanceToManhattan:function(a){return Math.abs(this.x-a.x)+Math.abs(this.y-a.y)},setLength:function(a){return this.normalize().multiplyScalar(a)},lerp:function(a,b){this.x+=(a.x-this.x)*b;this.y+=(a.y-this.y)*b;return this},lerpVectors:function(a,b,c){return this.subVectors(b,a).multiplyScalar(c).add(a)},equals:function(a){return a.x===this.x&&a.y===this.y},fromArray:function(a,b){void 0===b&&(b=0);this.x=a[b];this.y=a[b+ +1];return this},toArray:function(a,b){void 0===a&&(a=[]);void 0===b&&(b=0);a[b]=this.x;a[b+1]=this.y;return a},fromBufferAttribute:function(a,b,c){void 0!==c&&console.warn("THREE.Vector2: offset has been removed from .fromBufferAttribute().");this.x=a.getX(b);this.y=a.getY(b);return this},rotateAround:function(a,b){var c=Math.cos(b);b=Math.sin(b);var d=this.x-a.x,e=this.y-a.y;this.x=d*c-e*b+a.x;this.y=d*b+e*c+a.y;return this}});Object.assign(K.prototype,{isMatrix4:!0,set:function(a,b,c,d,e,f,g,h, +k,l,q,n,m,r,p,t){var u=this.elements;u[0]=a;u[4]=b;u[8]=c;u[12]=d;u[1]=e;u[5]=f;u[9]=g;u[13]=h;u[2]=k;u[6]=l;u[10]=q;u[14]=n;u[3]=m;u[7]=r;u[11]=p;u[15]=t;return this},identity:function(){this.set(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1);return this},clone:function(){return(new K).fromArray(this.elements)},copy:function(a){var b=this.elements;a=a.elements;b[0]=a[0];b[1]=a[1];b[2]=a[2];b[3]=a[3];b[4]=a[4];b[5]=a[5];b[6]=a[6];b[7]=a[7];b[8]=a[8];b[9]=a[9];b[10]=a[10];b[11]=a[11];b[12]=a[12];b[13]=a[13];b[14]= +a[14];b[15]=a[15];return this},copyPosition:function(a){var b=this.elements;a=a.elements;b[12]=a[12];b[13]=a[13];b[14]=a[14];return this},extractBasis:function(a,b,c){a.setFromMatrixColumn(this,0);b.setFromMatrixColumn(this,1);c.setFromMatrixColumn(this,2);return this},makeBasis:function(a,b,c){this.set(a.x,b.x,c.x,0,a.y,b.y,c.y,0,a.z,b.z,c.z,0,0,0,0,1);return this},extractRotation:function(){var a=new p;return function(b){var c=this.elements,d=b.elements,e=1/a.setFromMatrixColumn(b,0).length(),f= +1/a.setFromMatrixColumn(b,1).length();b=1/a.setFromMatrixColumn(b,2).length();c[0]=d[0]*e;c[1]=d[1]*e;c[2]=d[2]*e;c[4]=d[4]*f;c[5]=d[5]*f;c[6]=d[6]*f;c[8]=d[8]*b;c[9]=d[9]*b;c[10]=d[10]*b;return this}}(),makeRotationFromEuler:function(a){a&&a.isEuler||console.error("THREE.Matrix4: .makeRotationFromEuler() now expects a Euler rotation rather than a Vector3 and order.");var b=this.elements,c=a.x,d=a.y,e=a.z,f=Math.cos(c),c=Math.sin(c),g=Math.cos(d),d=Math.sin(d),h=Math.cos(e),e=Math.sin(e);if("XYZ"=== +a.order){var k=f*h;var l=f*e;var q=c*h;a=c*e;b[0]=g*h;b[4]=-g*e;b[8]=d;b[1]=l+q*d;b[5]=k-a*d;b[9]=-c*g;b[2]=a-k*d;b[6]=q+l*d;b[10]=f*g}else"YXZ"===a.order?(k=g*h,l=g*e,q=d*h,a=d*e,b[0]=k+a*c,b[4]=q*c-l,b[8]=f*d,b[1]=f*e,b[5]=f*h,b[9]=-c,b[2]=l*c-q,b[6]=a+k*c,b[10]=f*g):"ZXY"===a.order?(k=g*h,l=g*e,q=d*h,a=d*e,b[0]=k-a*c,b[4]=-f*e,b[8]=q+l*c,b[1]=l+q*c,b[5]=f*h,b[9]=a-k*c,b[2]=-f*d,b[6]=c,b[10]=f*g):"ZYX"===a.order?(k=f*h,l=f*e,q=c*h,a=c*e,b[0]=g*h,b[4]=q*d-l,b[8]=k*d+a,b[1]=g*e,b[5]=a*d+k,b[9]=l* +d-q,b[2]=-d,b[6]=c*g,b[10]=f*g):"YZX"===a.order?(k=f*g,l=f*d,q=c*g,a=c*d,b[0]=g*h,b[4]=a-k*e,b[8]=q*e+l,b[1]=e,b[5]=f*h,b[9]=-c*h,b[2]=-d*h,b[6]=l*e+q,b[10]=k-a*e):"XZY"===a.order&&(k=f*g,l=f*d,q=c*g,a=c*d,b[0]=g*h,b[4]=-e,b[8]=d*h,b[1]=k*e+a,b[5]=f*h,b[9]=l*e-q,b[2]=q*e-l,b[6]=c*h,b[10]=a*e+k);b[3]=0;b[7]=0;b[11]=0;b[12]=0;b[13]=0;b[14]=0;b[15]=1;return this},makeRotationFromQuaternion:function(a){var b=this.elements,c=a._x,d=a._y,e=a._z,f=a._w,g=c+c,h=d+d,k=e+e;a=c*g;var l=c*h,c=c*k,q=d*h,d=d*k, +e=e*k,g=f*g,h=f*h,f=f*k;b[0]=1-(q+e);b[4]=l-f;b[8]=c+h;b[1]=l+f;b[5]=1-(a+e);b[9]=d-g;b[2]=c-h;b[6]=d+g;b[10]=1-(a+q);b[3]=0;b[7]=0;b[11]=0;b[12]=0;b[13]=0;b[14]=0;b[15]=1;return this},lookAt:function(){var a=new p,b=new p,c=new p;return function(d,e,f){var g=this.elements;c.subVectors(d,e);0===c.lengthSq()&&(c.z=1);c.normalize();a.crossVectors(f,c);0===a.lengthSq()&&(1===Math.abs(f.z)?c.x+=1E-4:c.z+=1E-4,c.normalize(),a.crossVectors(f,c));a.normalize();b.crossVectors(c,a);g[0]=a.x;g[4]=b.x;g[8]= +c.x;g[1]=a.y;g[5]=b.y;g[9]=c.y;g[2]=a.z;g[6]=b.z;g[10]=c.z;return this}}(),multiply:function(a,b){return void 0!==b?(console.warn("THREE.Matrix4: .multiply() now only accepts one argument. Use .multiplyMatrices( a, b ) instead."),this.multiplyMatrices(a,b)):this.multiplyMatrices(this,a)},premultiply:function(a){return this.multiplyMatrices(a,this)},multiplyMatrices:function(a,b){var c=a.elements,d=b.elements;b=this.elements;a=c[0];var e=c[4],f=c[8],g=c[12],h=c[1],k=c[5],l=c[9],q=c[13],n=c[2],m=c[6], +r=c[10],p=c[14],t=c[3],w=c[7],x=c[11],c=c[15],A=d[0],I=d[4],C=d[8],J=d[12],y=d[1],z=d[5],D=d[9],B=d[13],E=d[2],H=d[6],M=d[10],L=d[14],K=d[3],N=d[7],U=d[11],d=d[15];b[0]=a*A+e*y+f*E+g*K;b[4]=a*I+e*z+f*H+g*N;b[8]=a*C+e*D+f*M+g*U;b[12]=a*J+e*B+f*L+g*d;b[1]=h*A+k*y+l*E+q*K;b[5]=h*I+k*z+l*H+q*N;b[9]=h*C+k*D+l*M+q*U;b[13]=h*J+k*B+l*L+q*d;b[2]=n*A+m*y+r*E+p*K;b[6]=n*I+m*z+r*H+p*N;b[10]=n*C+m*D+r*M+p*U;b[14]=n*J+m*B+r*L+p*d;b[3]=t*A+w*y+x*E+c*K;b[7]=t*I+w*z+x*H+c*N;b[11]=t*C+w*D+x*M+c*U;b[15]=t*J+w*B+x*L+ +c*d;return this},multiplyScalar:function(a){var b=this.elements;b[0]*=a;b[4]*=a;b[8]*=a;b[12]*=a;b[1]*=a;b[5]*=a;b[9]*=a;b[13]*=a;b[2]*=a;b[6]*=a;b[10]*=a;b[14]*=a;b[3]*=a;b[7]*=a;b[11]*=a;b[15]*=a;return this},applyToBufferAttribute:function(){var a=new p;return function(b){for(var c=0,d=b.count;cthis.determinant()&&(g=-g);c.x=f[12];c.y=f[13];c.z=f[14];b.copy(this);c=1/g;var f=1/h,l=1/k;b.elements[0]*=c;b.elements[1]*=c;b.elements[2]*=c;b.elements[4]*=f;b.elements[5]*=f;b.elements[6]*=f;b.elements[8]*=l;b.elements[9]*=l;b.elements[10]*=l;d.setFromRotationMatrix(b);e.x=g;e.y=h;e.z=k;return this}}(),makePerspective:function(a,b,c,d,e,f){void 0===f&&console.warn("THREE.Matrix4: .makePerspective() has been redefined and has a new signature. Please check the docs."); +var g=this.elements;g[0]=2*e/(b-a);g[4]=0;g[8]=(b+a)/(b-a);g[12]=0;g[1]=0;g[5]=2*e/(c-d);g[9]=(c+d)/(c-d);g[13]=0;g[2]=0;g[6]=0;g[10]=-(f+e)/(f-e);g[14]=-2*f*e/(f-e);g[3]=0;g[7]=0;g[11]=-1;g[15]=0;return this},makeOrthographic:function(a,b,c,d,e,f){var g=this.elements,h=1/(b-a),k=1/(c-d),l=1/(f-e);g[0]=2*h;g[4]=0;g[8]=0;g[12]=-((b+a)*h);g[1]=0;g[5]=2*k;g[9]=0;g[13]=-((c+d)*k);g[2]=0;g[6]=0;g[10]=-2*l;g[14]=-((f+e)*l);g[3]=0;g[7]=0;g[11]=0;g[15]=1;return this},equals:function(a){var b=this.elements; +a=a.elements;for(var c=0;16>c;c++)if(b[c]!==a[c])return!1;return!0},fromArray:function(a,b){void 0===b&&(b=0);for(var c=0;16>c;c++)this.elements[c]=a[c+b];return this},toArray:function(a,b){void 0===a&&(a=[]);void 0===b&&(b=0);var c=this.elements;a[b]=c[0];a[b+1]=c[1];a[b+2]=c[2];a[b+3]=c[3];a[b+4]=c[4];a[b+5]=c[5];a[b+6]=c[6];a[b+7]=c[7];a[b+8]=c[8];a[b+9]=c[9];a[b+10]=c[10];a[b+11]=c[11];a[b+12]=c[12];a[b+13]=c[13];a[b+14]=c[14];a[b+15]=c[15];return a}});Object.assign(fa,{slerp:function(a,b,c,d){return c.copy(a).slerp(b, +d)},slerpFlat:function(a,b,c,d,e,f,g){var h=c[d+0],k=c[d+1],l=c[d+2];c=c[d+3];d=e[f+0];var q=e[f+1],n=e[f+2];e=e[f+3];if(c!==e||h!==d||k!==q||l!==n){f=1-g;var m=h*d+k*q+l*n+c*e,r=0<=m?1:-1,p=1-m*m;p>Number.EPSILON&&(p=Math.sqrt(p),m=Math.atan2(p,m*r),f=Math.sin(f*m)/p,g=Math.sin(g*m)/p);r*=g;h=h*f+d*r;k=k*f+q*r;l=l*f+n*r;c=c*f+e*r;f===1-g&&(g=1/Math.sqrt(h*h+k*k+l*l+c*c),h*=g,k*=g,l*=g,c*=g)}a[b]=h;a[b+1]=k;a[b+2]=l;a[b+3]=c}});Object.defineProperties(fa.prototype,{x:{get:function(){return this._x}, +set:function(a){this._x=a;this.onChangeCallback()}},y:{get:function(){return this._y},set:function(a){this._y=a;this.onChangeCallback()}},z:{get:function(){return this._z},set:function(a){this._z=a;this.onChangeCallback()}},w:{get:function(){return this._w},set:function(a){this._w=a;this.onChangeCallback()}}});Object.assign(fa.prototype,{set:function(a,b,c,d){this._x=a;this._y=b;this._z=c;this._w=d;this.onChangeCallback();return this},clone:function(){return new this.constructor(this._x,this._y,this._z, +this._w)},copy:function(a){this._x=a.x;this._y=a.y;this._z=a.z;this._w=a.w;this.onChangeCallback();return this},setFromEuler:function(a,b){if(!a||!a.isEuler)throw Error("THREE.Quaternion: .setFromEuler() now expects an Euler rotation rather than a Vector3 and order.");var c=a._x,d=a._y,e=a._z;a=a.order;var f=Math.cos,g=Math.sin,h=f(c/2),k=f(d/2),f=f(e/2),c=g(c/2),d=g(d/2),e=g(e/2);"XYZ"===a?(this._x=c*k*f+h*d*e,this._y=h*d*f-c*k*e,this._z=h*k*e+c*d*f,this._w=h*k*f-c*d*e):"YXZ"===a?(this._x=c*k*f+ +h*d*e,this._y=h*d*f-c*k*e,this._z=h*k*e-c*d*f,this._w=h*k*f+c*d*e):"ZXY"===a?(this._x=c*k*f-h*d*e,this._y=h*d*f+c*k*e,this._z=h*k*e+c*d*f,this._w=h*k*f-c*d*e):"ZYX"===a?(this._x=c*k*f-h*d*e,this._y=h*d*f+c*k*e,this._z=h*k*e-c*d*f,this._w=h*k*f+c*d*e):"YZX"===a?(this._x=c*k*f+h*d*e,this._y=h*d*f+c*k*e,this._z=h*k*e-c*d*f,this._w=h*k*f-c*d*e):"XZY"===a&&(this._x=c*k*f-h*d*e,this._y=h*d*f-c*k*e,this._z=h*k*e+c*d*f,this._w=h*k*f+c*d*e);if(!1!==b)this.onChangeCallback();return this},setFromAxisAngle:function(a, +b){b/=2;var c=Math.sin(b);this._x=a.x*c;this._y=a.y*c;this._z=a.z*c;this._w=Math.cos(b);this.onChangeCallback();return this},setFromRotationMatrix:function(a){var b=a.elements,c=b[0];a=b[4];var d=b[8],e=b[1],f=b[5],g=b[9],h=b[2],k=b[6],b=b[10],l=c+f+b;0f&&c>b?(c=2*Math.sqrt(1+c-f-b),this._w=(k-g)/c,this._x=.25*c,this._y=(a+e)/c,this._z=(d+h)/c):f>b?(c=2*Math.sqrt(1+f-c-b),this._w=(d-h)/c,this._x=(a+e)/c,this._y= .25*c,this._z=(g+k)/c):(c=2*Math.sqrt(1+b-c-f),this._w=(e-a)/c,this._x=(d+h)/c,this._y=(g+k)/c,this._z=.25*c);this.onChangeCallback();return this},setFromUnitVectors:function(){var a=new p,b;return function(c,d){void 0===a&&(a=new p);b=c.dot(d)+1;1E-6>b?(b=0,Math.abs(c.x)>Math.abs(c.z)?a.set(-c.y,c.x,0):a.set(0,-c.z,c.y)):a.crossVectors(c,d);this._x=a.x;this._y=a.y;this._z=a.z;this._w=b;return this.normalize()}}(),inverse:function(){return this.conjugate().normalize()},conjugate:function(){this._x*= -1;this._y*=-1;this._z*=-1;this.onChangeCallback();return this},dot:function(a){return this._x*a._x+this._y*a._y+this._z*a._z+this._w*a._w},lengthSq:function(){return this._x*this._x+this._y*this._y+this._z*this._z+this._w*this._w},length:function(){return Math.sqrt(this._x*this._x+this._y*this._y+this._z*this._z+this._w*this._w)},normalize:function(){var a=this.length();0===a?(this._z=this._y=this._x=0,this._w=1):(a=1/a,this._x*=a,this._y*=a,this._z*=a,this._w*=a);this.onChangeCallback();return this}, -multiply:function(a,b){return void 0!==b?(console.warn("THREE.Quaternion: .multiply() now only accepts one argument. Use .multiplyQuaternions( a, b ) instead."),this.multiplyQuaternions(a,b)):this.multiplyQuaternions(this,a)},premultiply:function(a){return this.multiplyQuaternions(a,this)},multiplyQuaternions:function(a,b){var c=a._x,d=a._y,e=a._z,f=a._w,g=b._x,h=b._y,k=b._z,m=b._w;this._x=c*m+f*g+d*k-e*h;this._y=d*m+f*h+e*g-c*k;this._z=e*m+f*k+c*h-d*g;this._w=f*m-c*g-d*h-e*k;this.onChangeCallback(); -return this},slerp:function(a,b){if(0===b)return this;if(1===b)return this.copy(a);var c=this._x,d=this._y,e=this._z,f=this._w,g=f*a._w+c*a._x+d*a._y+e*a._z;0>g?(this._w=-a._w,this._x=-a._x,this._y=-a._y,this._z=-a._z,g=-g):this.copy(a);if(1<=g)return this._w=f,this._x=c,this._y=d,this._z=e,this;var h=Math.sqrt(1-g*g);if(.001>Math.abs(h))return this._w=.5*(f+this._w),this._x=.5*(c+this._x),this._y=.5*(d+this._y),this._z=.5*(e+this._z),this;var k=Math.atan2(h,g),g=Math.sin((1-b)*k)/h,h=Math.sin(b* -k)/h;this._w=f*g+this._w*h;this._x=c*g+this._x*h;this._y=d*g+this._y*h;this._z=e*g+this._z*h;this.onChangeCallback();return this},equals:function(a){return a._x===this._x&&a._y===this._y&&a._z===this._z&&a._w===this._w},fromArray:function(a,b){void 0===b&&(b=0);this._x=a[b];this._y=a[b+1];this._z=a[b+2];this._w=a[b+3];this.onChangeCallback();return this},toArray:function(a,b){void 0===a&&(a=[]);void 0===b&&(b=0);a[b]=this._x;a[b+1]=this._y;a[b+2]=this._z;a[b+3]=this._w;return a},onChange:function(a){this.onChangeCallback= +multiply:function(a,b){return void 0!==b?(console.warn("THREE.Quaternion: .multiply() now only accepts one argument. Use .multiplyQuaternions( a, b ) instead."),this.multiplyQuaternions(a,b)):this.multiplyQuaternions(this,a)},premultiply:function(a){return this.multiplyQuaternions(a,this)},multiplyQuaternions:function(a,b){var c=a._x,d=a._y,e=a._z;a=a._w;var f=b._x,g=b._y,h=b._z;b=b._w;this._x=c*b+a*f+d*h-e*g;this._y=d*b+a*g+e*f-c*h;this._z=e*b+a*h+c*g-d*f;this._w=a*b-c*f-d*g-e*h;this.onChangeCallback(); +return this},slerp:function(a,b){if(0===b)return this;if(1===b)return this.copy(a);var c=this._x,d=this._y,e=this._z,f=this._w,g=f*a._w+c*a._x+d*a._y+e*a._z;0>g?(this._w=-a._w,this._x=-a._x,this._y=-a._y,this._z=-a._z,g=-g):this.copy(a);if(1<=g)return this._w=f,this._x=c,this._y=d,this._z=e,this;a=Math.sqrt(1-g*g);if(.001>Math.abs(a))return this._w=.5*(f+this._w),this._x=.5*(c+this._x),this._y=.5*(d+this._y),this._z=.5*(e+this._z),this;var h=Math.atan2(a,g),g=Math.sin((1-b)*h)/a;b=Math.sin(b*h)/a; +this._w=f*g+this._w*b;this._x=c*g+this._x*b;this._y=d*g+this._y*b;this._z=e*g+this._z*b;this.onChangeCallback();return this},equals:function(a){return a._x===this._x&&a._y===this._y&&a._z===this._z&&a._w===this._w},fromArray:function(a,b){void 0===b&&(b=0);this._x=a[b];this._y=a[b+1];this._z=a[b+2];this._w=a[b+3];this.onChangeCallback();return this},toArray:function(a,b){void 0===a&&(a=[]);void 0===b&&(b=0);a[b]=this._x;a[b+1]=this._y;a[b+2]=this._z;a[b+3]=this._w;return a},onChange:function(a){this.onChangeCallback= a;return this},onChangeCallback:function(){}});Object.assign(p.prototype,{isVector3:!0,set:function(a,b,c){this.x=a;this.y=b;this.z=c;return this},setScalar:function(a){this.z=this.y=this.x=a;return this},setX:function(a){this.x=a;return this},setY:function(a){this.y=a;return this},setZ:function(a){this.z=a;return this},setComponent:function(a,b){switch(a){case 0:this.x=b;break;case 1:this.y=b;break;case 2:this.z=b;break;default:throw Error("index is out of range: "+a);}return this},getComponent:function(a){switch(a){case 0:return this.x; case 1:return this.y;case 2:return this.z;default:throw Error("index is out of range: "+a);}},clone:function(){return new this.constructor(this.x,this.y,this.z)},copy:function(a){this.x=a.x;this.y=a.y;this.z=a.z;return this},add:function(a,b){if(void 0!==b)return console.warn("THREE.Vector3: .add() now only accepts one argument. Use .addVectors( a, b ) instead."),this.addVectors(a,b);this.x+=a.x;this.y+=a.y;this.z+=a.z;return this},addScalar:function(a){this.x+=a;this.y+=a;this.z+=a;return this}, addVectors:function(a,b){this.x=a.x+b.x;this.y=a.y+b.y;this.z=a.z+b.z;return this},addScaledVector:function(a,b){this.x+=a.x*b;this.y+=a.y*b;this.z+=a.z*b;return this},sub:function(a,b){if(void 0!==b)return console.warn("THREE.Vector3: .sub() now only accepts one argument. Use .subVectors( a, b ) instead."),this.subVectors(a,b);this.x-=a.x;this.y-=a.y;this.z-=a.z;return this},subScalar:function(a){this.x-=a;this.y-=a;this.z-=a;return this},subVectors:function(a,b){this.x=a.x-b.x;this.y=a.y-b.y;this.z= -a.z-b.z;return this},multiply:function(a,b){if(void 0!==b)return console.warn("THREE.Vector3: .multiply() now only accepts one argument. Use .multiplyVectors( a, b ) instead."),this.multiplyVectors(a,b);this.x*=a.x;this.y*=a.y;this.z*=a.z;return this},multiplyScalar:function(a){this.x*=a;this.y*=a;this.z*=a;return this},multiplyVectors:function(a,b){this.x=a.x*b.x;this.y=a.y*b.y;this.z=a.z*b.z;return this},applyEuler:function(){var a=new qa;return function(b){!1===(b&&b.isEuler)&&console.error("THREE.Vector3: .applyEuler() now expects an Euler rotation rather than a Vector3 and order."); -return this.applyQuaternion(a.setFromEuler(b))}}(),applyAxisAngle:function(){var a=new qa;return function(b,c){return this.applyQuaternion(a.setFromAxisAngle(b,c))}}(),applyMatrix3:function(a){var b=this.x,c=this.y,d=this.z;a=a.elements;this.x=a[0]*b+a[3]*c+a[6]*d;this.y=a[1]*b+a[4]*c+a[7]*d;this.z=a[2]*b+a[5]*c+a[8]*d;return this},applyMatrix4:function(a){var b=this.x,c=this.y,d=this.z;a=a.elements;this.x=a[0]*b+a[4]*c+a[8]*d+a[12];this.y=a[1]*b+a[5]*c+a[9]*d+a[13];this.z=a[2]*b+a[6]*c+a[10]*d+a[14]; -return this.divideScalar(a[3]*b+a[7]*c+a[11]*d+a[15])},applyQuaternion:function(a){var b=this.x,c=this.y,d=this.z,e=a.x,f=a.y,g=a.z;a=a.w;var h=a*b+f*d-g*c,k=a*c+g*b-e*d,m=a*d+e*c-f*b,b=-e*b-f*c-g*d;this.x=h*a+b*-e+k*-g-m*-f;this.y=k*a+b*-f+m*-e-h*-g;this.z=m*a+b*-g+h*-f-k*-e;return this},project:function(){var a=new J;return function(b){a.multiplyMatrices(b.projectionMatrix,a.getInverse(b.matrixWorld));return this.applyMatrix4(a)}}(),unproject:function(){var a=new J;return function(b){a.multiplyMatrices(b.matrixWorld, +a.z-b.z;return this},multiply:function(a,b){if(void 0!==b)return console.warn("THREE.Vector3: .multiply() now only accepts one argument. Use .multiplyVectors( a, b ) instead."),this.multiplyVectors(a,b);this.x*=a.x;this.y*=a.y;this.z*=a.z;return this},multiplyScalar:function(a){this.x*=a;this.y*=a;this.z*=a;return this},multiplyVectors:function(a,b){this.x=a.x*b.x;this.y=a.y*b.y;this.z=a.z*b.z;return this},applyEuler:function(){var a=new fa;return function(b){b&&b.isEuler||console.error("THREE.Vector3: .applyEuler() now expects an Euler rotation rather than a Vector3 and order."); +return this.applyQuaternion(a.setFromEuler(b))}}(),applyAxisAngle:function(){var a=new fa;return function(b,c){return this.applyQuaternion(a.setFromAxisAngle(b,c))}}(),applyMatrix3:function(a){var b=this.x,c=this.y,d=this.z;a=a.elements;this.x=a[0]*b+a[3]*c+a[6]*d;this.y=a[1]*b+a[4]*c+a[7]*d;this.z=a[2]*b+a[5]*c+a[8]*d;return this},applyMatrix4:function(a){var b=this.x,c=this.y,d=this.z;a=a.elements;var e=1/(a[3]*b+a[7]*c+a[11]*d+a[15]);this.x=(a[0]*b+a[4]*c+a[8]*d+a[12])*e;this.y=(a[1]*b+a[5]*c+ +a[9]*d+a[13])*e;this.z=(a[2]*b+a[6]*c+a[10]*d+a[14])*e;return this},applyQuaternion:function(a){var b=this.x,c=this.y,d=this.z,e=a.x,f=a.y,g=a.z;a=a.w;var h=a*b+f*d-g*c,k=a*c+g*b-e*d,l=a*d+e*c-f*b,b=-e*b-f*c-g*d;this.x=h*a+b*-e+k*-g-l*-f;this.y=k*a+b*-f+l*-e-h*-g;this.z=l*a+b*-g+h*-f-k*-e;return this},project:function(){var a=new K;return function(b){a.multiplyMatrices(b.projectionMatrix,a.getInverse(b.matrixWorld));return this.applyMatrix4(a)}}(),unproject:function(){var a=new K;return function(b){a.multiplyMatrices(b.matrixWorld, a.getInverse(b.projectionMatrix));return this.applyMatrix4(a)}}(),transformDirection:function(a){var b=this.x,c=this.y,d=this.z;a=a.elements;this.x=a[0]*b+a[4]*c+a[8]*d;this.y=a[1]*b+a[5]*c+a[9]*d;this.z=a[2]*b+a[6]*c+a[10]*d;return this.normalize()},divide:function(a){this.x/=a.x;this.y/=a.y;this.z/=a.z;return this},divideScalar:function(a){return this.multiplyScalar(1/a)},min:function(a){this.x=Math.min(this.x,a.x);this.y=Math.min(this.y,a.y);this.z=Math.min(this.z,a.z);return this},max:function(a){this.x= -Math.max(this.x,a.x);this.y=Math.max(this.y,a.y);this.z=Math.max(this.z,a.z);return this},clamp:function(a,b){this.x=Math.max(a.x,Math.min(b.x,this.x));this.y=Math.max(a.y,Math.min(b.y,this.y));this.z=Math.max(a.z,Math.min(b.z,this.z));return this},clampScalar:function(){var a=new p,b=new p;return function(c,d){a.set(c,c,c);b.set(d,d,d);return this.clamp(a,b)}}(),clampLength:function(a,b){var c=this.length();return this.multiplyScalar(Math.max(a,Math.min(b,c))/c)},floor:function(){this.x=Math.floor(this.x); -this.y=Math.floor(this.y);this.z=Math.floor(this.z);return this},ceil:function(){this.x=Math.ceil(this.x);this.y=Math.ceil(this.y);this.z=Math.ceil(this.z);return this},round:function(){this.x=Math.round(this.x);this.y=Math.round(this.y);this.z=Math.round(this.z);return this},roundToZero:function(){this.x=0>this.x?Math.ceil(this.x):Math.floor(this.x);this.y=0>this.y?Math.ceil(this.y):Math.floor(this.y);this.z=0>this.z?Math.ceil(this.z):Math.floor(this.z);return this},negate:function(){this.x=-this.x; -this.y=-this.y;this.z=-this.z;return this},dot:function(a){return this.x*a.x+this.y*a.y+this.z*a.z},lengthSq:function(){return this.x*this.x+this.y*this.y+this.z*this.z},length:function(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z)},lengthManhattan:function(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)},normalize:function(){return this.divideScalar(this.length())},setLength:function(a){return this.multiplyScalar(a/this.length())},lerp:function(a,b){this.x+=(a.x-this.x)* -b;this.y+=(a.y-this.y)*b;this.z+=(a.z-this.z)*b;return this},lerpVectors:function(a,b,c){return this.subVectors(b,a).multiplyScalar(c).add(a)},cross:function(a,b){if(void 0!==b)return console.warn("THREE.Vector3: .cross() now only accepts one argument. Use .crossVectors( a, b ) instead."),this.crossVectors(a,b);var c=this.x,d=this.y,e=this.z;this.x=d*a.z-e*a.y;this.y=e*a.x-c*a.z;this.z=c*a.y-d*a.x;return this},crossVectors:function(a,b){var c=a.x,d=a.y,e=a.z,f=b.x,g=b.y,h=b.z;this.x=d*h-e*g;this.y= -e*f-c*h;this.z=c*g-d*f;return this},projectOnVector:function(a){var b=a.dot(this)/a.lengthSq();return this.copy(a).multiplyScalar(b)},projectOnPlane:function(){var a=new p;return function(b){a.copy(this).projectOnVector(b);return this.sub(a)}}(),reflect:function(){var a=new p;return function(b){return this.sub(a.copy(b).multiplyScalar(2*this.dot(b)))}}(),angleTo:function(a){a=this.dot(a)/Math.sqrt(this.lengthSq()*a.lengthSq());return Math.acos(Y.clamp(a,-1,1))},distanceTo:function(a){return Math.sqrt(this.distanceToSquared(a))}, -distanceToSquared:function(a){var b=this.x-a.x,c=this.y-a.y;a=this.z-a.z;return b*b+c*c+a*a},distanceToManhattan:function(a){return Math.abs(this.x-a.x)+Math.abs(this.y-a.y)+Math.abs(this.z-a.z)},setFromSpherical:function(a){var b=Math.sin(a.phi)*a.radius;this.x=b*Math.sin(a.theta);this.y=Math.cos(a.phi)*a.radius;this.z=b*Math.cos(a.theta);return this},setFromCylindrical:function(a){this.x=a.radius*Math.sin(a.theta);this.y=a.y;this.z=a.radius*Math.cos(a.theta);return this},setFromMatrixPosition:function(a){return this.setFromMatrixColumn(a, -3)},setFromMatrixScale:function(a){var b=this.setFromMatrixColumn(a,0).length(),c=this.setFromMatrixColumn(a,1).length();a=this.setFromMatrixColumn(a,2).length();this.x=b;this.y=c;this.z=a;return this},setFromMatrixColumn:function(a,b){return this.fromArray(a.elements,4*b)},equals:function(a){return a.x===this.x&&a.y===this.y&&a.z===this.z},fromArray:function(a,b){void 0===b&&(b=0);this.x=a[b];this.y=a[b+1];this.z=a[b+2];return this},toArray:function(a,b){void 0===a&&(a=[]);void 0===b&&(b=0);a[b]= -this.x;a[b+1]=this.y;a[b+2]=this.z;return a},fromBufferAttribute:function(a,b,c){void 0!==c&&console.warn("THREE.Vector3: offset has been removed from .fromBufferAttribute().");this.x=a.getX(b);this.y=a.getY(b);this.z=a.getZ(b);return this}});Object.assign(J.prototype,{isMatrix4:!0,set:function(a,b,c,d,e,f,g,h,k,m,u,l,n,t,p,r){var x=this.elements;x[0]=a;x[4]=b;x[8]=c;x[12]=d;x[1]=e;x[5]=f;x[9]=g;x[13]=h;x[2]=k;x[6]=m;x[10]=u;x[14]=l;x[3]=n;x[7]=t;x[11]=p;x[15]=r;return this},identity:function(){this.set(1, -0,0,0,0,1,0,0,0,0,1,0,0,0,0,1);return this},clone:function(){return(new J).fromArray(this.elements)},copy:function(a){var b=this.elements;a=a.elements;b[0]=a[0];b[1]=a[1];b[2]=a[2];b[3]=a[3];b[4]=a[4];b[5]=a[5];b[6]=a[6];b[7]=a[7];b[8]=a[8];b[9]=a[9];b[10]=a[10];b[11]=a[11];b[12]=a[12];b[13]=a[13];b[14]=a[14];b[15]=a[15];return this},copyPosition:function(a){var b=this.elements;a=a.elements;b[12]=a[12];b[13]=a[13];b[14]=a[14];return this},extractBasis:function(a,b,c){a.setFromMatrixColumn(this,0); -b.setFromMatrixColumn(this,1);c.setFromMatrixColumn(this,2);return this},makeBasis:function(a,b,c){this.set(a.x,b.x,c.x,0,a.y,b.y,c.y,0,a.z,b.z,c.z,0,0,0,0,1);return this},extractRotation:function(){var a=new p;return function(b){var c=this.elements,d=b.elements,e=1/a.setFromMatrixColumn(b,0).length(),f=1/a.setFromMatrixColumn(b,1).length();b=1/a.setFromMatrixColumn(b,2).length();c[0]=d[0]*e;c[1]=d[1]*e;c[2]=d[2]*e;c[4]=d[4]*f;c[5]=d[5]*f;c[6]=d[6]*f;c[8]=d[8]*b;c[9]=d[9]*b;c[10]=d[10]*b;return this}}(), -makeRotationFromEuler:function(a){!1===(a&&a.isEuler)&&console.error("THREE.Matrix: .makeRotationFromEuler() now expects a Euler rotation rather than a Vector3 and order.");var b=this.elements,c=a.x,d=a.y,e=a.z,f=Math.cos(c),c=Math.sin(c),g=Math.cos(d),d=Math.sin(d),h=Math.cos(e),e=Math.sin(e);if("XYZ"===a.order){a=f*h;var k=f*e,m=c*h,u=c*e;b[0]=g*h;b[4]=-g*e;b[8]=d;b[1]=k+m*d;b[5]=a-u*d;b[9]=-c*g;b[2]=u-a*d;b[6]=m+k*d;b[10]=f*g}else"YXZ"===a.order?(a=g*h,k=g*e,m=d*h,u=d*e,b[0]=a+u*c,b[4]=m*c-k,b[8]= -f*d,b[1]=f*e,b[5]=f*h,b[9]=-c,b[2]=k*c-m,b[6]=u+a*c,b[10]=f*g):"ZXY"===a.order?(a=g*h,k=g*e,m=d*h,u=d*e,b[0]=a-u*c,b[4]=-f*e,b[8]=m+k*c,b[1]=k+m*c,b[5]=f*h,b[9]=u-a*c,b[2]=-f*d,b[6]=c,b[10]=f*g):"ZYX"===a.order?(a=f*h,k=f*e,m=c*h,u=c*e,b[0]=g*h,b[4]=m*d-k,b[8]=a*d+u,b[1]=g*e,b[5]=u*d+a,b[9]=k*d-m,b[2]=-d,b[6]=c*g,b[10]=f*g):"YZX"===a.order?(a=f*g,k=f*d,m=c*g,u=c*d,b[0]=g*h,b[4]=u-a*e,b[8]=m*e+k,b[1]=e,b[5]=f*h,b[9]=-c*h,b[2]=-d*h,b[6]=k*e+m,b[10]=a-u*e):"XZY"===a.order&&(a=f*g,k=f*d,m=c*g,u=c*d,b[0]= -g*h,b[4]=-e,b[8]=d*h,b[1]=a*e+u,b[5]=f*h,b[9]=k*e-m,b[2]=m*e-k,b[6]=c*h,b[10]=u*e+a);b[3]=0;b[7]=0;b[11]=0;b[12]=0;b[13]=0;b[14]=0;b[15]=1;return this},makeRotationFromQuaternion:function(a){var b=this.elements,c=a._x,d=a._y,e=a._z,f=a._w,g=c+c,h=d+d,k=e+e;a=c*g;var m=c*h,c=c*k,u=d*h,d=d*k,e=e*k,g=f*g,h=f*h,f=f*k;b[0]=1-(u+e);b[4]=m-f;b[8]=c+h;b[1]=m+f;b[5]=1-(a+e);b[9]=d-g;b[2]=c-h;b[6]=d+g;b[10]=1-(a+u);b[3]=0;b[7]=0;b[11]=0;b[12]=0;b[13]=0;b[14]=0;b[15]=1;return this},lookAt:function(){var a=new p, -b=new p,c=new p;return function(d,e,f){var g=this.elements;c.subVectors(d,e);0===c.lengthSq()&&(c.z=1);c.normalize();a.crossVectors(f,c);0===a.lengthSq()&&(c.z+=1E-4,a.crossVectors(f,c));a.normalize();b.crossVectors(c,a);g[0]=a.x;g[4]=b.x;g[8]=c.x;g[1]=a.y;g[5]=b.y;g[9]=c.y;g[2]=a.z;g[6]=b.z;g[10]=c.z;return this}}(),multiply:function(a,b){return void 0!==b?(console.warn("THREE.Matrix4: .multiply() now only accepts one argument. Use .multiplyMatrices( a, b ) instead."),this.multiplyMatrices(a,b)): -this.multiplyMatrices(this,a)},premultiply:function(a){return this.multiplyMatrices(a,this)},multiplyMatrices:function(a,b){var c=a.elements,d=b.elements,e=this.elements,f=c[0],g=c[4],h=c[8],k=c[12],m=c[1],u=c[5],l=c[9],n=c[13],t=c[2],p=c[6],r=c[10],x=c[14],y=c[3],v=c[7],F=c[11],c=c[15],w=d[0],S=d[4],W=d[8],C=d[12],G=d[1],D=d[5],O=d[9],E=d[13],B=d[2],I=d[6],H=d[10],J=d[14],Q=d[3],K=d[7],V=d[11],d=d[15];e[0]=f*w+g*G+h*B+k*Q;e[4]=f*S+g*D+h*I+k*K;e[8]=f*W+g*O+h*H+k*V;e[12]=f*C+g*E+h*J+k*d;e[1]=m*w+u* -G+l*B+n*Q;e[5]=m*S+u*D+l*I+n*K;e[9]=m*W+u*O+l*H+n*V;e[13]=m*C+u*E+l*J+n*d;e[2]=t*w+p*G+r*B+x*Q;e[6]=t*S+p*D+r*I+x*K;e[10]=t*W+p*O+r*H+x*V;e[14]=t*C+p*E+r*J+x*d;e[3]=y*w+v*G+F*B+c*Q;e[7]=y*S+v*D+F*I+c*K;e[11]=y*W+v*O+F*H+c*V;e[15]=y*C+v*E+F*J+c*d;return this},multiplyScalar:function(a){var b=this.elements;b[0]*=a;b[4]*=a;b[8]*=a;b[12]*=a;b[1]*=a;b[5]*=a;b[9]*=a;b[13]*=a;b[2]*=a;b[6]*=a;b[10]*=a;b[14]*=a;b[3]*=a;b[7]*=a;b[11]*=a;b[15]*=a;return this},applyToBufferAttribute:function(){var a=new p;return function(b){for(var c= -0,d=b.count;cthis.determinant()&&(g=-g);c.x=f[12];c.y=f[13];c.z=f[14];b.copy(this);c=1/g;var f=1/h,m=1/k;b.elements[0]*=c;b.elements[1]*=c;b.elements[2]*=c;b.elements[4]*=f;b.elements[5]*=f;b.elements[6]*=f;b.elements[8]*= -m;b.elements[9]*=m;b.elements[10]*=m;d.setFromRotationMatrix(b);e.x=g;e.y=h;e.z=k;return this}}(),makePerspective:function(a,b,c,d,e,f){void 0===f&&console.warn("THREE.Matrix4: .makePerspective() has been redefined and has a new signature. Please check the docs.");var g=this.elements;g[0]=2*e/(b-a);g[4]=0;g[8]=(b+a)/(b-a);g[12]=0;g[1]=0;g[5]=2*e/(c-d);g[9]=(c+d)/(c-d);g[13]=0;g[2]=0;g[6]=0;g[10]=-(f+e)/(f-e);g[14]=-2*f*e/(f-e);g[3]=0;g[7]=0;g[11]=-1;g[15]=0;return this},makeOrthographic:function(a, -b,c,d,e,f){var g=this.elements,h=1/(b-a),k=1/(c-d),m=1/(f-e);g[0]=2*h;g[4]=0;g[8]=0;g[12]=-((b+a)*h);g[1]=0;g[5]=2*k;g[9]=0;g[13]=-((c+d)*k);g[2]=0;g[6]=0;g[10]=-2*m;g[14]=-((f+e)*m);g[3]=0;g[7]=0;g[11]=0;g[15]=1;return this},equals:function(a){var b=this.elements;a=a.elements;for(var c=0;16>c;c++)if(b[c]!==a[c])return!1;return!0},fromArray:function(a,b){void 0===b&&(b=0);for(var c=0;16>c;c++)this.elements[c]=a[c+b];return this},toArray:function(a,b){void 0===a&&(a=[]);void 0===b&&(b=0);var c=this.elements; -a[b]=c[0];a[b+1]=c[1];a[b+2]=c[2];a[b+3]=c[3];a[b+4]=c[4];a[b+5]=c[5];a[b+6]=c[6];a[b+7]=c[7];a[b+8]=c[8];a[b+9]=c[9];a[b+10]=c[10];a[b+11]=c[11];a[b+12]=c[12];a[b+13]=c[13];a[b+14]=c[14];a[b+15]=c[15];return a}});eb.prototype=Object.create(X.prototype);eb.prototype.constructor=eb;eb.prototype.isDataTexture=!0;Za.prototype=Object.create(X.prototype);Za.prototype.constructor=Za;Za.prototype.isCubeTexture=!0;Object.defineProperty(Za.prototype,"images",{get:function(){return this.image},set:function(a){this.image= -a}});var De=new X,Ee=new Za,ye=[],Ae=[],Ce=new Float32Array(16),Be=new Float32Array(9);Ie.prototype.setValue=function(a,b){for(var c=this.seq,d=0,e=c.length;d!==e;++d){var f=c[d];f.setValue(a,b[f.id])}};var Qd=/([\w\d_]+)(\])?(\[|\.)?/g;fb.prototype.setValue=function(a,b,c){b=this.map[b];void 0!==b&&b.setValue(a,c,this.renderer)};fb.prototype.setOptional=function(a,b,c){b=b[c];void 0!==b&&this.setValue(a,c,b)};fb.upload=function(a,b,c,d){for(var e=0,f=b.length;e!==f;++e){var g=b[e],h=c[g.id];!1!== -h.needsUpdate&&g.setValue(a,h.value,d)}};fb.seqWithValue=function(a,b){for(var c=[],d=0,e=a.length;d!==e;++d){var f=a[d];f.id in b&&c.push(f)}return c};var kg={aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535, -darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842, -fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762, -lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685, -navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331, -slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074};Object.assign(H.prototype,{isColor:!0,r:1,g:1,b:1,set:function(a){a&&a.isColor?this.copy(a):"number"===typeof a?this.setHex(a):"string"===typeof a&&this.setStyle(a);return this},setScalar:function(a){this.b=this.g=this.r= -a;return this},setHex:function(a){a=Math.floor(a);this.r=(a>>16&255)/255;this.g=(a>>8&255)/255;this.b=(a&255)/255;return this},setRGB:function(a,b,c){this.r=a;this.g=b;this.b=c;return this},setHSL:function(){function a(a,c,d){0>d&&(d+=1);1d?c:d<2/3?a+6*(c-a)*(2/3-d):a}return function(b,c,d){b=Y.euclideanModulo(b,1);c=Y.clamp(c,0,1);d=Y.clamp(d,0,1);0===c?this.r=this.g=this.b=d:(c=.5>=d?d*(1+c):d+c-d*c,d=2*d-c,this.r=a(d,c,b+1/3),this.g=a(d,c,b),this.b=a(d,c,b-1/ -3));return this}}(),setStyle:function(a){function b(b){void 0!==b&&1>parseFloat(b)&&console.warn("THREE.Color: Alpha component of "+a+" will be ignored.")}var c;if(c=/^((?:rgb|hsl)a?)\(\s*([^\)]*)\)/.exec(a)){var d=c[2];switch(c[1]){case "rgb":case "rgba":if(c=/^(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec(d))return this.r=Math.min(255,parseInt(c[1],10))/255,this.g=Math.min(255,parseInt(c[2],10))/255,this.b=Math.min(255,parseInt(c[3],10))/255,b(c[5]),this;if(c=/^(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec(d))return this.r= -Math.min(100,parseInt(c[1],10))/100,this.g=Math.min(100,parseInt(c[2],10))/100,this.b=Math.min(100,parseInt(c[3],10))/100,b(c[5]),this;break;case "hsl":case "hsla":if(c=/^([0-9]*\.?[0-9]+)\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec(d)){var d=parseFloat(c[1])/360,e=parseInt(c[2],10)/100,f=parseInt(c[3],10)/100;b(c[5]);return this.setHSL(d,e,f)}}}else if(c=/^\#([A-Fa-f0-9]+)$/.exec(a)){c=c[1];d=c.length;if(3===d)return this.r=parseInt(c.charAt(0)+c.charAt(0),16)/255,this.g=parseInt(c.charAt(1)+ -c.charAt(1),16)/255,this.b=parseInt(c.charAt(2)+c.charAt(2),16)/255,this;if(6===d)return this.r=parseInt(c.charAt(0)+c.charAt(1),16)/255,this.g=parseInt(c.charAt(2)+c.charAt(3),16)/255,this.b=parseInt(c.charAt(4)+c.charAt(5),16)/255,this}a&&0=h?k/(e+f):k/(2-e-f);switch(e){case b:g=(c-d)/k+(cthis.x?Math.ceil(this.x):Math.floor(this.x);this.y=0>this.y?Math.ceil(this.y):Math.floor(this.y);this.z=0>this.z?Math.ceil(this.z):Math.floor(this.z);return this},negate:function(){this.x= +-this.x;this.y=-this.y;this.z=-this.z;return this},dot:function(a){return this.x*a.x+this.y*a.y+this.z*a.z},lengthSq:function(){return this.x*this.x+this.y*this.y+this.z*this.z},length:function(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z)},lengthManhattan:function(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)},normalize:function(){return this.divideScalar(this.length()||1)},setLength:function(a){return this.normalize().multiplyScalar(a)},lerp:function(a,b){this.x+=(a.x- +this.x)*b;this.y+=(a.y-this.y)*b;this.z+=(a.z-this.z)*b;return this},lerpVectors:function(a,b,c){return this.subVectors(b,a).multiplyScalar(c).add(a)},cross:function(a,b){if(void 0!==b)return console.warn("THREE.Vector3: .cross() now only accepts one argument. Use .crossVectors( a, b ) instead."),this.crossVectors(a,b);b=this.x;var c=this.y,d=this.z;this.x=c*a.z-d*a.y;this.y=d*a.x-b*a.z;this.z=b*a.y-c*a.x;return this},crossVectors:function(a,b){var c=a.x,d=a.y;a=a.z;var e=b.x,f=b.y;b=b.z;this.x=d* +b-a*f;this.y=a*e-c*b;this.z=c*f-d*e;return this},projectOnVector:function(a){var b=a.dot(this)/a.lengthSq();return this.copy(a).multiplyScalar(b)},projectOnPlane:function(){var a=new p;return function(b){a.copy(this).projectOnVector(b);return this.sub(a)}}(),reflect:function(){var a=new p;return function(b){return this.sub(a.copy(b).multiplyScalar(2*this.dot(b)))}}(),angleTo:function(a){a=this.dot(a)/Math.sqrt(this.lengthSq()*a.lengthSq());return Math.acos(R.clamp(a,-1,1))},distanceTo:function(a){return Math.sqrt(this.distanceToSquared(a))}, +distanceToSquared:function(a){var b=this.x-a.x,c=this.y-a.y;a=this.z-a.z;return b*b+c*c+a*a},distanceToManhattan:function(a){return Math.abs(this.x-a.x)+Math.abs(this.y-a.y)+Math.abs(this.z-a.z)},setFromSpherical:function(a){var b=Math.sin(a.phi)*a.radius;this.x=b*Math.sin(a.theta);this.y=Math.cos(a.phi)*a.radius;this.z=b*Math.cos(a.theta);return this},setFromCylindrical:function(a){this.x=a.radius*Math.sin(a.theta);this.y=a.y;this.z=a.radius*Math.cos(a.theta);return this},setFromMatrixPosition:function(a){a= +a.elements;this.x=a[12];this.y=a[13];this.z=a[14];return this},setFromMatrixScale:function(a){var b=this.setFromMatrixColumn(a,0).length(),c=this.setFromMatrixColumn(a,1).length();a=this.setFromMatrixColumn(a,2).length();this.x=b;this.y=c;this.z=a;return this},setFromMatrixColumn:function(a,b){return this.fromArray(a.elements,4*b)},equals:function(a){return a.x===this.x&&a.y===this.y&&a.z===this.z},fromArray:function(a,b){void 0===b&&(b=0);this.x=a[b];this.y=a[b+1];this.z=a[b+2];return this},toArray:function(a, +b){void 0===a&&(a=[]);void 0===b&&(b=0);a[b]=this.x;a[b+1]=this.y;a[b+2]=this.z;return a},fromBufferAttribute:function(a,b,c){void 0!==c&&console.warn("THREE.Vector3: offset has been removed from .fromBufferAttribute().");this.x=a.getX(b);this.y=a.getY(b);this.z=a.getZ(b);return this}});Object.assign(qa.prototype,{isMatrix3:!0,set:function(a,b,c,d,e,f,g,h,k){var l=this.elements;l[0]=a;l[1]=d;l[2]=g;l[3]=b;l[4]=e;l[5]=h;l[6]=c;l[7]=f;l[8]=k;return this},identity:function(){this.set(1,0,0,0,1,0,0,0, +1);return this},clone:function(){return(new this.constructor).fromArray(this.elements)},copy:function(a){var b=this.elements;a=a.elements;b[0]=a[0];b[1]=a[1];b[2]=a[2];b[3]=a[3];b[4]=a[4];b[5]=a[5];b[6]=a[6];b[7]=a[7];b[8]=a[8];return this},setFromMatrix4:function(a){a=a.elements;this.set(a[0],a[4],a[8],a[1],a[5],a[9],a[2],a[6],a[10]);return this},applyToBufferAttribute:function(){var a=new p;return function(b){for(var c=0,d=b.count;cc;c++)if(b[c]!==a[c])return!1;return!0},fromArray:function(a, +b){void 0===b&&(b=0);for(var c=0;9>c;c++)this.elements[c]=a[c+b];return this},toArray:function(a,b){void 0===a&&(a=[]);void 0===b&&(b=0);var c=this.elements;a[b]=c[0];a[b+1]=c[1];a[b+2]=c[2];a[b+3]=c[3];a[b+4]=c[4];a[b+5]=c[5];a[b+6]=c[6];a[b+7]=c[7];a[b+8]=c[8];return a}});var kf=0;O.DEFAULT_IMAGE=void 0;O.DEFAULT_MAPPING=300;Object.defineProperty(O.prototype,"needsUpdate",{set:function(a){!0===a&&this.version++}});Object.assign(O.prototype,sa.prototype,{constructor:O,isTexture:!0,clone:function(){return(new this.constructor).copy(this)}, +copy:function(a){this.name=a.name;this.image=a.image;this.mipmaps=a.mipmaps.slice(0);this.mapping=a.mapping;this.wrapS=a.wrapS;this.wrapT=a.wrapT;this.magFilter=a.magFilter;this.minFilter=a.minFilter;this.anisotropy=a.anisotropy;this.format=a.format;this.type=a.type;this.offset.copy(a.offset);this.repeat.copy(a.repeat);this.rotation=a.rotation;this.matrixAutoUpdate=a.matrixAutoUpdate;this.matrix.copy(a.matrix);this.generateMipmaps=a.generateMipmaps;this.premultiplyAlpha=a.premultiplyAlpha;this.flipY= +a.flipY;this.unpackAlignment=a.unpackAlignment;this.encoding=a.encoding;return this},toJSON:function(a){if(void 0!==a.textures[this.uuid])return a.textures[this.uuid];var b={metadata:{version:4.5,type:"Texture",generator:"Texture.toJSON"},uuid:this.uuid,name:this.name,mapping:this.mapping,repeat:[this.repeat.x,this.repeat.y],offset:[this.offset.x,this.offset.y],rotation:this.rotation,wrap:[this.wrapS,this.wrapT],minFilter:this.minFilter,magFilter:this.magFilter,anisotropy:this.anisotropy,flipY:this.flipY}; +if(void 0!==this.image){var c=this.image;void 0===c.uuid&&(c.uuid=R.generateUUID());if(void 0===a.images[c.uuid]){var d=a.images,e=c.uuid,f=c.uuid;if(c instanceof HTMLCanvasElement)var g=c;else{g=document.createElementNS("http://www.w3.org/1999/xhtml","canvas");g.width=c.width;g.height=c.height;var h=g.getContext("2d");c instanceof ImageData?h.putImageData(c,0,0):h.drawImage(c,0,0,c.width,c.height)}g=2048a.x||1a.x?0:1;break;case 1002:a.x=1===Math.abs(Math.floor(a.x)%2)?Math.ceil(a.x)-a.x:a.x-Math.floor(a.x)}if(0>a.y||1a.y?0:1;break;case 1002:a.y=1===Math.abs(Math.floor(a.y)% +2)?Math.ceil(a.y)-a.y:a.y-Math.floor(a.y)}this.flipY&&(a.y=1-a.y)}}});Object.assign(da.prototype,{isVector4:!0,set:function(a,b,c,d){this.x=a;this.y=b;this.z=c;this.w=d;return this},setScalar:function(a){this.w=this.z=this.y=this.x=a;return this},setX:function(a){this.x=a;return this},setY:function(a){this.y=a;return this},setZ:function(a){this.z=a;return this},setW:function(a){this.w=a;return this},setComponent:function(a,b){switch(a){case 0:this.x=b;break;case 1:this.y=b;break;case 2:this.z=b;break; +case 3:this.w=b;break;default:throw Error("index is out of range: "+a);}return this},getComponent:function(a){switch(a){case 0:return this.x;case 1:return this.y;case 2:return this.z;case 3:return this.w;default:throw Error("index is out of range: "+a);}},clone:function(){return new this.constructor(this.x,this.y,this.z,this.w)},copy:function(a){this.x=a.x;this.y=a.y;this.z=a.z;this.w=void 0!==a.w?a.w:1;return this},add:function(a,b){if(void 0!==b)return console.warn("THREE.Vector4: .add() now only accepts one argument. Use .addVectors( a, b ) instead."), +this.addVectors(a,b);this.x+=a.x;this.y+=a.y;this.z+=a.z;this.w+=a.w;return this},addScalar:function(a){this.x+=a;this.y+=a;this.z+=a;this.w+=a;return this},addVectors:function(a,b){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},addScaledVector:function(a,b){this.x+=a.x*b;this.y+=a.y*b;this.z+=a.z*b;this.w+=a.w*b;return this},sub:function(a,b){if(void 0!==b)return console.warn("THREE.Vector4: .sub() now only accepts one argument. Use .subVectors( a, b ) instead."),this.subVectors(a, +b);this.x-=a.x;this.y-=a.y;this.z-=a.z;this.w-=a.w;return this},subScalar:function(a){this.x-=a;this.y-=a;this.z-=a;this.w-=a;return this},subVectors:function(a,b){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},multiplyScalar:function(a){this.x*=a;this.y*=a;this.z*=a;this.w*=a;return this},applyMatrix4:function(a){var b=this.x,c=this.y,d=this.z,e=this.w;a=a.elements;this.x=a[0]*b+a[4]*c+a[8]*d+a[12]*e;this.y=a[1]*b+a[5]*c+a[9]*d+a[13]*e;this.z=a[2]*b+a[6]*c+a[10]*d+a[14]* +e;this.w=a[3]*b+a[7]*c+a[11]*d+a[15]*e;return this},divideScalar:function(a){return this.multiplyScalar(1/a)},setAxisAngleFromQuaternion:function(a){this.w=2*Math.acos(a.w);var b=Math.sqrt(1-a.w*a.w);1E-4>b?(this.x=1,this.z=this.y=0):(this.x=a.x/b,this.y=a.y/b,this.z=a.z/b);return this},setAxisAngleFromRotationMatrix:function(a){a=a.elements;var b=a[0];var c=a[4];var d=a[8],e=a[1],f=a[5],g=a[9];var h=a[2];var k=a[6];var l=a[10];if(.01>Math.abs(c-e)&&.01>Math.abs(d-h)&&.01>Math.abs(g-k)){if(.1>Math.abs(c+ +e)&&.1>Math.abs(d+h)&&.1>Math.abs(g+k)&&.1>Math.abs(b+f+l-3))return this.set(1,0,0,0),this;a=Math.PI;b=(b+1)/2;f=(f+1)/2;l=(l+1)/2;c=(c+e)/4;d=(d+h)/4;g=(g+k)/4;b>f&&b>l?.01>b?(k=0,c=h=.707106781):(k=Math.sqrt(b),h=c/k,c=d/k):f>l?.01>f?(k=.707106781,h=0,c=.707106781):(h=Math.sqrt(f),k=c/h,c=g/h):.01>l?(h=k=.707106781,c=0):(c=Math.sqrt(l),k=d/c,h=g/c);this.set(k,h,c,a);return this}a=Math.sqrt((k-g)*(k-g)+(d-h)*(d-h)+(e-c)*(e-c));.001>Math.abs(a)&&(a=1);this.x=(k-g)/a;this.y=(d-h)/a;this.z=(e-c)/a; +this.w=Math.acos((b+f+l-1)/2);return this},min:function(a){this.x=Math.min(this.x,a.x);this.y=Math.min(this.y,a.y);this.z=Math.min(this.z,a.z);this.w=Math.min(this.w,a.w);return this},max:function(a){this.x=Math.max(this.x,a.x);this.y=Math.max(this.y,a.y);this.z=Math.max(this.z,a.z);this.w=Math.max(this.w,a.w);return this},clamp:function(a,b){this.x=Math.max(a.x,Math.min(b.x,this.x));this.y=Math.max(a.y,Math.min(b.y,this.y));this.z=Math.max(a.z,Math.min(b.z,this.z));this.w=Math.max(a.w,Math.min(b.w, +this.w));return this},clampScalar:function(){var a,b;return function(c,d){void 0===a&&(a=new da,b=new da);a.set(c,c,c,c);b.set(d,d,d,d);return this.clamp(a,b)}}(),clampLength:function(a,b){var c=this.length();return this.divideScalar(c||1).multiplyScalar(Math.max(a,Math.min(b,c)))},floor:function(){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},ceil:function(){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},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);return this},roundToZero:function(){this.x=0>this.x?Math.ceil(this.x):Math.floor(this.x);this.y=0>this.y?Math.ceil(this.y):Math.floor(this.y);this.z=0>this.z?Math.ceil(this.z):Math.floor(this.z);this.w=0>this.w?Math.ceil(this.w):Math.floor(this.w);return this},negate:function(){this.x=-this.x;this.y=-this.y;this.z=-this.z;this.w=-this.w;return this}, +dot:function(a){return this.x*a.x+this.y*a.y+this.z*a.z+this.w*a.w},lengthSq:function(){return this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w},length:function(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w)},lengthManhattan:function(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)+Math.abs(this.w)},normalize:function(){return this.divideScalar(this.length()||1)},setLength:function(a){return this.normalize().multiplyScalar(a)},lerp:function(a,b){this.x+= +(a.x-this.x)*b;this.y+=(a.y-this.y)*b;this.z+=(a.z-this.z)*b;this.w+=(a.w-this.w)*b;return this},lerpVectors:function(a,b,c){return this.subVectors(b,a).multiplyScalar(c).add(a)},equals:function(a){return a.x===this.x&&a.y===this.y&&a.z===this.z&&a.w===this.w},fromArray:function(a,b){void 0===b&&(b=0);this.x=a[b];this.y=a[b+1];this.z=a[b+2];this.w=a[b+3];return this},toArray:function(a,b){void 0===a&&(a=[]);void 0===b&&(b=0);a[b]=this.x;a[b+1]=this.y;a[b+2]=this.z;a[b+3]=this.w;return a},fromBufferAttribute:function(a, +b,c){void 0!==c&&console.warn("THREE.Vector4: offset has been removed from .fromBufferAttribute().");this.x=a.getX(b);this.y=a.getY(b);this.z=a.getZ(b);this.w=a.getW(b);return this}});Object.assign(Bb.prototype,sa.prototype,{isWebGLRenderTarget:!0,setSize:function(a,b){if(this.width!==a||this.height!==b)this.width=a,this.height=b,this.dispose();this.viewport.set(0,0,a,b);this.scissor.set(0,0,a,b)},clone:function(){return(new this.constructor).copy(this)},copy:function(a){this.width=a.width;this.height= +a.height;this.viewport.copy(a.viewport);this.texture=a.texture.clone();this.depthBuffer=a.depthBuffer;this.stencilBuffer=a.stencilBuffer;this.depthTexture=a.depthTexture;return this},dispose:function(){this.dispatchEvent({type:"dispose"})}});Cb.prototype=Object.create(Bb.prototype);Cb.prototype.constructor=Cb;Cb.prototype.isWebGLRenderTargetCube=!0;cb.prototype=Object.create(O.prototype);cb.prototype.constructor=cb;cb.prototype.isDataTexture=!0;Va.prototype=Object.create(O.prototype);Va.prototype.constructor= +Va;Va.prototype.isCubeTexture=!0;Object.defineProperty(Va.prototype,"images",{get:function(){return this.image},set:function(a){this.image=a}});var De=new O,Ee=new Va,ye=[],Ae=[],Ce=new Float32Array(16),Be=new Float32Array(9);Ie.prototype.setValue=function(a,b){for(var c=this.seq,d=0,e=c.length;d!==e;++d){var f=c[d];f.setValue(a,b[f.id])}};var Pd=/([\w\d_]+)(\])?(\[|\.)?/g;db.prototype.setValue=function(a,b,c){b=this.map[b];void 0!==b&&b.setValue(a,c,this.renderer)};db.prototype.setOptional=function(a, +b,c){b=b[c];void 0!==b&&this.setValue(a,c,b)};db.upload=function(a,b,c,d){for(var e=0,f=b.length;e!==f;++e){var g=b[e],h=c[g.id];!1!==h.needsUpdate&&g.setValue(a,h.value,d)}};db.seqWithValue=function(a,b){for(var c=[],d=0,e=a.length;d!==e;++d){var f=a[d];f.id in b&&c.push(f)}return c};var qg={aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231, +cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539, +deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536, +lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154, +mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519, +royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074};Object.assign(H.prototype,{isColor:!0,r:1,g:1,b:1,set:function(a){a&& +a.isColor?this.copy(a):"number"===typeof a?this.setHex(a):"string"===typeof a&&this.setStyle(a);return this},setScalar:function(a){this.b=this.g=this.r=a;return this},setHex:function(a){a=Math.floor(a);this.r=(a>>16&255)/255;this.g=(a>>8&255)/255;this.b=(a&255)/255;return this},setRGB:function(a,b,c){this.r=a;this.g=b;this.b=c;return this},setHSL:function(){function a(a,c,d){0>d&&(d+=1);1d?c:d<2/3?a+6*(c-a)*(2/3-d):a}return function(b,c,d){b=R.euclideanModulo(b, +1);c=R.clamp(c,0,1);d=R.clamp(d,0,1);0===c?this.r=this.g=this.b=d:(c=.5>=d?d*(1+c):d+c-d*c,d=2*d-c,this.r=a(d,c,b+1/3),this.g=a(d,c,b),this.b=a(d,c,b-1/3));return this}}(),setStyle:function(a){function b(b){void 0!==b&&1>parseFloat(b)&&console.warn("THREE.Color: Alpha component of "+a+" will be ignored.")}var c;if(c=/^((?:rgb|hsl)a?)\(\s*([^\)]*)\)/.exec(a)){var d=c[2];switch(c[1]){case "rgb":case "rgba":if(c=/^(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec(d))return this.r=Math.min(255, +parseInt(c[1],10))/255,this.g=Math.min(255,parseInt(c[2],10))/255,this.b=Math.min(255,parseInt(c[3],10))/255,b(c[5]),this;if(c=/^(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec(d))return this.r=Math.min(100,parseInt(c[1],10))/100,this.g=Math.min(100,parseInt(c[2],10))/100,this.b=Math.min(100,parseInt(c[3],10))/100,b(c[5]),this;break;case "hsl":case "hsla":if(c=/^([0-9]*\.?[0-9]+)\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec(d)){var d=parseFloat(c[1])/360, +e=parseInt(c[2],10)/100,f=parseInt(c[3],10)/100;b(c[5]);return this.setHSL(d,e,f)}}}else if(c=/^\#([A-Fa-f0-9]+)$/.exec(a)){c=c[1];d=c.length;if(3===d)return this.r=parseInt(c.charAt(0)+c.charAt(0),16)/255,this.g=parseInt(c.charAt(1)+c.charAt(1),16)/255,this.b=parseInt(c.charAt(2)+c.charAt(2),16)/255,this;if(6===d)return this.r=parseInt(c.charAt(0)+c.charAt(1),16)/255,this.g=parseInt(c.charAt(2)+c.charAt(3),16)/255,this.b=parseInt(c.charAt(4)+c.charAt(5),16)/255,this}a&&0=h?k/(e+f): +k/(2-e-f);switch(e){case b:g=(c-d)/k+(c 0.0 ) {\n#if defined ( PHYSICALLY_CORRECT_LIGHTS )\n\t\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\t\tfloat maxDistanceCutoffFactor = pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t\treturn distanceFalloff * maxDistanceCutoffFactor;\n#else\n\t\treturn pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );\n#endif\n\t}\n\treturn 1.0;\n}\nvec3 BRDF_Diffuse_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 specularColor, const in float dotLH ) {\n\tfloat fresnel = exp2( ( -5.55473 * dotLH - 6.98316 ) * dotLH );\n\treturn ( 1.0 - specularColor ) * fresnel + specularColor;\n}\nfloat G_GGX_Smith( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gl = dotNL + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\tfloat gv = dotNV + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\treturn 1.0 / ( gl * gv );\n}\nfloat G_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}\nvec3 BRDF_Specular_GGX( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNL = saturate( dot( geometry.normal, incidentLight.direction ) );\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\tfloat D = D_GGX( alpha, dotNH );\n\treturn F * ( G * 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 theta = acos( dot( N, V ) );\n\tvec2 uv = vec2(\n\t\tsqrt( saturate( roughness ) ),\n\t\tsaturate( theta / ( 0.5 * PI ) ) );\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.86267 + (0.49788 + 0.01436 * y ) * y;\n\tfloat b = 3.45068 + (4.18814 + y) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = (x > 0.0) ? v : 0.5 * inversesqrt( 1.0 - x * x ) - 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 * transpose( 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\tvec3 result = vec3( LTC_ClippedSphereFormFactor( vectorFormFactor ) );\n\treturn result;\n}\nvec3 BRDF_Specular_GGX_Environment( const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.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 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;\n\treturn specularColor * AB.x + AB.y;\n}\nfloat 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_Specular_BlinnPhong( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float shininess ) {\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n}\nfloat GGXRoughnessToBlinnExponent( const in float ggxRoughness ) {\n\treturn ( 2.0 / pow2( ggxRoughness + 0.0001 ) - 2.0 );\n}\nfloat BlinnExponentToGGXRoughness( const in float blinnExponent ) {\n\treturn sqrt( 2.0 / ( blinnExponent + 2.0 ) );\n}\n", -bumpmap_pars_fragment:"#ifdef USE_BUMPMAP\n\tuniform sampler2D bumpMap;\n\tuniform float bumpScale;\n\tvec2 dHdxy_fwd() {\n\t\tvec2 dSTdx = dFdx( vUv );\n\t\tvec2 dSTdy = dFdy( vUv );\n\t\tfloat Hll = bumpScale * texture2D( bumpMap, vUv ).x;\n\t\tfloat dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;\n\t\tfloat dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;\n\t\treturn vec2( dBx, dBy );\n\t}\n\tvec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy ) {\n\t\tvec3 vSigmaX = dFdx( surf_pos );\n\t\tvec3 vSigmaY = dFdy( surf_pos );\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 );\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\n", +bumpmap_pars_fragment:"#ifdef USE_BUMPMAP\n\tuniform sampler2D bumpMap;\n\tuniform float bumpScale;\n\tvec2 dHdxy_fwd() {\n\t\tvec2 dSTdx = dFdx( vUv );\n\t\tvec2 dSTdy = dFdy( vUv );\n\t\tfloat Hll = bumpScale * texture2D( bumpMap, vUv ).x;\n\t\tfloat dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;\n\t\tfloat dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;\n\t\treturn vec2( dBx, dBy );\n\t}\n\tvec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy ) {\n\t\tvec3 vSigmaX = vec3( dFdx( surf_pos.x ), dFdx( surf_pos.y ), dFdx( surf_pos.z ) );\n\t\tvec3 vSigmaY = vec3( dFdy( surf_pos.x ), dFdy( surf_pos.y ), dFdy( surf_pos.z ) );\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 );\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\n", clipping_planes_fragment:"#if NUM_CLIPPING_PLANES > 0\n\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; ++ i ) {\n\t\tvec4 plane = clippingPlanes[ i ];\n\t\tif ( dot( vViewPosition, plane.xyz ) > plane.w ) discard;\n\t}\n\t\t\n\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\tbool clipped = true;\n\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; ++ i ) {\n\t\t\tvec4 plane = clippingPlanes[ i ];\n\t\t\tclipped = ( dot( vViewPosition, plane.xyz ) > plane.w ) && clipped;\n\t\t}\n\t\tif ( clipped ) discard;\n\t\n\t#endif\n#endif\n", clipping_planes_pars_fragment:"#if NUM_CLIPPING_PLANES > 0\n\t#if ! defined( PHYSICAL ) && ! defined( PHONG )\n\t\tvarying vec3 vViewPosition;\n\t#endif\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif\n",clipping_planes_pars_vertex:"#if NUM_CLIPPING_PLANES > 0 && ! defined( PHYSICAL ) && ! defined( PHONG )\n\tvarying vec3 vViewPosition;\n#endif\n",clipping_planes_vertex:"#if NUM_CLIPPING_PLANES > 0 && ! defined( PHYSICAL ) && ! defined( PHONG )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n", -color_fragment:"#ifdef USE_COLOR\n\tdiffuseColor.rgb *= vColor;\n#endif",color_pars_fragment:"#ifdef USE_COLOR\n\tvarying vec3 vColor;\n#endif\n",color_pars_vertex:"#ifdef USE_COLOR\n\tvarying vec3 vColor;\n#endif",color_vertex:"#ifdef USE_COLOR\n\tvColor.xyz = color.xyz;\n#endif",common:"#define PI 3.14159265359\n#define PI2 6.28318530718\n#define PI_HALF 1.5707963267949\n#define RECIPROCAL_PI 0.31830988618\n#define RECIPROCAL_PI2 0.15915494\n#define LOG2 1.442695\n#define EPSILON 1e-6\n#define saturate(a) clamp( a, 0.0, 1.0 )\n#define whiteCompliment(a) ( 1.0 - saturate( a ) )\nfloat pow2( const in float 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 average( const in vec3 color ) { return dot( color, vec3( 0.3333 ) ); }\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}\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};\nstruct GeometricContext {\n\tvec3 position;\n\tvec3 normal;\n\tvec3 viewDir;\n};\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}\nvec3 projectOnPlane(in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\tfloat distance = dot( planeNormal, point - pointOnPlane );\n\treturn - distance * planeNormal + point;\n}\nfloat sideOfPlane( in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn sign( dot( point - pointOnPlane, planeNormal ) );\n}\nvec3 linePlaneIntersect( in vec3 pointOnLine, in vec3 lineDirection, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn lineDirection * ( dot( planeNormal, pointOnPlane - pointOnLine ) / dot( planeNormal, lineDirection ) ) + pointOnLine;\n}\nmat3 transpose( const in mat3 v ) {\n\tmat3 tmp;\n\ttmp[0] = vec3(v[0].x, v[1].x, v[2].x);\n\ttmp[1] = vec3(v[0].y, v[1].y, v[2].y);\n\ttmp[2] = vec3(v[0].z, v[1].z, v[2].z);\n\treturn tmp;\n}\n", +color_fragment:"#ifdef USE_COLOR\n\tdiffuseColor.rgb *= vColor;\n#endif",color_pars_fragment:"#ifdef USE_COLOR\n\tvarying vec3 vColor;\n#endif\n",color_pars_vertex:"#ifdef USE_COLOR\n\tvarying vec3 vColor;\n#endif",color_vertex:"#ifdef USE_COLOR\n\tvColor.xyz = color.xyz;\n#endif",common:"#define PI 3.14159265359\n#define PI2 6.28318530718\n#define PI_HALF 1.5707963267949\n#define RECIPROCAL_PI 0.31830988618\n#define RECIPROCAL_PI2 0.15915494\n#define LOG2 1.442695\n#define EPSILON 1e-6\n#define saturate(a) clamp( a, 0.0, 1.0 )\n#define whiteCompliment(a) ( 1.0 - saturate( a ) )\nfloat pow2( const in float 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 average( const in vec3 color ) { return dot( color, vec3( 0.3333 ) ); }\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}\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};\nstruct GeometricContext {\n\tvec3 position;\n\tvec3 normal;\n\tvec3 viewDir;\n};\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}\nvec3 projectOnPlane(in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\tfloat distance = dot( planeNormal, point - pointOnPlane );\n\treturn - distance * planeNormal + point;\n}\nfloat sideOfPlane( in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn sign( dot( point - pointOnPlane, planeNormal ) );\n}\nvec3 linePlaneIntersect( in vec3 pointOnLine, in vec3 lineDirection, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn lineDirection * ( dot( planeNormal, pointOnPlane - pointOnLine ) / dot( planeNormal, lineDirection ) ) + pointOnLine;\n}\nmat3 transpose( const in mat3 v ) {\n\tmat3 tmp;\n\ttmp[0] = vec3(v[0].x, v[1].x, v[2].x);\n\ttmp[1] = vec3(v[0].y, v[1].y, v[2].y);\n\ttmp[2] = vec3(v[0].z, v[1].z, v[2].z);\n\treturn tmp;\n}\nfloat linearToRelativeLuminance( const in vec3 color ) {\n\tvec3 weights = vec3( 0.2126, 0.7152, 0.0722 );\n\treturn dot( weights, color.rgb );\n}\n", cube_uv_reflection_fragment:"#ifdef ENVMAP_TYPE_CUBE_UV\n#define cubeUV_textureSize (1024.0)\nint getFaceFromDirection(vec3 direction) {\n\tvec3 absDirection = abs(direction);\n\tint face = -1;\n\tif( absDirection.x > absDirection.z ) {\n\t\tif(absDirection.x > absDirection.y )\n\t\t\tface = direction.x > 0.0 ? 0 : 3;\n\t\telse\n\t\t\tface = direction.y > 0.0 ? 1 : 4;\n\t}\n\telse {\n\t\tif(absDirection.z > absDirection.y )\n\t\t\tface = direction.z > 0.0 ? 2 : 5;\n\t\telse\n\t\t\tface = direction.y > 0.0 ? 1 : 4;\n\t}\n\treturn face;\n}\n#define cubeUV_maxLods1 (log2(cubeUV_textureSize*0.25) - 1.0)\n#define cubeUV_rangeClamp (exp2((6.0 - 1.0) * 2.0))\nvec2 MipLevelInfo( vec3 vec, float roughnessLevel, float roughness ) {\n\tfloat scale = exp2(cubeUV_maxLods1 - roughnessLevel);\n\tfloat dxRoughness = dFdx(roughness);\n\tfloat dyRoughness = dFdy(roughness);\n\tvec3 dx = dFdx( vec * scale * dxRoughness );\n\tvec3 dy = dFdy( vec * scale * dyRoughness );\n\tfloat d = max( dot( dx, dx ), dot( dy, dy ) );\n\td = clamp(d, 1.0, cubeUV_rangeClamp);\n\tfloat mipLevel = 0.5 * log2(d);\n\treturn vec2(floor(mipLevel), fract(mipLevel));\n}\n#define cubeUV_maxLods2 (log2(cubeUV_textureSize*0.25) - 2.0)\n#define cubeUV_rcpTextureSize (1.0 / cubeUV_textureSize)\nvec2 getCubeUV(vec3 direction, float roughnessLevel, float mipLevel) {\n\tmipLevel = roughnessLevel > cubeUV_maxLods2 - 3.0 ? 0.0 : mipLevel;\n\tfloat a = 16.0 * cubeUV_rcpTextureSize;\n\tvec2 exp2_packed = exp2( vec2( roughnessLevel, mipLevel ) );\n\tvec2 rcp_exp2_packed = vec2( 1.0 ) / exp2_packed;\n\tfloat powScale = exp2_packed.x * exp2_packed.y;\n\tfloat scale = rcp_exp2_packed.x * rcp_exp2_packed.y * 0.25;\n\tfloat mipOffset = 0.75*(1.0 - rcp_exp2_packed.y) * rcp_exp2_packed.x;\n\tbool bRes = mipLevel == 0.0;\n\tscale = bRes && (scale < a) ? a : scale;\n\tvec3 r;\n\tvec2 offset;\n\tint face = getFaceFromDirection(direction);\n\tfloat rcpPowScale = 1.0 / powScale;\n\tif( face == 0) {\n\t\tr = vec3(direction.x, -direction.z, direction.y);\n\t\toffset = vec2(0.0+mipOffset,0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 1) {\n\t\tr = vec3(direction.y, direction.x, direction.z);\n\t\toffset = vec2(scale+mipOffset, 0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 2) {\n\t\tr = vec3(direction.z, direction.x, direction.y);\n\t\toffset = vec2(2.0*scale+mipOffset, 0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 3) {\n\t\tr = vec3(direction.x, direction.z, direction.y);\n\t\toffset = vec2(0.0+mipOffset,0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\telse if( face == 4) {\n\t\tr = vec3(direction.y, direction.x, -direction.z);\n\t\toffset = vec2(scale+mipOffset, 0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\telse {\n\t\tr = vec3(direction.z, -direction.x, direction.y);\n\t\toffset = vec2(2.0*scale+mipOffset, 0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\tr = normalize(r);\n\tfloat texelOffset = 0.5 * cubeUV_rcpTextureSize;\n\tvec2 s = ( r.yz / abs( r.x ) + vec2( 1.0 ) ) * 0.5;\n\tvec2 base = offset + vec2( texelOffset );\n\treturn base + s * ( scale - 2.0 * texelOffset );\n}\n#define cubeUV_maxLods3 (log2(cubeUV_textureSize*0.25) - 3.0)\nvec4 textureCubeUV(vec3 reflectedDirection, float roughness ) {\n\tfloat roughnessVal = roughness* cubeUV_maxLods3;\n\tfloat r1 = floor(roughnessVal);\n\tfloat r2 = r1 + 1.0;\n\tfloat t = fract(roughnessVal);\n\tvec2 mipInfo = MipLevelInfo(reflectedDirection, r1, roughness);\n\tfloat s = mipInfo.y;\n\tfloat level0 = mipInfo.x;\n\tfloat level1 = level0 + 1.0;\n\tlevel1 = level1 > 5.0 ? 5.0 : level1;\n\tlevel0 += min( floor( s + 0.5 ), 5.0 );\n\tvec2 uv_10 = getCubeUV(reflectedDirection, r1, level0);\n\tvec4 color10 = envMapTexelToLinear(texture2D(envMap, uv_10));\n\tvec2 uv_20 = getCubeUV(reflectedDirection, r2, level0);\n\tvec4 color20 = envMapTexelToLinear(texture2D(envMap, uv_20));\n\tvec4 result = mix(color10, color20, t);\n\treturn vec4(result.rgb, 1.0);\n}\n#endif\n", -defaultnormal_vertex:"#ifdef FLIP_SIDED\n\tobjectNormal = -objectNormal;\n#endif\nvec3 transformedNormal = normalMatrix * objectNormal;\n",displacementmap_pars_vertex:"#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif\n",displacementmap_vertex:"#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normal * ( texture2D( displacementMap, uv ).x * displacementScale + displacementBias );\n#endif\n",emissivemap_fragment:"#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vUv );\n\temissiveColor.rgb = emissiveMapTexelToLinear( emissiveColor ).rgb;\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif\n", -emissivemap_pars_fragment:"#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif\n",encodings_fragment:" gl_FragColor = linearToOutputTexel( gl_FragColor );\n",encodings_pars_fragment:"\nvec4 LinearToLinear( in vec4 value ) {\n\treturn value;\n}\nvec4 GammaToLinear( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.xyz, vec3( gammaFactor ) ), value.w );\n}\nvec4 LinearToGamma( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.xyz, vec3( 1.0 / gammaFactor ) ), value.w );\n}\nvec4 sRGBToLinear( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), value.rgb * 0.0773993808, vec3( lessThanEqual( value.rgb, vec3( 0.04045 ) ) ) ), value.w );\n}\nvec4 LinearTosRGB( 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.w );\n}\nvec4 RGBEToLinear( in vec4 value ) {\n\treturn vec4( value.rgb * exp2( value.a * 255.0 - 128.0 ), 1.0 );\n}\nvec4 LinearToRGBE( in vec4 value ) {\n\tfloat maxComponent = max( max( value.r, value.g ), value.b );\n\tfloat fExp = clamp( ceil( log2( maxComponent ) ), -128.0, 127.0 );\n\treturn vec4( value.rgb / exp2( fExp ), ( fExp + 128.0 ) / 255.0 );\n}\nvec4 RGBMToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.xyz * value.w * maxRange, 1.0 );\n}\nvec4 LinearToRGBM( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.x, max( value.g, value.b ) );\n\tfloat M = clamp( maxRGB / maxRange, 0.0, 1.0 );\n\tM = ceil( M * 255.0 ) / 255.0;\n\treturn vec4( value.rgb / ( M * maxRange ), M );\n}\nvec4 RGBDToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.rgb * ( ( maxRange / 255.0 ) / value.a ), 1.0 );\n}\nvec4 LinearToRGBD( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.x, max( value.g, value.b ) );\n\tfloat D = max( maxRange / maxRGB, 1.0 );\n\tD = min( floor( D ) / 255.0, 1.0 );\n\treturn vec4( value.rgb * ( D * ( 255.0 / maxRange ) ), D );\n}\nconst mat3 cLogLuvM = mat3( 0.2209, 0.3390, 0.4184, 0.1138, 0.6780, 0.7319, 0.0102, 0.1130, 0.2969 );\nvec4 LinearToLogLuv( in vec4 value ) {\n\tvec3 Xp_Y_XYZp = value.rgb * cLogLuvM;\n\tXp_Y_XYZp = max(Xp_Y_XYZp, vec3(1e-6, 1e-6, 1e-6));\n\tvec4 vResult;\n\tvResult.xy = Xp_Y_XYZp.xy / Xp_Y_XYZp.z;\n\tfloat Le = 2.0 * log2(Xp_Y_XYZp.y) + 127.0;\n\tvResult.w = fract(Le);\n\tvResult.z = (Le - (floor(vResult.w*255.0))/255.0)/255.0;\n\treturn vResult;\n}\nconst mat3 cLogLuvInverseM = mat3( 6.0014, -2.7008, -1.7996, -1.3320, 3.1029, -5.7721, 0.3008, -1.0882, 5.6268 );\nvec4 LogLuvToLinear( in vec4 value ) {\n\tfloat Le = value.z * 255.0 + value.w;\n\tvec3 Xp_Y_XYZp;\n\tXp_Y_XYZp.y = exp2((Le - 127.0) / 2.0);\n\tXp_Y_XYZp.z = Xp_Y_XYZp.y / value.y;\n\tXp_Y_XYZp.x = value.x * Xp_Y_XYZp.z;\n\tvec3 vRGB = Xp_Y_XYZp.rgb * cLogLuvInverseM;\n\treturn vec4( max(vRGB, 0.0), 1.0 );\n}\n", -envmap_fragment:"#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvec3 cameraToVertex = normalize( vWorldPosition - cameraPosition );\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToVertex, 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, flipNormal * vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\t#elif defined( ENVMAP_TYPE_EQUIREC )\n\t\tvec2 sampleUV;\n\t\tsampleUV.y = saturate( flipNormal * reflectVec.y * 0.5 + 0.5 );\n\t\tsampleUV.x = atan( flipNormal * reflectVec.z, flipNormal * reflectVec.x ) * RECIPROCAL_PI2 + 0.5;\n\t\tvec4 envColor = texture2D( envMap, sampleUV );\n\t#elif defined( ENVMAP_TYPE_SPHERE )\n\t\tvec3 reflectView = flipNormal * normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0, 0.0, 1.0 ) );\n\t\tvec4 envColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5 );\n\t#else\n\t\tvec4 envColor = vec4( 0.0 );\n\t#endif\n\tenvColor = envMapTexelToLinear( envColor );\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\n", +defaultnormal_vertex:"vec3 transformedNormal = normalMatrix * objectNormal;\n#ifdef FLIP_SIDED\n\ttransformedNormal = - transformedNormal;\n#endif\n",displacementmap_pars_vertex:"#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif\n",displacementmap_vertex:"#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, uv ).x * displacementScale + displacementBias );\n#endif\n", +emissivemap_fragment:"#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vUv );\n\temissiveColor.rgb = emissiveMapTexelToLinear( emissiveColor ).rgb;\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif\n",emissivemap_pars_fragment:"#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif\n",encodings_fragment:" gl_FragColor = linearToOutputTexel( gl_FragColor );\n",encodings_pars_fragment:"\nvec4 LinearToLinear( in vec4 value ) {\n\treturn value;\n}\nvec4 GammaToLinear( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.xyz, vec3( gammaFactor ) ), value.w );\n}\nvec4 LinearToGamma( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.xyz, vec3( 1.0 / gammaFactor ) ), value.w );\n}\nvec4 sRGBToLinear( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), value.rgb * 0.0773993808, vec3( lessThanEqual( value.rgb, vec3( 0.04045 ) ) ) ), value.w );\n}\nvec4 LinearTosRGB( 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.w );\n}\nvec4 RGBEToLinear( in vec4 value ) {\n\treturn vec4( value.rgb * exp2( value.a * 255.0 - 128.0 ), 1.0 );\n}\nvec4 LinearToRGBE( in vec4 value ) {\n\tfloat maxComponent = max( max( value.r, value.g ), value.b );\n\tfloat fExp = clamp( ceil( log2( maxComponent ) ), -128.0, 127.0 );\n\treturn vec4( value.rgb / exp2( fExp ), ( fExp + 128.0 ) / 255.0 );\n}\nvec4 RGBMToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.xyz * value.w * maxRange, 1.0 );\n}\nvec4 LinearToRGBM( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.x, max( value.g, value.b ) );\n\tfloat M = clamp( maxRGB / maxRange, 0.0, 1.0 );\n\tM = ceil( M * 255.0 ) / 255.0;\n\treturn vec4( value.rgb / ( M * maxRange ), M );\n}\nvec4 RGBDToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.rgb * ( ( maxRange / 255.0 ) / value.a ), 1.0 );\n}\nvec4 LinearToRGBD( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.x, max( value.g, value.b ) );\n\tfloat D = max( maxRange / maxRGB, 1.0 );\n\tD = min( floor( D ) / 255.0, 1.0 );\n\treturn vec4( value.rgb * ( D * ( 255.0 / maxRange ) ), D );\n}\nconst mat3 cLogLuvM = mat3( 0.2209, 0.3390, 0.4184, 0.1138, 0.6780, 0.7319, 0.0102, 0.1130, 0.2969 );\nvec4 LinearToLogLuv( in vec4 value ) {\n\tvec3 Xp_Y_XYZp = value.rgb * cLogLuvM;\n\tXp_Y_XYZp = max(Xp_Y_XYZp, vec3(1e-6, 1e-6, 1e-6));\n\tvec4 vResult;\n\tvResult.xy = Xp_Y_XYZp.xy / Xp_Y_XYZp.z;\n\tfloat Le = 2.0 * log2(Xp_Y_XYZp.y) + 127.0;\n\tvResult.w = fract(Le);\n\tvResult.z = (Le - (floor(vResult.w*255.0))/255.0)/255.0;\n\treturn vResult;\n}\nconst mat3 cLogLuvInverseM = mat3( 6.0014, -2.7008, -1.7996, -1.3320, 3.1029, -5.7721, 0.3008, -1.0882, 5.6268 );\nvec4 LogLuvToLinear( in vec4 value ) {\n\tfloat Le = value.z * 255.0 + value.w;\n\tvec3 Xp_Y_XYZp;\n\tXp_Y_XYZp.y = exp2((Le - 127.0) / 2.0);\n\tXp_Y_XYZp.z = Xp_Y_XYZp.y / value.y;\n\tXp_Y_XYZp.x = value.x * Xp_Y_XYZp.z;\n\tvec3 vRGB = Xp_Y_XYZp.rgb * cLogLuvInverseM;\n\treturn vec4( max(vRGB, 0.0), 1.0 );\n}\n", +envmap_fragment:"#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvec3 cameraToVertex = normalize( vWorldPosition - cameraPosition );\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToVertex, 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#elif defined( ENVMAP_TYPE_EQUIREC )\n\t\tvec2 sampleUV;\n\t\treflectVec = normalize( reflectVec );\n\t\tsampleUV.y = asin( clamp( reflectVec.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\t\tsampleUV.x = atan( reflectVec.z, reflectVec.x ) * RECIPROCAL_PI2 + 0.5;\n\t\tvec4 envColor = texture2D( envMap, sampleUV );\n\t#elif defined( ENVMAP_TYPE_SPHERE )\n\t\treflectVec = normalize( reflectVec );\n\t\tvec3 reflectView = normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0, 0.0, 1.0 ) );\n\t\tvec4 envColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5 );\n\t#else\n\t\tvec4 envColor = vec4( 0.0 );\n\t#endif\n\tenvColor = envMapTexelToLinear( envColor );\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\n", envmap_pars_fragment:"#if defined( USE_ENVMAP ) || defined( PHYSICAL )\n\tuniform float reflectivity;\n\tuniform float envMapIntensity;\n#endif\n#ifdef USE_ENVMAP\n\t#if ! defined( PHYSICAL ) && ( defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) )\n\t\tvarying vec3 vWorldPosition;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tuniform samplerCube envMap;\n\t#else\n\t\tuniform sampler2D envMap;\n\t#endif\n\tuniform float flipEnvMap;\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( PHYSICAL )\n\t\tuniform float refractionRatio;\n\t#else\n\t\tvarying vec3 vReflect;\n\t#endif\n#endif\n", envmap_pars_vertex:"#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvarying vec3 vWorldPosition;\n\t#else\n\t\tvarying vec3 vReflect;\n\t\tuniform float refractionRatio;\n\t#endif\n#endif\n",envmap_vertex:"#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvWorldPosition = worldPosition.xyz;\n\t#else\n\t\tvec3 cameraToVertex = normalize( worldPosition.xyz - cameraPosition );\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\n", fog_vertex:"\n#ifdef USE_FOG\nfogDepth = -mvPosition.z;\n#endif",fog_pars_vertex:"#ifdef USE_FOG\n varying float fogDepth;\n#endif\n",fog_fragment:"#ifdef USE_FOG\n\t#ifdef FOG_EXP2\n\t\tfloat fogFactor = whiteCompliment( exp2( - fogDensity * fogDensity * fogDepth * fogDepth * LOG2 ) );\n\t#else\n\t\tfloat fogFactor = smoothstep( fogNear, fogFar, fogDepth );\n\t#endif\n\tgl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n#endif\n",fog_pars_fragment:"#ifdef USE_FOG\n\tuniform vec3 fogColor;\n\tvarying float fogDepth;\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\n", gradientmap_pars_fragment:"#ifdef TOON\n\tuniform sampler2D gradientMap;\n\tvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\n\t\tfloat dotNL = dot( normal, lightDirection );\n\t\tvec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\n\t\t#ifdef USE_GRADIENTMAP\n\t\t\treturn texture2D( gradientMap, coord ).rgb;\n\t\t#else\n\t\t\treturn ( coord.x < 0.7 ) ? vec3( 0.7 ) : vec3( 1.0 );\n\t\t#endif\n\t}\n#endif\n",lightmap_fragment:"#ifdef USE_LIGHTMAP\n\treflectedLight.indirectDiffuse += PI * texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n#endif\n", lightmap_pars_fragment:"#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif",lights_lambert_vertex:"vec3 diffuse = vec3( 1.0 );\nGeometricContext geometry;\ngeometry.position = mvPosition.xyz;\ngeometry.normal = normalize( transformedNormal );\ngeometry.viewDir = normalize( -mvPosition.xyz );\nGeometricContext backGeometry;\nbackGeometry.position = geometry.position;\nbackGeometry.normal = -geometry.normal;\nbackGeometry.viewDir = geometry.viewDir;\nvLightFront = vec3( 0.0 );\n#ifdef DOUBLE_SIDED\n\tvLightBack = vec3( 0.0 );\n#endif\nIncidentLight directLight;\nfloat dotNL;\nvec3 directLightColor_Diffuse;\n#if NUM_POINT_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tgetPointDirectLightIrradiance( pointLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tgetSpotDirectLightIrradiance( spotLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_DIR_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tgetDirectionalDirectLightIrradiance( directionalLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\tvLightFront += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += getHemisphereLightIrradiance( hemisphereLights[ i ], backGeometry );\n\t\t#endif\n\t}\n#endif\n", -lights_pars:"uniform vec3 ambientLightColor;\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treturn irradiance;\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalDirectLightIrradiance( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tdirectLight.color = directionalLight.color;\n\t\tdirectLight.direction = directionalLight.direction;\n\t\tdirectLight.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\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointDirectLightIrradiance( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tvec3 lVector = pointLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tdirectLight.color = pointLight.color;\n\t\tdirectLight.color *= punctualLightIntensityToIrradianceFactor( lightDistance, pointLight.distance, pointLight.decay );\n\t\tdirectLight.visible = ( directLight.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\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\tvoid getSpotDirectLightIrradiance( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tvec3 lVector = spotLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tfloat angleCos = dot( directLight.direction, spotLight.direction );\n\t\tif ( angleCos > spotLight.coneCos ) {\n\t\t\tfloat spotEffect = smoothstep( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\t\tdirectLight.color = spotLight.color;\n\t\t\tdirectLight.color *= spotEffect * punctualLightIntensityToIrradianceFactor( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tdirectLight.visible = true;\n\t\t} else {\n\t\t\tdirectLight.color = vec3( 0.0 );\n\t\t\tdirectLight.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 ltcMat;\tuniform sampler2D ltcMag;\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 GeometricContext geometry ) {\n\t\tfloat dotNL = dot( geometry.normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tirradiance *= PI;\n\t\t#endif\n\t\treturn irradiance;\n\t}\n#endif\n#if defined( USE_ENVMAP ) && defined( PHYSICAL )\n\tvec3 getLightProbeIndirectIrradiance( const in GeometricContext geometry, const in int maxMIPLevel ) {\n\t\tvec3 worldNormal = inverseTransformDirection( geometry.normal, viewMatrix );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\tvec4 envMapColor = textureCubeUV( queryVec, 1.0 );\n\t\t#else\n\t\t\tvec4 envMapColor = vec4( 0.0 );\n\t\t#endif\n\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t}\n\tfloat getSpecularMIPLevel( const in float blinnShininessExponent, const in int maxMIPLevel ) {\n\t\tfloat maxMIPLevelScalar = float( maxMIPLevel );\n\t\tfloat desiredMIPLevel = maxMIPLevelScalar - 0.79248 - 0.5 * log2( pow2( blinnShininessExponent ) + 1.0 );\n\t\treturn clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );\n\t}\n\tvec3 getLightProbeIndirectRadiance( const in GeometricContext geometry, const in float blinnShininessExponent, const in int maxMIPLevel ) {\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( -geometry.viewDir, geometry.normal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( -geometry.viewDir, geometry.normal, refractionRatio );\n\t\t#endif\n\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\tfloat specularMIPLevel = getSpecularMIPLevel( blinnShininessExponent, maxMIPLevel );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\tvec4 envMapColor = textureCubeUV(queryReflectVec, BlinnExponentToGGXRoughness(blinnShininessExponent));\n\t\t#elif defined( ENVMAP_TYPE_EQUIREC )\n\t\t\tvec2 sampleUV;\n\t\t\tsampleUV.y = saturate( reflectVec.y * 0.5 + 0.5 );\n\t\t\tsampleUV.x = atan( reflectVec.z, reflectVec.x ) * RECIPROCAL_PI2 + 0.5;\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = texture2DLodEXT( envMap, sampleUV, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = texture2D( envMap, sampleUV, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_SPHERE )\n\t\t\tvec3 reflectView = normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0,0.0,1.0 ) );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = texture2DLodEXT( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#endif\n\t\treturn envMapColor.rgb * envMapIntensity;\n\t}\n#endif\n", +lights_pars:"uniform vec3 ambientLightColor;\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treturn irradiance;\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalDirectLightIrradiance( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tdirectLight.color = directionalLight.color;\n\t\tdirectLight.direction = directionalLight.direction;\n\t\tdirectLight.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\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t\tfloat shadowCameraNear;\n\t\tfloat shadowCameraFar;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointDirectLightIrradiance( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tvec3 lVector = pointLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tdirectLight.color = pointLight.color;\n\t\tdirectLight.color *= punctualLightIntensityToIrradianceFactor( lightDistance, pointLight.distance, pointLight.decay );\n\t\tdirectLight.visible = ( directLight.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\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\tvoid getSpotDirectLightIrradiance( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tvec3 lVector = spotLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tfloat angleCos = dot( directLight.direction, spotLight.direction );\n\t\tif ( angleCos > spotLight.coneCos ) {\n\t\t\tfloat spotEffect = smoothstep( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\t\tdirectLight.color = spotLight.color;\n\t\t\tdirectLight.color *= spotEffect * punctualLightIntensityToIrradianceFactor( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tdirectLight.visible = true;\n\t\t} else {\n\t\t\tdirectLight.color = vec3( 0.0 );\n\t\t\tdirectLight.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 ltcMat;\tuniform sampler2D ltcMag;\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 GeometricContext geometry ) {\n\t\tfloat dotNL = dot( geometry.normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tirradiance *= PI;\n\t\t#endif\n\t\treturn irradiance;\n\t}\n#endif\n#if defined( USE_ENVMAP ) && defined( PHYSICAL )\n\tvec3 getLightProbeIndirectIrradiance( const in GeometricContext geometry, const in int maxMIPLevel ) {\n\t\tvec3 worldNormal = inverseTransformDirection( geometry.normal, viewMatrix );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\tvec4 envMapColor = textureCubeUV( queryVec, 1.0 );\n\t\t#else\n\t\t\tvec4 envMapColor = vec4( 0.0 );\n\t\t#endif\n\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t}\n\tfloat getSpecularMIPLevel( const in float blinnShininessExponent, const in int maxMIPLevel ) {\n\t\tfloat maxMIPLevelScalar = float( maxMIPLevel );\n\t\tfloat desiredMIPLevel = maxMIPLevelScalar - 0.79248 - 0.5 * log2( pow2( blinnShininessExponent ) + 1.0 );\n\t\treturn clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );\n\t}\n\tvec3 getLightProbeIndirectRadiance( const in GeometricContext geometry, const in float blinnShininessExponent, const in int maxMIPLevel ) {\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( -geometry.viewDir, geometry.normal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( -geometry.viewDir, geometry.normal, refractionRatio );\n\t\t#endif\n\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\tfloat specularMIPLevel = getSpecularMIPLevel( blinnShininessExponent, maxMIPLevel );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\tvec4 envMapColor = textureCubeUV(queryReflectVec, BlinnExponentToGGXRoughness(blinnShininessExponent));\n\t\t#elif defined( ENVMAP_TYPE_EQUIREC )\n\t\t\tvec2 sampleUV;\n\t\t\tsampleUV.y = asin( clamp( reflectVec.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\t\t\tsampleUV.x = atan( reflectVec.z, reflectVec.x ) * RECIPROCAL_PI2 + 0.5;\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = texture2DLodEXT( envMap, sampleUV, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = texture2D( envMap, sampleUV, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_SPHERE )\n\t\t\tvec3 reflectView = normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0,0.0,1.0 ) );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = texture2DLodEXT( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#endif\n\t\treturn envMapColor.rgb * envMapIntensity;\n\t}\n#endif\n", lights_phong_fragment:"BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;\n",lights_phong_pars_fragment:"varying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\nstruct BlinnPhongMaterial {\n\tvec3\tdiffuseColor;\n\tvec3\tspecularColor;\n\tfloat\tspecularShininess;\n\tfloat\tspecularStrength;\n};\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\t#ifdef TOON\n\t\tvec3 irradiance = getGradientIrradiance( geometry.normal, directLight.direction ) * directLight.color;\n\t#else\n\t\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\t\tvec3 irradiance = dotNL * directLight.color;\n\t#endif\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treflectedLight.directDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_Specular_BlinnPhong( directLight, geometry, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_BlinnPhong\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_BlinnPhong\n#define Material_LightProbeLOD( material )\t(0)\n", lights_physical_fragment:"PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nmaterial.specularRoughness = clamp( roughnessFactor, 0.04, 1.0 );\n#ifdef STANDARD\n\tmaterial.specularColor = mix( vec3( DEFAULT_SPECULAR_COEFFICIENT ), diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( MAXIMUM_SPECULAR_COEFFICIENT * pow2( reflectivity ) ), diffuseColor.rgb, metalnessFactor );\n\tmaterial.clearCoat = saturate( clearCoat );\tmaterial.clearCoatRoughness = clamp( clearCoatRoughness, 0.04, 1.0 );\n#endif\n", lights_physical_pars_fragment:"struct PhysicalMaterial {\n\tvec3\tdiffuseColor;\n\tfloat\tspecularRoughness;\n\tvec3\tspecularColor;\n\t#ifndef STANDARD\n\t\tfloat clearCoat;\n\t\tfloat clearCoatRoughness;\n\t#endif\n};\n#define MAXIMUM_SPECULAR_COEFFICIENT 0.16\n#define DEFAULT_SPECULAR_COEFFICIENT 0.04\nfloat clearCoatDHRApprox( const in float roughness, const in float dotNL ) {\n\treturn DEFAULT_SPECULAR_COEFFICIENT + ( 1.0 - DEFAULT_SPECULAR_COEFFICIENT ) * ( pow( 1.0 - dotNL, 5.0 ) * pow( 1.0 - roughness, 2.0 ) );\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometry.normal;\n\t\tvec3 viewDir = geometry.viewDir;\n\t\tvec3 position = geometry.position;\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.specularRoughness;\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\tfloat norm = texture2D( ltcMag, uv ).a;\n\t\tvec4 t = texture2D( ltcMat, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( 1, 0, t.y ),\n\t\t\tvec3( 0, t.z, 0 ),\n\t\t\tvec3( t.w, 0, t.x )\n\t\t);\n\t\treflectedLight.directSpecular += lightColor * material.specularColor * norm * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\t#ifndef STANDARD\n\t\tfloat clearCoatDHR = material.clearCoat * clearCoatDHRApprox( material.clearCoatRoughness, dotNL );\n\t#else\n\t\tfloat clearCoatDHR = 0.0;\n\t#endif\n\treflectedLight.directSpecular += ( 1.0 - clearCoatDHR ) * irradiance * BRDF_Specular_GGX( directLight, geometry, material.specularColor, material.specularRoughness );\n\treflectedLight.directDiffuse += ( 1.0 - clearCoatDHR ) * irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\t#ifndef STANDARD\n\t\treflectedLight.directSpecular += irradiance * material.clearCoat * BRDF_Specular_GGX( directLight, geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness );\n\t#endif\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 clearCoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t#ifndef STANDARD\n\t\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\t\tfloat dotNL = dotNV;\n\t\tfloat clearCoatDHR = material.clearCoat * clearCoatDHRApprox( material.clearCoatRoughness, dotNL );\n\t#else\n\t\tfloat clearCoatDHR = 0.0;\n\t#endif\n\treflectedLight.indirectSpecular += ( 1.0 - clearCoatDHR ) * radiance * BRDF_Specular_GGX_Environment( geometry, material.specularColor, material.specularRoughness );\n\t#ifndef STANDARD\n\t\treflectedLight.indirectSpecular += clearCoatRadiance * material.clearCoat * BRDF_Specular_GGX_Environment( geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness );\n\t#endif\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\n#define Material_BlinnShininessExponent( material ) GGXRoughnessToBlinnExponent( material.specularRoughness )\n#define Material_ClearCoat_BlinnShininessExponent( material ) GGXRoughnessToBlinnExponent( material.clearCoatRoughness )\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}\n", -lights_template:"\nGeometricContext geometry;\ngeometry.position = - vViewPosition;\ngeometry.normal = normal;\ngeometry.viewDir = normalize( vViewPosition );\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointDirectLightIrradiance( pointLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( pointLight.shadow, directLight.visible ) ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotDirectLightIrradiance( spotLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( spotLight.shadow, directLight.visible ) ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalDirectLightIrradiance( directionalLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( directionalLight.shadow, directLight.visible ) ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\t#ifdef USE_LIGHTMAP\n\t\tvec3 lightMapIrradiance = texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tlightMapIrradiance *= PI;\n\t\t#endif\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t}\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( PHYSICAL ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tirradiance += getLightProbeIndirectIrradiance( geometry, 8 );\n\t#endif\n\tRE_IndirectDiffuse( irradiance, geometry, material, reflectedLight );\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\tvec3 radiance = getLightProbeIndirectRadiance( geometry, Material_BlinnShininessExponent( material ), 8 );\n\t#ifndef STANDARD\n\t\tvec3 clearCoatRadiance = getLightProbeIndirectRadiance( geometry, Material_ClearCoat_BlinnShininessExponent( material ), 8 );\n\t#else\n\t\tvec3 clearCoatRadiance = vec3( 0.0 );\n\t#endif\n\tRE_IndirectSpecular( radiance, clearCoatRadiance, geometry, material, reflectedLight );\n#endif\n", -logdepthbuf_fragment:"#if defined(USE_LOGDEPTHBUF) && defined(USE_LOGDEPTHBUF_EXT)\n\tgl_FragDepthEXT = log2(vFragDepth) * logDepthBufFC * 0.5;\n#endif",logdepthbuf_pars_fragment:"#ifdef USE_LOGDEPTHBUF\n\tuniform float logDepthBufFC;\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t#endif\n#endif\n",logdepthbuf_pars_vertex:"#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t#endif\n\tuniform float logDepthBufFC;\n#endif",logdepthbuf_vertex:"#ifdef USE_LOGDEPTHBUF\n\tgl_Position.z = log2(max( EPSILON, gl_Position.w + 1.0 )) * logDepthBufFC;\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvFragDepth = 1.0 + gl_Position.w;\n\t#else\n\t\tgl_Position.z = (gl_Position.z - 1.0) * gl_Position.w;\n\t#endif\n#endif\n", -map_fragment:"#ifdef USE_MAP\n\tvec4 texelColor = texture2D( map, vUv );\n\ttexelColor = mapTexelToLinear( texelColor );\n\tdiffuseColor *= texelColor;\n#endif\n",map_pars_fragment:"#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif\n",map_particle_fragment:"#ifdef USE_MAP\n\tvec4 mapTexel = texture2D( map, vec2( gl_PointCoord.x, 1.0 - gl_PointCoord.y ) * offsetRepeat.zw + offsetRepeat.xy );\n\tdiffuseColor *= mapTexelToLinear( mapTexel );\n#endif\n",map_particle_pars_fragment:"#ifdef USE_MAP\n\tuniform vec4 offsetRepeat;\n\tuniform sampler2D map;\n#endif\n", +lights_template:"\nGeometricContext geometry;\ngeometry.position = - vViewPosition;\ngeometry.normal = normal;\ngeometry.viewDir = normalize( vViewPosition );\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointDirectLightIrradiance( pointLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( pointLight.shadow, directLight.visible ) ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotDirectLightIrradiance( spotLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( spotLight.shadow, directLight.visible ) ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalDirectLightIrradiance( directionalLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( directionalLight.shadow, directLight.visible ) ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\t#ifdef USE_LIGHTMAP\n\t\tvec3 lightMapIrradiance = texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tlightMapIrradiance *= PI;\n\t\t#endif\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t}\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( PHYSICAL ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tirradiance += getLightProbeIndirectIrradiance( geometry, 8 );\n\t#endif\n\tRE_IndirectDiffuse( irradiance, geometry, material, reflectedLight );\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\tvec3 radiance = getLightProbeIndirectRadiance( geometry, Material_BlinnShininessExponent( material ), 8 );\n\t#ifndef STANDARD\n\t\tvec3 clearCoatRadiance = getLightProbeIndirectRadiance( geometry, Material_ClearCoat_BlinnShininessExponent( material ), 8 );\n\t#else\n\t\tvec3 clearCoatRadiance = vec3( 0.0 );\n\t#endif\n\tRE_IndirectSpecular( radiance, clearCoatRadiance, geometry, material, reflectedLight );\n#endif\n", +logdepthbuf_fragment:"#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tgl_FragDepthEXT = log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif",logdepthbuf_pars_fragment:"#ifdef USE_LOGDEPTHBUF\n\tuniform float logDepthBufFC;\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t#endif\n#endif\n",logdepthbuf_pars_vertex:"#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t#endif\n\tuniform float logDepthBufFC;\n#endif",logdepthbuf_vertex:"#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvFragDepth = 1.0 + gl_Position.w;\n\t#else\n\t\tgl_Position.z = log2( max( EPSILON, gl_Position.w + 1.0 ) ) * logDepthBufFC - 1.0;\n\t\tgl_Position.z *= gl_Position.w;\n\t#endif\n#endif\n", +map_fragment:"#ifdef USE_MAP\n\tvec4 texelColor = texture2D( map, vUv );\n\ttexelColor = mapTexelToLinear( texelColor );\n\tdiffuseColor *= texelColor;\n#endif\n",map_pars_fragment:"#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif\n",map_particle_fragment:"#ifdef USE_MAP\n\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n\tvec4 mapTexel = texture2D( map, uv );\n\tdiffuseColor *= mapTexelToLinear( mapTexel );\n#endif\n",map_particle_pars_fragment:"#ifdef USE_MAP\n\tuniform mat3 uvTransform;\n\tuniform sampler2D map;\n#endif\n", metalnessmap_fragment:"float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif\n",metalnessmap_pars_fragment:"#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif",morphnormal_vertex:"#ifdef USE_MORPHNORMALS\n\tobjectNormal += ( morphNormal0 - normal ) * morphTargetInfluences[ 0 ];\n\tobjectNormal += ( morphNormal1 - normal ) * morphTargetInfluences[ 1 ];\n\tobjectNormal += ( morphNormal2 - normal ) * morphTargetInfluences[ 2 ];\n\tobjectNormal += ( morphNormal3 - normal ) * morphTargetInfluences[ 3 ];\n#endif\n", morphtarget_pars_vertex:"#ifdef USE_MORPHTARGETS\n\t#ifndef USE_MORPHNORMALS\n\tuniform float morphTargetInfluences[ 8 ];\n\t#else\n\tuniform float morphTargetInfluences[ 4 ];\n\t#endif\n#endif",morphtarget_vertex:"#ifdef USE_MORPHTARGETS\n\ttransformed += ( morphTarget0 - position ) * morphTargetInfluences[ 0 ];\n\ttransformed += ( morphTarget1 - position ) * morphTargetInfluences[ 1 ];\n\ttransformed += ( morphTarget2 - position ) * morphTargetInfluences[ 2 ];\n\ttransformed += ( morphTarget3 - position ) * morphTargetInfluences[ 3 ];\n\t#ifndef USE_MORPHNORMALS\n\ttransformed += ( morphTarget4 - position ) * morphTargetInfluences[ 4 ];\n\ttransformed += ( morphTarget5 - position ) * morphTargetInfluences[ 5 ];\n\ttransformed += ( morphTarget6 - position ) * morphTargetInfluences[ 6 ];\n\ttransformed += ( morphTarget7 - position ) * morphTargetInfluences[ 7 ];\n\t#endif\n#endif\n", -normal_flip:"#ifdef DOUBLE_SIDED\n\tfloat flipNormal = ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n#else\n\tfloat flipNormal = 1.0;\n#endif\n",normal_fragment:"#ifdef FLAT_SHADED\n\tvec3 fdx = vec3( dFdx( vViewPosition.x ), dFdx( vViewPosition.y ), dFdx( vViewPosition.z ) );\n\tvec3 fdy = vec3( dFdy( vViewPosition.x ), dFdy( vViewPosition.y ), dFdy( vViewPosition.z ) );\n\tvec3 normal = normalize( cross( fdx, fdy ) );\n#else\n\tvec3 normal = normalize( vNormal ) * flipNormal;\n#endif\n#ifdef USE_NORMALMAP\n\tnormal = perturbNormal2Arb( -vViewPosition, normal );\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );\n#endif\n", -normalmap_pars_fragment:"#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n\tvec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm ) {\n\t\tvec3 q0 = dFdx( eye_pos.xyz );\n\t\tvec3 q1 = dFdy( eye_pos.xyz );\n\t\tvec2 st0 = dFdx( vUv.st );\n\t\tvec2 st1 = dFdy( vUv.st );\n\t\tvec3 S = normalize( q0 * st1.t - q1 * st0.t );\n\t\tvec3 T = normalize( -q0 * st1.s + q1 * st0.s );\n\t\tvec3 N = normalize( surf_norm );\n\t\tvec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\t\tmapN.xy = normalScale * mapN.xy;\n\t\tmat3 tsn = mat3( S, T, N );\n\t\treturn normalize( tsn * mapN );\n\t}\n#endif\n", +normal_fragment:"#ifdef FLAT_SHADED\n\tvec3 fdx = vec3( dFdx( vViewPosition.x ), dFdx( vViewPosition.y ), dFdx( vViewPosition.z ) );\n\tvec3 fdy = vec3( dFdy( vViewPosition.x ), dFdy( vViewPosition.y ), dFdy( vViewPosition.z ) );\n\tvec3 normal = normalize( cross( fdx, fdy ) );\n#else\n\tvec3 normal = normalize( vNormal );\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t#endif\n#endif\n#ifdef USE_NORMALMAP\n\tnormal = perturbNormal2Arb( -vViewPosition, normal );\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );\n#endif\n", +normalmap_pars_fragment:"#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n\tvec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm ) {\n\t\tvec3 q0 = vec3( dFdx( eye_pos.x ), dFdx( eye_pos.y ), dFdx( eye_pos.z ) );\n\t\tvec3 q1 = vec3( dFdy( eye_pos.x ), dFdy( eye_pos.y ), dFdy( eye_pos.z ) );\n\t\tvec2 st0 = dFdx( vUv.st );\n\t\tvec2 st1 = dFdy( vUv.st );\n\t\tvec3 S = normalize( q0 * st1.t - q1 * st0.t );\n\t\tvec3 T = normalize( -q0 * st1.s + q1 * st0.s );\n\t\tvec3 N = normalize( surf_norm );\n\t\tvec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\t\tmapN.xy = normalScale * mapN.xy;\n\t\tmat3 tsn = mat3( S, T, N );\n\t\treturn normalize( tsn * mapN );\n\t}\n#endif\n", packing:"vec3 packNormalToRGB( const in vec3 normal ) {\n\treturn normalize( normal ) * 0.5 + 0.5;\n}\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n\treturn 1.0 - 2.0 * rgb.xyz;\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}\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 linearClipZ, const in float near, const in float far ) {\n\treturn linearClipZ * ( 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 invClipZ, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * invClipZ - far );\n}\n", -premultiplied_alpha_fragment:"#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif\n",project_vertex:"#ifdef USE_SKINNING\n\tvec4 mvPosition = modelViewMatrix * skinned;\n#else\n\tvec4 mvPosition = modelViewMatrix * vec4( transformed, 1.0 );\n#endif\ngl_Position = projectionMatrix * mvPosition;\n",dithering_fragment:"#if defined( DITHERING )\n gl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif\n",dithering_pars_fragment:"#if defined( 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\n", -roughnessmap_fragment:"float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vUv );\n\troughnessFactor *= texelRoughness.g;\n#endif\n",roughnessmap_pars_fragment:"#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif",shadowmap_pars_fragment:"#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHTS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHTS ];\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHTS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHTS ];\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHTS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHTS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tfloat texture2DShadowLerp( sampler2D depths, vec2 size, vec2 uv, float compare ) {\n\t\tconst vec2 offset = vec2( 0.0, 1.0 );\n\t\tvec2 texelSize = vec2( 1.0 ) / size;\n\t\tvec2 centroidUV = floor( uv * size + 0.5 ) / size;\n\t\tfloat lb = texture2DCompare( depths, centroidUV + texelSize * offset.xx, compare );\n\t\tfloat lt = texture2DCompare( depths, centroidUV + texelSize * offset.xy, compare );\n\t\tfloat rb = texture2DCompare( depths, centroidUV + texelSize * offset.yx, compare );\n\t\tfloat rt = texture2DCompare( depths, centroidUV + texelSize * offset.yy, compare );\n\t\tvec2 f = fract( uv * size + 0.5 );\n\t\tfloat a = mix( lb, lt, f.y );\n\t\tfloat b = mix( rb, rt, f.y );\n\t\tfloat c = mix( a, b, f.x );\n\t\treturn c;\n\t}\n\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\tshadowCoord.z += shadowBias;\n\t\tbvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );\n\t\tbool inFrustum = all( inFrustumVec );\n\t\tbvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );\n\t\tbool frustumTest = all( frustumTestVec );\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\treturn (\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( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, 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( 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 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\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\treturn (\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\treturn texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#endif\n\t\t}\n\t\treturn 1.0;\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 ) {\n\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\tvec3 bd3D = normalize( lightToPosition );\n\t\tfloat dp = ( length( lightToPosition ) - shadowBias ) / 1000.0;\n\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT )\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\n", +premultiplied_alpha_fragment:"#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif\n",project_vertex:"vec4 mvPosition = modelViewMatrix * vec4( transformed, 1.0 );\ngl_Position = projectionMatrix * mvPosition;\n",dithering_fragment:"#if defined( DITHERING )\n gl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif\n",dithering_pars_fragment:"#if defined( 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\n", +roughnessmap_fragment:"float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vUv );\n\troughnessFactor *= texelRoughness.g;\n#endif\n",roughnessmap_pars_fragment:"#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif",shadowmap_pars_fragment:"#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHTS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHTS ];\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHTS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHTS ];\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHTS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHTS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tfloat texture2DShadowLerp( sampler2D depths, vec2 size, vec2 uv, float compare ) {\n\t\tconst vec2 offset = vec2( 0.0, 1.0 );\n\t\tvec2 texelSize = vec2( 1.0 ) / size;\n\t\tvec2 centroidUV = floor( uv * size + 0.5 ) / size;\n\t\tfloat lb = texture2DCompare( depths, centroidUV + texelSize * offset.xx, compare );\n\t\tfloat lt = texture2DCompare( depths, centroidUV + texelSize * offset.xy, compare );\n\t\tfloat rb = texture2DCompare( depths, centroidUV + texelSize * offset.yx, compare );\n\t\tfloat rt = texture2DCompare( depths, centroidUV + texelSize * offset.yy, compare );\n\t\tvec2 f = fract( uv * size + 0.5 );\n\t\tfloat a = mix( lb, lt, f.y );\n\t\tfloat b = mix( rb, rt, f.y );\n\t\tfloat c = mix( a, b, f.x );\n\t\treturn c;\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\tbvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );\n\t\tbool inFrustum = all( inFrustumVec );\n\t\tbvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );\n\t\tbool frustumTest = all( frustumTestVec );\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\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( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, 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( 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 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\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\tshadow = (\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 9.0 );\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 )\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\n", shadowmap_pars_vertex:"#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHTS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHTS ];\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\t\tuniform mat4 spotShadowMatrix[ NUM_SPOT_LIGHTS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHTS ];\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHTS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHTS ];\n\t#endif\n#endif\n", shadowmap_vertex:"#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tvSpotShadowCoord[ i ] = spotShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n#endif\n", -shadowmask_pars_fragment:"float getShadowMask() {\n\tfloat shadow = 1.0;\n\t#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\tDirectionalLight directionalLight;\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tshadow *= bool( directionalLight.shadow ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t}\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\tSpotLight spotLight;\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tshadow *= bool( spotLight.shadow ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t}\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\tPointLight pointLight;\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tshadow *= bool( pointLight.shadow ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ] ) : 1.0;\n\t}\n\t#endif\n\t#endif\n\treturn shadow;\n}\n", +shadowmask_pars_fragment:"float getShadowMask() {\n\tfloat shadow = 1.0;\n\t#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\tDirectionalLight directionalLight;\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tshadow *= bool( directionalLight.shadow ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t}\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\tSpotLight spotLight;\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tshadow *= bool( spotLight.shadow ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t}\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\tPointLight pointLight;\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tshadow *= bool( pointLight.shadow ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t}\n\t#endif\n\t#endif\n\treturn shadow;\n}\n", 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",skinning_pars_vertex:"#ifdef USE_SKINNING\n\tuniform mat4 bindMatrix;\n\tuniform mat4 bindMatrixInverse;\n\t#ifdef BONE_TEXTURE\n\t\tuniform sampler2D boneTexture;\n\t\tuniform int boneTextureSize;\n\t\tmat4 getBoneMatrix( const in float i ) {\n\t\t\tfloat j = i * 4.0;\n\t\t\tfloat x = mod( j, float( boneTextureSize ) );\n\t\t\tfloat y = floor( j / float( boneTextureSize ) );\n\t\t\tfloat dx = 1.0 / float( boneTextureSize );\n\t\t\tfloat dy = 1.0 / float( boneTextureSize );\n\t\t\ty = dy * ( y + 0.5 );\n\t\t\tvec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );\n\t\t\tvec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );\n\t\t\tvec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );\n\t\t\tvec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );\n\t\t\tmat4 bone = mat4( v1, v2, v3, v4 );\n\t\t\treturn bone;\n\t\t}\n\t#else\n\t\tuniform mat4 boneMatrices[ MAX_BONES ];\n\t\tmat4 getBoneMatrix( const in float i ) {\n\t\t\tmat4 bone = boneMatrices[ int(i) ];\n\t\t\treturn bone;\n\t\t}\n\t#endif\n#endif\n", -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\tskinned = bindMatrixInverse * skinned;\n#endif\n",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#endif\n", +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\n",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#endif\n", specularmap_fragment:"float specularStrength;\n#ifdef USE_SPECULARMAP\n\tvec4 texelSpecular = texture2D( specularMap, vUv );\n\tspecularStrength = texelSpecular.r;\n#else\n\tspecularStrength = 1.0;\n#endif",specularmap_pars_fragment:"#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif",tonemapping_fragment:"#if defined( TONE_MAPPING )\n gl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif\n",tonemapping_pars_fragment:"#define saturate(a) clamp( a, 0.0, 1.0 )\nuniform float toneMappingExposure;\nuniform float toneMappingWhitePoint;\nvec3 LinearToneMapping( vec3 color ) {\n\treturn toneMappingExposure * color;\n}\nvec3 ReinhardToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( color / ( vec3( 1.0 ) + color ) );\n}\n#define Uncharted2Helper( x ) max( ( ( x * ( 0.15 * x + 0.10 * 0.50 ) + 0.20 * 0.02 ) / ( x * ( 0.15 * x + 0.50 ) + 0.20 * 0.30 ) ) - 0.02 / 0.30, vec3( 0.0 ) )\nvec3 Uncharted2ToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( Uncharted2Helper( color ) / Uncharted2Helper( vec3( toneMappingWhitePoint ) ) );\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}\n", -uv_pars_fragment:"#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvarying vec2 vUv;\n#endif",uv_pars_vertex:"#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvarying vec2 vUv;\n\tuniform vec4 offsetRepeat;\n#endif\n", -uv_vertex:"#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvUv = uv * offsetRepeat.zw + offsetRepeat.xy;\n#endif",uv2_pars_fragment:"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvarying vec2 vUv2;\n#endif",uv2_pars_vertex:"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tattribute vec2 uv2;\n\tvarying vec2 vUv2;\n#endif", -uv2_vertex:"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvUv2 = uv2;\n#endif",worldpos_vertex:"#if defined( USE_ENVMAP ) || defined( PHONG ) || defined( PHYSICAL ) || defined( LAMBERT ) || defined ( USE_SHADOWMAP )\n\t#ifdef USE_SKINNING\n\t\tvec4 worldPosition = modelMatrix * skinned;\n\t#else\n\t\tvec4 worldPosition = modelMatrix * vec4( transformed, 1.0 );\n\t#endif\n#endif\n",cube_frag:"uniform samplerCube tCube;\nuniform float tFlip;\nuniform float opacity;\nvarying vec3 vWorldPosition;\n#include \nvoid main() {\n\tgl_FragColor = textureCube( tCube, vec3( tFlip * vWorldPosition.x, vWorldPosition.yz ) );\n\tgl_FragColor.a *= opacity;\n}\n", +uv_pars_fragment:"#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvarying vec2 vUv;\n#endif",uv_pars_vertex:"#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvarying vec2 vUv;\n\tuniform mat3 uvTransform;\n#endif\n", +uv_vertex:"#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n#endif",uv2_pars_fragment:"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvarying vec2 vUv2;\n#endif",uv2_pars_vertex:"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tattribute vec2 uv2;\n\tvarying vec2 vUv2;\n#endif", +uv2_vertex:"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvUv2 = uv2;\n#endif",worldpos_vertex:"#if defined( USE_ENVMAP ) || defined( PHONG ) || defined( PHYSICAL ) || defined( LAMBERT ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP )\n\tvec4 worldPosition = modelMatrix * vec4( transformed, 1.0 );\n#endif\n",cube_frag:"uniform samplerCube tCube;\nuniform float tFlip;\nuniform float opacity;\nvarying vec3 vWorldPosition;\nvoid main() {\n\tgl_FragColor = textureCube( tCube, vec3( tFlip * vWorldPosition.x, vWorldPosition.yz ) );\n\tgl_FragColor.a *= opacity;\n}\n", cube_vert:"varying vec3 vWorldPosition;\n#include \nvoid main() {\n\tvWorldPosition = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n}\n",depth_frag:"#if DEPTH_PACKING == 3200\n\tuniform float opacity;\n#endif\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#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#if DEPTH_PACKING == 3200\n\t\tgl_FragColor = vec4( vec3( gl_FragCoord.z ), opacity );\n\t#elif DEPTH_PACKING == 3201\n\t\tgl_FragColor = packDepthToRGBA( gl_FragCoord.z );\n\t#endif\n}\n", -depth_vert:"#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}\n", -distanceRGBA_frag:"uniform vec3 lightPos;\nvarying vec4 vWorldPosition;\n#include \n#include \n#include \nvoid main () {\n\t#include \n\tgl_FragColor = packDepthToRGBA( length( vWorldPosition.xyz - lightPos.xyz ) / 1000.0 );\n}\n",distanceRGBA_vert:"varying vec4 vWorldPosition;\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\tvWorldPosition = worldPosition;\n}\n", -equirect_frag:"uniform sampler2D tEquirect;\nuniform float tFlip;\nvarying vec3 vWorldPosition;\n#include \nvoid main() {\n\tvec3 direction = normalize( vWorldPosition );\n\tvec2 sampleUV;\n\tsampleUV.y = saturate( tFlip * direction.y * -0.5 + 0.5 );\n\tsampleUV.x = atan( direction.z, direction.x ) * RECIPROCAL_PI2 + 0.5;\n\tgl_FragColor = texture2D( tEquirect, sampleUV );\n}\n",equirect_vert:"varying vec3 vWorldPosition;\n#include \nvoid main() {\n\tvWorldPosition = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n}\n", +depth_vert:"#include \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}\n", +distanceRGBA_frag:"#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 \nvoid main () {\n\t#include \n\tvec4 diffuseColor = vec4( 1.0 );\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}\n", +distanceRGBA_vert:"#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}\n", +equirect_frag:"uniform sampler2D tEquirect;\nvarying vec3 vWorldPosition;\n#include \nvoid main() {\n\tvec3 direction = normalize( vWorldPosition );\n\tvec2 sampleUV;\n\tsampleUV.y = asin( clamp( direction.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\tsampleUV.x = atan( direction.z, direction.x ) * RECIPROCAL_PI2 + 0.5;\n\tgl_FragColor = texture2D( tEquirect, sampleUV );\n}\n",equirect_vert:"varying vec3 vWorldPosition;\n#include \nvoid main() {\n\tvWorldPosition = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n}\n", linedashed_frag:"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 \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\toutgoingLight = diffuseColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n}\n", linedashed_vert:"uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvLineDistance = scale * lineDistance;\n\tvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\n\tgl_Position = projectionMatrix * mvPosition;\n\t#include \n\t#include \n\t#include \n}\n", -meshbasic_frag:"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 \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\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\treflectedLight.indirectDiffuse += texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\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\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n}\n", +meshbasic_frag:"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 \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\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\treflectedLight.indirectDiffuse += texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\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\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n}\n", meshbasic_vert:"#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#ifdef USE_ENVMAP\n\t#include \n\t#include \n\t#include \n\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}\n", -meshlambert_frag:"uniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\nvarying vec3 vLightFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\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 \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\treflectedLight.indirectDiffuse = getAmbientLightIrradiance( ambientLightColor );\n\t#include \n\treflectedLight.indirectDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb );\n\t#ifdef DOUBLE_SIDED\n\t\treflectedLight.directDiffuse = ( gl_FrontFacing ) ? vLightFront : vLightBack;\n\t#else\n\t\treflectedLight.directDiffuse = vLightFront;\n\t#endif\n\treflectedLight.directDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb ) * getShadowMask();\n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\t#include \n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n", +meshlambert_frag:"uniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\nvarying vec3 vLightFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\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 \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\treflectedLight.indirectDiffuse = getAmbientLightIrradiance( ambientLightColor );\n\t#include \n\treflectedLight.indirectDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb );\n\t#ifdef DOUBLE_SIDED\n\t\treflectedLight.directDiffuse = ( gl_FrontFacing ) ? vLightFront : vLightBack;\n\t#else\n\t\treflectedLight.directDiffuse = vLightFront;\n\t#endif\n\treflectedLight.directDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb ) * getShadowMask();\n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n", meshlambert_vert:"#define LAMBERT\nvarying vec3 vLightFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\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 \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\t#include \n\t#include \n\t#include \n}\n", -meshphong_frag:"#define PHONG\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;\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 \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\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\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\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include \n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n", -meshphong_vert:"#define PHONG\nvarying vec3 vViewPosition;\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 \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#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\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}\n", -meshphysical_frag:"#define PHYSICAL\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifndef STANDARD\n\tuniform float clearCoat;\n\tuniform float clearCoatRoughness;\n#endif\nvarying vec3 vViewPosition;\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 \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\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\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\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n", -meshphysical_vert:"#define PHYSICAL\nvarying vec3 vViewPosition;\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 \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#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\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}\n", -normal_frag:"#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\tgl_FragColor = vec4( packNormalToRGB( normal ), opacity );\n}\n", -normal_vert:"#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\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#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}\n", +meshphong_frag:"#define PHONG\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;\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 \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\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\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\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include \n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n", +meshphong_vert:"#define PHONG\nvarying vec3 vViewPosition;\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 \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#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\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}\n", +meshphysical_frag:"#define PHYSICAL\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifndef STANDARD\n\tuniform float clearCoat;\n\tuniform float clearCoatRoughness;\n#endif\nvarying vec3 vViewPosition;\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 \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\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\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\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n", +meshphysical_vert:"#define PHYSICAL\nvarying vec3 vViewPosition;\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 \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#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\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}\n", +normal_frag:"#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\tgl_FragColor = vec4( packNormalToRGB( normal ), opacity );\n}\n", +normal_vert:"#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\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#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}\n", points_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n}\n", points_vert:"uniform float size;\nuniform float scale;\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#ifdef USE_SIZEATTENUATION\n\t\tgl_PointSize = size * ( scale / - mvPosition.z );\n\t#else\n\t\tgl_PointSize = size;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n", -shadow_frag:"uniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tgl_FragColor = vec4( 0.0, 0.0, 0.0, opacity * ( 1.0 - getShadowMask() ) );\n}\n",shadow_vert:"#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n}\n"},ab={basic:{uniforms:Ha.merge([U.common, -U.aomap,U.lightmap,U.fog]),vertexShader:T.meshbasic_vert,fragmentShader:T.meshbasic_frag},lambert:{uniforms:Ha.merge([U.common,U.aomap,U.lightmap,U.emissivemap,U.fog,U.lights,{emissive:{value:new H(0)}}]),vertexShader:T.meshlambert_vert,fragmentShader:T.meshlambert_frag},phong:{uniforms:Ha.merge([U.common,U.aomap,U.lightmap,U.emissivemap,U.bumpmap,U.normalmap,U.displacementmap,U.gradientmap,U.fog,U.lights,{emissive:{value:new H(0)},specular:{value:new H(1118481)},shininess:{value:30}}]),vertexShader:T.meshphong_vert, -fragmentShader:T.meshphong_frag},standard:{uniforms:Ha.merge([U.common,U.aomap,U.lightmap,U.emissivemap,U.bumpmap,U.normalmap,U.displacementmap,U.roughnessmap,U.metalnessmap,U.fog,U.lights,{emissive:{value:new H(0)},roughness:{value:.5},metalness:{value:.5},envMapIntensity:{value:1}}]),vertexShader:T.meshphysical_vert,fragmentShader:T.meshphysical_frag},points:{uniforms:Ha.merge([U.points,U.fog]),vertexShader:T.points_vert,fragmentShader:T.points_frag},dashed:{uniforms:Ha.merge([U.common,U.fog,{scale:{value:1}, -dashSize:{value:1},totalSize:{value:2}}]),vertexShader:T.linedashed_vert,fragmentShader:T.linedashed_frag},depth:{uniforms:Ha.merge([U.common,U.displacementmap]),vertexShader:T.depth_vert,fragmentShader:T.depth_frag},normal:{uniforms:Ha.merge([U.common,U.bumpmap,U.normalmap,U.displacementmap,{opacity:{value:1}}]),vertexShader:T.normal_vert,fragmentShader:T.normal_frag},cube:{uniforms:{tCube:{value:null},tFlip:{value:-1},opacity:{value:1}},vertexShader:T.cube_vert,fragmentShader:T.cube_frag},equirect:{uniforms:{tEquirect:{value:null}, -tFlip:{value:-1}},vertexShader:T.equirect_vert,fragmentShader:T.equirect_frag},distanceRGBA:{uniforms:{lightPos:{value:new p}},vertexShader:T.distanceRGBA_vert,fragmentShader:T.distanceRGBA_frag}};ab.physical={uniforms:Ha.merge([ab.standard.uniforms,{clearCoat:{value:0},clearCoatRoughness:{value:0}}]),vertexShader:T.meshphysical_vert,fragmentShader:T.meshphysical_frag};Object.assign(id.prototype,{set:function(a,b){this.min.copy(a);this.max.copy(b);return this},setFromPoints:function(a){this.makeEmpty(); -for(var b=0,c=a.length;bthis.max.x||a.ythis.max.y?!1:!0},containsBox:function(a){return this.min.x<=a.min.x&&a.max.x<=this.max.x&&this.min.y<=a.min.y&&a.max.y<=this.max.y},getParameter:function(a,b){return(b||new E).set((a.x-this.min.x)/(this.max.x-this.min.x),(a.y-this.min.y)/(this.max.y-this.min.y))},intersectsBox:function(a){return a.max.xthis.max.x||a.max.ythis.max.y?!1:!0},clampPoint:function(a,b){return(b||new E).copy(a).clamp(this.min,this.max)}, -distanceToPoint:function(){var a=new E;return function(b){return a.copy(b).clamp(this.min,this.max).sub(b).length()}}(),intersect:function(a){this.min.max(a.min);this.max.min(a.max);return this},union:function(a){this.min.min(a.min);this.max.max(a.max);return this},translate:function(a){this.min.add(a);this.max.add(a);return this},equals:function(a){return a.min.equals(this.min)&&a.max.equals(this.max)}});var Kf=0;Object.assign(Z.prototype,sa.prototype,{isMaterial:!0,setValues:function(a){if(void 0!== -a)for(var b in a){var c=a[b];if(void 0===c)console.warn("THREE.Material: '"+b+"' parameter is undefined.");else{var d=this[b];void 0===d?console.warn("THREE."+this.type+": '"+b+"' is not a property of this material."):d&&d.isColor?d.set(c):d&&d.isVector3&&c&&c.isVector3?d.copy(c):this[b]="overdraw"===b?Number(c):c}}},toJSON:function(a){function b(a){var b=[],c;for(c in a){var d=a[c];delete d.metadata;b.push(d)}return b}var c=void 0===a;c&&(a={textures:{},images:{}});var d={metadata:{version:4.5,type:"Material", -generator:"Material.toJSON"}};d.uuid=this.uuid;d.type=this.type;""!==this.name&&(d.name=this.name);this.color&&this.color.isColor&&(d.color=this.color.getHex());void 0!==this.roughness&&(d.roughness=this.roughness);void 0!==this.metalness&&(d.metalness=this.metalness);this.emissive&&this.emissive.isColor&&(d.emissive=this.emissive.getHex());this.specular&&this.specular.isColor&&(d.specular=this.specular.getHex());void 0!==this.shininess&&(d.shininess=this.shininess);void 0!==this.clearCoat&&(d.clearCoat= -this.clearCoat);void 0!==this.clearCoatRoughness&&(d.clearCoatRoughness=this.clearCoatRoughness);this.map&&this.map.isTexture&&(d.map=this.map.toJSON(a).uuid);this.alphaMap&&this.alphaMap.isTexture&&(d.alphaMap=this.alphaMap.toJSON(a).uuid);this.lightMap&&this.lightMap.isTexture&&(d.lightMap=this.lightMap.toJSON(a).uuid);this.bumpMap&&this.bumpMap.isTexture&&(d.bumpMap=this.bumpMap.toJSON(a).uuid,d.bumpScale=this.bumpScale);this.normalMap&&this.normalMap.isTexture&&(d.normalMap=this.normalMap.toJSON(a).uuid, -d.normalScale=this.normalScale.toArray());this.displacementMap&&this.displacementMap.isTexture&&(d.displacementMap=this.displacementMap.toJSON(a).uuid,d.displacementScale=this.displacementScale,d.displacementBias=this.displacementBias);this.roughnessMap&&this.roughnessMap.isTexture&&(d.roughnessMap=this.roughnessMap.toJSON(a).uuid);this.metalnessMap&&this.metalnessMap.isTexture&&(d.metalnessMap=this.metalnessMap.toJSON(a).uuid);this.emissiveMap&&this.emissiveMap.isTexture&&(d.emissiveMap=this.emissiveMap.toJSON(a).uuid); -this.specularMap&&this.specularMap.isTexture&&(d.specularMap=this.specularMap.toJSON(a).uuid);this.envMap&&this.envMap.isTexture&&(d.envMap=this.envMap.toJSON(a).uuid,d.reflectivity=this.reflectivity);this.gradientMap&&this.gradientMap.isTexture&&(d.gradientMap=this.gradientMap.toJSON(a).uuid);void 0!==this.size&&(d.size=this.size);void 0!==this.sizeAttenuation&&(d.sizeAttenuation=this.sizeAttenuation);1!==this.blending&&(d.blending=this.blending);2!==this.shading&&(d.shading=this.shading);0!==this.side&& -(d.side=this.side);0!==this.vertexColors&&(d.vertexColors=this.vertexColors);1>this.opacity&&(d.opacity=this.opacity);!0===this.transparent&&(d.transparent=this.transparent);d.depthFunc=this.depthFunc;d.depthTest=this.depthTest;d.depthWrite=this.depthWrite;0e&&(e=m);l>f&&(f=l);q>g&&(g=q)}this.min.set(b,c,d);this.max.set(e, -f,g);return this},setFromBufferAttribute:function(a){for(var b=Infinity,c=Infinity,d=Infinity,e=-Infinity,f=-Infinity,g=-Infinity,h=0,k=a.count;he&&(e=m);l>f&&(f=l);q>g&&(g=q)}this.min.set(b,c,d);this.max.set(e,f,g);return this},setFromPoints:function(a){this.makeEmpty();for(var b=0,c=a.length;bthis.max.x||a.ythis.max.y||a.zthis.max.z?!1:!0},containsBox:function(a){return this.min.x<= -a.min.x&&a.max.x<=this.max.x&&this.min.y<=a.min.y&&a.max.y<=this.max.y&&this.min.z<=a.min.z&&a.max.z<=this.max.z},getParameter:function(a,b){return(b||new p).set((a.x-this.min.x)/(this.max.x-this.min.x),(a.y-this.min.y)/(this.max.y-this.min.y),(a.z-this.min.z)/(this.max.z-this.min.z))},intersectsBox:function(a){return a.max.xthis.max.x||a.max.ythis.max.y||a.max.zthis.max.z?!1:!0},intersectsSphere:function(){var a=new p;return function(b){this.clampPoint(b.center, -a);return a.distanceToSquared(b.center)<=b.radius*b.radius}}(),intersectsPlane:function(a){var b,c;0=a.constant},clampPoint:function(a, -b){return(b||new p).copy(a).clamp(this.min,this.max)},distanceToPoint:function(){var a=new p;return function(b){return a.copy(b).clamp(this.min,this.max).sub(b).length()}}(),getBoundingSphere:function(){var a=new p;return function(b){b=b||new Ga;this.getCenter(b.center);b.radius=.5*this.getSize(a).length();return b}}(),intersect:function(a){this.min.max(a.min);this.max.min(a.max);this.isEmpty()&&this.makeEmpty();return this},union:function(a){this.min.min(a.min);this.max.max(a.max);return this},applyMatrix4:function(){var a= -[new p,new p,new p,new p,new p,new p,new p,new p];return function(b){if(this.isEmpty())return this;a[0].set(this.min.x,this.min.y,this.min.z).applyMatrix4(b);a[1].set(this.min.x,this.min.y,this.max.z).applyMatrix4(b);a[2].set(this.min.x,this.max.y,this.min.z).applyMatrix4(b);a[3].set(this.min.x,this.max.y,this.max.z).applyMatrix4(b);a[4].set(this.max.x,this.min.y,this.min.z).applyMatrix4(b);a[5].set(this.max.x,this.min.y,this.max.z).applyMatrix4(b);a[6].set(this.max.x,this.max.y,this.min.z).applyMatrix4(b); -a[7].set(this.max.x,this.max.y,this.max.z).applyMatrix4(b);this.setFromPoints(a);return this}}(),translate:function(a){this.min.add(a);this.max.add(a);return this},equals:function(a){return a.min.equals(this.min)&&a.max.equals(this.max)}});Object.assign(Ga.prototype,{set:function(a,b){this.center.copy(a);this.radius=b;return this},setFromPoints:function(){var a=new Ta;return function(b,c){var d=this.center;void 0!==c?d.copy(c):a.setFromPoints(b).getCenter(d);for(var e=0,f=0,g=b.length;f=this.radius},containsPoint:function(a){return a.distanceToSquared(this.center)<=this.radius*this.radius},distanceToPoint:function(a){return a.distanceTo(this.center)-this.radius},intersectsSphere:function(a){var b=this.radius+a.radius;return a.center.distanceToSquared(this.center)<= -b*b},intersectsBox:function(a){return a.intersectsSphere(this)},intersectsPlane:function(a){return Math.abs(this.center.dot(a.normal)-a.constant)<=this.radius},clampPoint:function(a,b){var c=this.center.distanceToSquared(a),d=b||new p;d.copy(a);c>this.radius*this.radius&&(d.sub(this.center).normalize(),d.multiplyScalar(this.radius).add(this.center));return d},getBoundingBox:function(a){a=a||new Ta;a.set(this.center,this.center);a.expandByScalar(this.radius);return a},applyMatrix4:function(a){this.center.applyMatrix4(a); -this.radius*=a.getMaxScaleOnAxis();return this},translate:function(a){this.center.add(a);return this},equals:function(a){return a.center.equals(this.center)&&a.radius===this.radius}});Object.assign(Ka.prototype,{isMatrix3:!0,set:function(a,b,c,d,e,f,g,h,k){var m=this.elements;m[0]=a;m[1]=d;m[2]=g;m[3]=b;m[4]=e;m[5]=h;m[6]=c;m[7]=f;m[8]=k;return this},identity:function(){this.set(1,0,0,0,1,0,0,0,1);return this},clone:function(){return(new this.constructor).fromArray(this.elements)},copy:function(a){var b= -this.elements;a=a.elements;b[0]=a[0];b[1]=a[1];b[2]=a[2];b[3]=a[3];b[4]=a[4];b[5]=a[5];b[6]=a[6];b[7]=a[7];b[8]=a[8];return this},setFromMatrix4:function(a){a=a.elements;this.set(a[0],a[4],a[8],a[1],a[5],a[9],a[2],a[6],a[10]);return this},applyToBufferAttribute:function(){var a=new p;return function(b){for(var c=0,d=b.count;cc;c++)if(b[c]!==a[c])return!1;return!0},fromArray:function(a,b){void 0===b&&(b=0);for(var c=0;9>c;c++)this.elements[c]=a[c+b];return this},toArray:function(a,b){void 0===a&&(a=[]);void 0===b&&(b=0);var c=this.elements;a[b]=c[0];a[b+1]=c[1];a[b+2]=c[2];a[b+3]=c[3];a[b+4]=c[4];a[b+5]=c[5];a[b+6]=c[6];a[b+7]=c[7];a[b+8]= -c[8];return a}});Object.assign(wa.prototype,{set:function(a,b){this.normal.copy(a);this.constant=b;return this},setComponents:function(a,b,c,d){this.normal.set(a,b,c);this.constant=d;return this},setFromNormalAndCoplanarPoint:function(a,b){this.normal.copy(a);this.constant=-b.dot(this.normal);return this},setFromCoplanarPoints:function(){var a=new p,b=new p;return function(c,d,e){d=a.subVectors(e,d).cross(b.subVectors(c,d)).normalize();this.setFromNormalAndCoplanarPoint(d,c);return this}}(),clone:function(){return(new this.constructor).copy(this)}, -copy:function(a){this.normal.copy(a.normal);this.constant=a.constant;return this},normalize:function(){var a=1/this.normal.length();this.normal.multiplyScalar(a);this.constant*=a;return this},negate:function(){this.constant*=-1;this.normal.negate();return this},distanceToPoint:function(a){return this.normal.dot(a)+this.constant},distanceToSphere:function(a){return this.distanceToPoint(a.center)-a.radius},projectPoint:function(a,b){return this.orthoPoint(a,b).sub(a).negate()},orthoPoint:function(a, -b){var c=this.distanceToPoint(a);return(b||new p).copy(this.normal).multiplyScalar(c)},intersectLine:function(){var a=new p;return function(b,c){var d=c||new p,e=b.delta(a),f=this.normal.dot(e);if(0===f){if(0===this.distanceToPoint(b.start))return d.copy(b.start)}else return f=-(b.start.dot(this.normal)+this.constant)/f,0>f||1b&&0a&&0c;c++)b[c].copy(a.planes[c]);return this},setFromMatrix:function(a){var b=this.planes,c=a.elements;a=c[0];var d=c[1],e=c[2],f=c[3],g=c[4],h=c[5],k=c[6],m=c[7],l=c[8],q=c[9],n=c[10],t=c[11],p=c[12],r=c[13], -x=c[14],c=c[15];b[0].setComponents(f-a,m-g,t-l,c-p).normalize();b[1].setComponents(f+a,m+g,t+l,c+p).normalize();b[2].setComponents(f+d,m+h,t+q,c+r).normalize();b[3].setComponents(f-d,m-h,t-q,c-r).normalize();b[4].setComponents(f-e,m-k,t-n,c-x).normalize();b[5].setComponents(f+e,m+k,t+n,c+x).normalize();return this},intersectsObject:function(){var a=new Ga;return function(b){var c=b.geometry;null===c.boundingSphere&&c.computeBoundingSphere();a.copy(c.boundingSphere).applyMatrix4(b.matrixWorld);return this.intersectsSphere(a)}}(), -intersectsSprite:function(){var a=new Ga;return function(b){a.center.set(0,0,0);a.radius=.7071067811865476;a.applyMatrix4(b.matrixWorld);return this.intersectsSphere(a)}}(),intersectsSphere:function(a){var b=this.planes,c=a.center;a=-a.radius;for(var d=0;6>d;d++)if(b[d].distanceToPoint(c)e;e++){var f=d[e];a.x=0g&&0>f)return!1}return!0}}(),containsPoint:function(a){for(var b=this.planes,c=0;6>c;c++)if(0>b[c].distanceToPoint(a))return!1;return!0}});Object.assign(hb.prototype,{set:function(a,b){this.origin.copy(a);this.direction.copy(b);return this},clone:function(){return(new this.constructor).copy(this)},copy:function(a){this.origin.copy(a.origin); -this.direction.copy(a.direction);return this},at:function(a,b){return(b||new p).copy(this.direction).multiplyScalar(a).add(this.origin)},lookAt:function(a){this.direction.copy(a).sub(this.origin).normalize();return this},recast:function(){var a=new p;return function(b){this.origin.copy(this.at(b,a));return this}}(),closestPointToPoint:function(a,b){var c=b||new p;c.subVectors(a,this.origin);var d=c.dot(this.direction);return 0>d?c.copy(this.origin):c.copy(this.direction).multiplyScalar(d).add(this.origin)}, -distanceToPoint:function(a){return Math.sqrt(this.distanceSqToPoint(a))},distanceSqToPoint:function(){var a=new p;return function(b){var c=a.subVectors(b,this.origin).dot(this.direction);if(0>c)return this.origin.distanceToSquared(b);a.copy(this.direction).multiplyScalar(c).add(this.origin);return a.distanceToSquared(b)}}(),distanceSqToSegment:function(){var a=new p,b=new p,c=new p;return function(d,e,f,g){a.copy(d).add(e).multiplyScalar(.5);b.copy(e).sub(d).normalize();c.copy(this.origin).sub(a); -var h=.5*d.distanceTo(e),k=-this.direction.dot(b),m=c.dot(this.direction),l=-c.dot(b),q=c.lengthSq(),n=Math.abs(1-k*k),t;0=-t?e<=t?(h=1/n,d*=h,e*=h,k=d*(d+k*e+2*m)+e*(k*d+e+2*l)+q):(e=h,d=Math.max(0,-(k*e+m)),k=-d*d+e*(e+2*l)+q):(e=-h,d=Math.max(0,-(k*e+m)),k=-d*d+e*(e+2*l)+q):e<=-t?(d=Math.max(0,-(-k*h+m)),e=0f)return null;f=Math.sqrt(f-e);e=d-f;d+=f;return 0>e&&0>d?null:0>e?this.at(d,c):this.at(e,c)}}(),intersectsSphere:function(a){return this.distanceToPoint(a.center)<= -a.radius},distanceToPlane:function(a){var b=a.normal.dot(this.direction);if(0===b)return 0===a.distanceToPoint(this.origin)?0:null;a=-(this.origin.dot(a.normal)+a.constant)/b;return 0<=a?a:null},intersectPlane:function(a,b){var c=this.distanceToPlane(a);return null===c?null:this.at(c,b)},intersectsPlane:function(a){var b=a.distanceToPoint(this.origin);return 0===b||0>a.normal.dot(this.direction)*b?!0:!1},intersectBox:function(a,b){var c,d,e,f,g;d=1/this.direction.x;f=1/this.direction.y;g=1/this.direction.z; -var h=this.origin;0<=d?(c=(a.min.x-h.x)*d,d*=a.max.x-h.x):(c=(a.max.x-h.x)*d,d*=a.min.x-h.x);0<=f?(e=(a.min.y-h.y)*f,f*=a.max.y-h.y):(e=(a.max.y-h.y)*f,f*=a.min.y-h.y);if(c>f||e>d)return null;if(e>c||c!==c)c=e;if(fg||e>d)return null;if(e>c||c!==c)c=e;if(gd?null:this.at(0<=c?c:d,b)},intersectsBox:function(){var a=new p;return function(b){return null!==this.intersectBox(b,a)}}(),intersectTriangle:function(){var a= -new p,b=new p,c=new p,d=new p;return function(e,f,g,h,k){b.subVectors(f,e);c.subVectors(g,e);d.crossVectors(b,c);f=this.direction.dot(d);if(0f)h=-1,f=-f;else return null;a.subVectors(this.origin,e);e=h*this.direction.dot(c.crossVectors(a,c));if(0>e)return null;g=h*this.direction.dot(b.cross(a));if(0>g||e+g>f)return null;e=-h*a.dot(d);return 0>e?null:this.at(e/f,k)}}(),applyMatrix4:function(a){this.direction.add(this.origin).applyMatrix4(a);this.origin.applyMatrix4(a); -this.direction.sub(this.origin);this.direction.normalize();return this},equals:function(a){return a.origin.equals(this.origin)&&a.direction.equals(this.direction)}});bb.RotationOrders="XYZ YZX ZXY XZY YXZ ZYX".split(" ");bb.DefaultOrder="XYZ";Object.defineProperties(bb.prototype,{x:{get:function(){return this._x},set:function(a){this._x=a;this.onChangeCallback()}},y:{get:function(){return this._y},set:function(a){this._y=a;this.onChangeCallback()}},z:{get:function(){return this._z},set:function(a){this._z= -a;this.onChangeCallback()}},order:{get:function(){return this._order},set:function(a){this._order=a;this.onChangeCallback()}}});Object.assign(bb.prototype,{isEuler:!0,set:function(a,b,c,d){this._x=a;this._y=b;this._z=c;this._order=d||this._order;this.onChangeCallback();return this},clone:function(){return new this.constructor(this._x,this._y,this._z,this._order)},copy:function(a){this._x=a._x;this._y=a._y;this._z=a._z;this._order=a._order;this.onChangeCallback();return this},setFromRotationMatrix:function(a, -b,c){var d=Y.clamp,e=a.elements;a=e[0];var f=e[4],g=e[8],h=e[1],k=e[5],m=e[9],l=e[2],q=e[6],e=e[10];b=b||this._order;"XYZ"===b?(this._y=Math.asin(d(g,-1,1)),.99999>Math.abs(g)?(this._x=Math.atan2(-m,e),this._z=Math.atan2(-f,a)):(this._x=Math.atan2(q,k),this._z=0)):"YXZ"===b?(this._x=Math.asin(-d(m,-1,1)),.99999>Math.abs(m)?(this._y=Math.atan2(g,e),this._z=Math.atan2(h,k)):(this._y=Math.atan2(-l,a),this._z=0)):"ZXY"===b?(this._x=Math.asin(d(q,-1,1)),.99999>Math.abs(q)?(this._y=Math.atan2(-l,e),this._z= -Math.atan2(-f,k)):(this._y=0,this._z=Math.atan2(h,a))):"ZYX"===b?(this._y=Math.asin(-d(l,-1,1)),.99999>Math.abs(l)?(this._x=Math.atan2(q,e),this._z=Math.atan2(h,a)):(this._x=0,this._z=Math.atan2(-f,k))):"YZX"===b?(this._z=Math.asin(d(h,-1,1)),.99999>Math.abs(h)?(this._x=Math.atan2(-m,k),this._y=Math.atan2(-l,a)):(this._x=0,this._y=Math.atan2(g,e))):"XZY"===b?(this._z=Math.asin(-d(f,-1,1)),.99999>Math.abs(f)?(this._x=Math.atan2(q,k),this._y=Math.atan2(g,a)):(this._x=Math.atan2(-m,e),this._y=0)):console.warn("THREE.Euler: .setFromRotationMatrix() given unsupported order: "+ -b);this._order=b;if(!1!==c)this.onChangeCallback();return this},setFromQuaternion:function(){var a=new J;return function(b,c,d){a.makeRotationFromQuaternion(b);return this.setFromRotationMatrix(a,c,d)}}(),setFromVector3:function(a,b){return this.set(a.x,a.y,a.z,b||this._order)},reorder:function(){var a=new qa;return function(b){a.setFromEuler(this);return this.setFromQuaternion(a,b)}}(),equals:function(a){return a._x===this._x&&a._y===this._y&&a._z===this._z&&a._order===this._order},fromArray:function(a){this._x= -a[0];this._y=a[1];this._z=a[2];void 0!==a[3]&&(this._order=a[3]);this.onChangeCallback();return this},toArray:function(a,b){void 0===a&&(a=[]);void 0===b&&(b=0);a[b]=this._x;a[b+1]=this._y;a[b+2]=this._z;a[b+3]=this._order;return a},toVector3:function(a){return a?a.set(this._x,this._y,this._z):new p(this._x,this._y,this._z)},onChange:function(a){this.onChangeCallback=a;return this},onChangeCallback:function(){}});Object.assign(Rd.prototype,{set:function(a){this.mask=1<=b.x+b.y}}()});Object.assign(Ua.prototype,{set:function(a,b,c){this.a.copy(a);this.b.copy(b);this.c.copy(c);return this},setFromPointsAndIndices:function(a,b,c,d){this.a.copy(a[b]);this.b.copy(a[c]);this.c.copy(a[d]);return this},clone:function(){return(new this.constructor).copy(this)},copy:function(a){this.a.copy(a.a);this.b.copy(a.b);this.c.copy(a.c);return this},area:function(){var a=new p,b=new p;return function(){a.subVectors(this.c,this.b);b.subVectors(this.a,this.b); -return.5*a.cross(b).length()}}(),midpoint:function(a){return(a||new p).addVectors(this.a,this.b).add(this.c).multiplyScalar(1/3)},normal:function(a){return Ua.normal(this.a,this.b,this.c,a)},plane:function(a){return(a||new wa).setFromCoplanarPoints(this.a,this.b,this.c)},barycoordFromPoint:function(a,b){return Ua.barycoordFromPoint(a,this.a,this.b,this.c,b)},containsPoint:function(a){return Ua.containsPoint(a,this.a,this.b,this.c)},closestPointToPoint:function(){var a=new wa,b=[new Hb,new Hb,new Hb], -c=new p,d=new p;return function(e,f){var g=f||new p,h=Infinity;a.setFromCoplanarPoints(this.a,this.b,this.c);a.projectPoint(e,c);if(!0===this.containsPoint(c))g.copy(c);else{b[0].set(this.a,this.b);b[1].set(this.b,this.c);b[2].set(this.c,this.a);for(var k=0;kd;d++)if(e[d]===e[(d+1)%3]){a.push(f);break}for(f=a.length-1;0<=f;f--)for(e=a[f],this.faces.splice(e,1),c=0,g=this.faceVertexUvs.length;c\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tgl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\n\t#include \n}\n",shadow_vert:"#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n"}, +jb={basic:{uniforms:Ca.merge([B.common,B.specularmap,B.envmap,B.aomap,B.lightmap,B.fog]),vertexShader:S.meshbasic_vert,fragmentShader:S.meshbasic_frag},lambert:{uniforms:Ca.merge([B.common,B.specularmap,B.envmap,B.aomap,B.lightmap,B.emissivemap,B.fog,B.lights,{emissive:{value:new H(0)}}]),vertexShader:S.meshlambert_vert,fragmentShader:S.meshlambert_frag},phong:{uniforms:Ca.merge([B.common,B.specularmap,B.envmap,B.aomap,B.lightmap,B.emissivemap,B.bumpmap,B.normalmap,B.displacementmap,B.gradientmap, +B.fog,B.lights,{emissive:{value:new H(0)},specular:{value:new H(1118481)},shininess:{value:30}}]),vertexShader:S.meshphong_vert,fragmentShader:S.meshphong_frag},standard:{uniforms:Ca.merge([B.common,B.envmap,B.aomap,B.lightmap,B.emissivemap,B.bumpmap,B.normalmap,B.displacementmap,B.roughnessmap,B.metalnessmap,B.fog,B.lights,{emissive:{value:new H(0)},roughness:{value:.5},metalness:{value:.5},envMapIntensity:{value:1}}]),vertexShader:S.meshphysical_vert,fragmentShader:S.meshphysical_frag},points:{uniforms:Ca.merge([B.points, +B.fog]),vertexShader:S.points_vert,fragmentShader:S.points_frag},dashed:{uniforms:Ca.merge([B.common,B.fog,{scale:{value:1},dashSize:{value:1},totalSize:{value:2}}]),vertexShader:S.linedashed_vert,fragmentShader:S.linedashed_frag},depth:{uniforms:Ca.merge([B.common,B.displacementmap]),vertexShader:S.depth_vert,fragmentShader:S.depth_frag},normal:{uniforms:Ca.merge([B.common,B.bumpmap,B.normalmap,B.displacementmap,{opacity:{value:1}}]),vertexShader:S.normal_vert,fragmentShader:S.normal_frag},cube:{uniforms:{tCube:{value:null}, +tFlip:{value:-1},opacity:{value:1}},vertexShader:S.cube_vert,fragmentShader:S.cube_frag},equirect:{uniforms:{tEquirect:{value:null}},vertexShader:S.equirect_vert,fragmentShader:S.equirect_frag},distanceRGBA:{uniforms:Ca.merge([B.common,B.displacementmap,{referencePosition:{value:new p},nearDistance:{value:1},farDistance:{value:1E3}}]),vertexShader:S.distanceRGBA_vert,fragmentShader:S.distanceRGBA_frag},shadow:{uniforms:Ca.merge([B.lights,B.fog,{color:{value:new H(0)},opacity:{value:1}}]),vertexShader:S.shadow_vert, +fragmentShader:S.shadow_frag}};jb.physical={uniforms:Ca.merge([jb.standard.uniforms,{clearCoat:{value:0},clearCoatRoughness:{value:0}}]),vertexShader:S.meshphysical_vert,fragmentShader:S.meshphysical_frag};Object.assign(jd.prototype,{set:function(a,b){this.min.copy(a);this.max.copy(b);return this},setFromPoints:function(a){this.makeEmpty();for(var b=0,c=a.length;bthis.max.x||a.ythis.max.y?!1:!0},containsBox:function(a){return this.min.x<=a.min.x&&a.max.x<=this.max.x&&this.min.y<=a.min.y&&a.max.y<= +this.max.y},getParameter:function(a,b){return(b||new D).set((a.x-this.min.x)/(this.max.x-this.min.x),(a.y-this.min.y)/(this.max.y-this.min.y))},intersectsBox:function(a){return a.max.xthis.max.x||a.max.ythis.max.y?!1:!0},clampPoint:function(a,b){return(b||new D).copy(a).clamp(this.min,this.max)},distanceToPoint:function(){var a=new D;return function(b){return a.copy(b).clamp(this.min,this.max).sub(b).length()}}(),intersect:function(a){this.min.max(a.min); +this.max.min(a.max);return this},union:function(a){this.min.min(a.min);this.max.max(a.max);return this},translate:function(a){this.min.add(a);this.max.add(a);return this},equals:function(a){return a.min.equals(this.min)&&a.max.equals(this.max)}});pc.prototype=Object.create(O.prototype);pc.prototype.constructor=pc;var Lf=0;Object.assign(P.prototype,sa.prototype,{isMaterial:!0,onBeforeCompile:function(){},setValues:function(a){if(void 0!==a)for(var b in a){var c=a[b];if(void 0===c)console.warn("THREE.Material: '"+ +b+"' parameter is undefined.");else if("shading"===b)console.warn("THREE."+this.type+": .shading has been removed. Use the boolean .flatShading instead."),this.flatShading=1===c?!0:!1;else{var d=this[b];void 0===d?console.warn("THREE."+this.type+": '"+b+"' is not a property of this material."):d&&d.isColor?d.set(c):d&&d.isVector3&&c&&c.isVector3?d.copy(c):this[b]="overdraw"===b?Number(c):c}}},toJSON:function(a){function b(a){var b=[],c;for(c in a){var d=a[c];delete d.metadata;b.push(d)}return b}var c= +void 0===a;c&&(a={textures:{},images:{}});var d={metadata:{version:4.5,type:"Material",generator:"Material.toJSON"}};d.uuid=this.uuid;d.type=this.type;""!==this.name&&(d.name=this.name);this.color&&this.color.isColor&&(d.color=this.color.getHex());void 0!==this.roughness&&(d.roughness=this.roughness);void 0!==this.metalness&&(d.metalness=this.metalness);this.emissive&&this.emissive.isColor&&(d.emissive=this.emissive.getHex());this.specular&&this.specular.isColor&&(d.specular=this.specular.getHex()); +void 0!==this.shininess&&(d.shininess=this.shininess);void 0!==this.clearCoat&&(d.clearCoat=this.clearCoat);void 0!==this.clearCoatRoughness&&(d.clearCoatRoughness=this.clearCoatRoughness);this.map&&this.map.isTexture&&(d.map=this.map.toJSON(a).uuid);this.alphaMap&&this.alphaMap.isTexture&&(d.alphaMap=this.alphaMap.toJSON(a).uuid);this.lightMap&&this.lightMap.isTexture&&(d.lightMap=this.lightMap.toJSON(a).uuid);this.bumpMap&&this.bumpMap.isTexture&&(d.bumpMap=this.bumpMap.toJSON(a).uuid,d.bumpScale= +this.bumpScale);this.normalMap&&this.normalMap.isTexture&&(d.normalMap=this.normalMap.toJSON(a).uuid,d.normalScale=this.normalScale.toArray());this.displacementMap&&this.displacementMap.isTexture&&(d.displacementMap=this.displacementMap.toJSON(a).uuid,d.displacementScale=this.displacementScale,d.displacementBias=this.displacementBias);this.roughnessMap&&this.roughnessMap.isTexture&&(d.roughnessMap=this.roughnessMap.toJSON(a).uuid);this.metalnessMap&&this.metalnessMap.isTexture&&(d.metalnessMap=this.metalnessMap.toJSON(a).uuid); +this.emissiveMap&&this.emissiveMap.isTexture&&(d.emissiveMap=this.emissiveMap.toJSON(a).uuid);this.specularMap&&this.specularMap.isTexture&&(d.specularMap=this.specularMap.toJSON(a).uuid);this.envMap&&this.envMap.isTexture&&(d.envMap=this.envMap.toJSON(a).uuid,d.reflectivity=this.reflectivity);this.gradientMap&&this.gradientMap.isTexture&&(d.gradientMap=this.gradientMap.toJSON(a).uuid);void 0!==this.size&&(d.size=this.size);void 0!==this.sizeAttenuation&&(d.sizeAttenuation=this.sizeAttenuation);1!== +this.blending&&(d.blending=this.blending);!0===this.flatShading&&(d.flatShading=this.flatShading);0!==this.side&&(d.side=this.side);0!==this.vertexColors&&(d.vertexColors=this.vertexColors);1>this.opacity&&(d.opacity=this.opacity);!0===this.transparent&&(d.transparent=this.transparent);d.depthFunc=this.depthFunc;d.depthTest=this.depthTest;d.depthWrite=this.depthWrite;!0===this.dithering&&(d.dithering=!0);0e&&(e=l);q>f&&(f=q);n>g&&(g=n)}this.min.set(b,c,d);this.max.set(e,f,g);return this},setFromBufferAttribute:function(a){for(var b=Infinity,c=Infinity,d=Infinity,e=-Infinity,f=-Infinity,g=-Infinity,h=0,k=a.count;he&&(e=l);q>f&&(f=q);n>g&&(g=n)}this.min.set(b,c,d);this.max.set(e,f,g);return this},setFromPoints:function(a){this.makeEmpty();for(var b=0,c=a.length;bthis.max.x||a.ythis.max.y||a.zthis.max.z?!1:!0},containsBox:function(a){return this.min.x<=a.min.x&&a.max.x<=this.max.x&&this.min.y<=a.min.y&&a.max.y<=this.max.y&&this.min.z<=a.min.z&&a.max.z<=this.max.z},getParameter:function(a,b){return(b||new p).set((a.x-this.min.x)/ +(this.max.x-this.min.x),(a.y-this.min.y)/(this.max.y-this.min.y),(a.z-this.min.z)/(this.max.z-this.min.z))},intersectsBox:function(a){return a.max.xthis.max.x||a.max.ythis.max.y||a.max.zthis.max.z?!1:!0},intersectsSphere:function(){var a=new p;return function(b){this.clampPoint(b.center,a);return a.distanceToSquared(b.center)<=b.radius*b.radius}}(),intersectsPlane:function(a){if(0=a.constant},clampPoint:function(a,b){return(b||new p).copy(a).clamp(this.min,this.max)},distanceToPoint:function(){var a=new p;return function(b){return a.copy(b).clamp(this.min, +this.max).sub(b).length()}}(),getBoundingSphere:function(){var a=new p;return function(b){b=b||new ra;this.getCenter(b.center);b.radius=.5*this.getSize(a).length();return b}}(),intersect:function(a){this.min.max(a.min);this.max.min(a.max);this.isEmpty()&&this.makeEmpty();return this},union:function(a){this.min.min(a.min);this.max.max(a.max);return this},applyMatrix4:function(){var a=[new p,new p,new p,new p,new p,new p,new p,new p];return function(b){if(this.isEmpty())return this;a[0].set(this.min.x, +this.min.y,this.min.z).applyMatrix4(b);a[1].set(this.min.x,this.min.y,this.max.z).applyMatrix4(b);a[2].set(this.min.x,this.max.y,this.min.z).applyMatrix4(b);a[3].set(this.min.x,this.max.y,this.max.z).applyMatrix4(b);a[4].set(this.max.x,this.min.y,this.min.z).applyMatrix4(b);a[5].set(this.max.x,this.min.y,this.max.z).applyMatrix4(b);a[6].set(this.max.x,this.max.y,this.min.z).applyMatrix4(b);a[7].set(this.max.x,this.max.y,this.max.z).applyMatrix4(b);this.setFromPoints(a);return this}}(),translate:function(a){this.min.add(a); +this.max.add(a);return this},equals:function(a){return a.min.equals(this.min)&&a.max.equals(this.max)}});Object.assign(ra.prototype,{set:function(a,b){this.center.copy(a);this.radius=b;return this},setFromPoints:function(){var a=new Pa;return function(b,c){var d=this.center;void 0!==c?d.copy(c):a.setFromPoints(b).getCenter(d);for(var e=c=0,f=b.length;e=this.radius},containsPoint:function(a){return a.distanceToSquared(this.center)<=this.radius*this.radius},distanceToPoint:function(a){return a.distanceTo(this.center)-this.radius},intersectsSphere:function(a){var b=this.radius+a.radius;return a.center.distanceToSquared(this.center)<=b*b},intersectsBox:function(a){return a.intersectsSphere(this)},intersectsPlane:function(a){return Math.abs(a.distanceToPoint(this.center))<=this.radius},clampPoint:function(a, +b){var c=this.center.distanceToSquared(a);b=b||new p;b.copy(a);c>this.radius*this.radius&&(b.sub(this.center).normalize(),b.multiplyScalar(this.radius).add(this.center));return b},getBoundingBox:function(a){a=a||new Pa;a.set(this.center,this.center);a.expandByScalar(this.radius);return a},applyMatrix4:function(a){this.center.applyMatrix4(a);this.radius*=a.getMaxScaleOnAxis();return this},translate:function(a){this.center.add(a);return this},equals:function(a){return a.center.equals(this.center)&& +a.radius===this.radius}});Object.assign(za.prototype,{set:function(a,b){this.normal.copy(a);this.constant=b;return this},setComponents:function(a,b,c,d){this.normal.set(a,b,c);this.constant=d;return this},setFromNormalAndCoplanarPoint:function(a,b){this.normal.copy(a);this.constant=-b.dot(this.normal);return this},setFromCoplanarPoints:function(){var a=new p,b=new p;return function(c,d,e){d=a.subVectors(e,d).cross(b.subVectors(c,d)).normalize();this.setFromNormalAndCoplanarPoint(d,c);return this}}(), +clone:function(){return(new this.constructor).copy(this)},copy:function(a){this.normal.copy(a.normal);this.constant=a.constant;return this},normalize:function(){var a=1/this.normal.length();this.normal.multiplyScalar(a);this.constant*=a;return this},negate:function(){this.constant*=-1;this.normal.negate();return this},distanceToPoint:function(a){return this.normal.dot(a)+this.constant},distanceToSphere:function(a){return this.distanceToPoint(a.center)-a.radius},projectPoint:function(a,b){return(b|| +new p).copy(this.normal).multiplyScalar(-this.distanceToPoint(a)).add(a)},intersectLine:function(){var a=new p;return function(b,c){c=c||new p;var d=b.delta(a),e=this.normal.dot(d);if(0===e){if(0===this.distanceToPoint(b.start))return c.copy(b.start)}else if(e=-(b.start.dot(this.normal)+this.constant)/e,!(0>e||1b&&0a&&0c;c++)b[c].copy(a.planes[c]);return this},setFromMatrix:function(a){var b=this.planes,c=a.elements;a=c[0];var d=c[1],e=c[2],f=c[3],g=c[4],h=c[5],k=c[6],l=c[7],q=c[8],n=c[9],m=c[10],r=c[11],p=c[12],t=c[13],w=c[14],c=c[15]; +b[0].setComponents(f-a,l-g,r-q,c-p).normalize();b[1].setComponents(f+a,l+g,r+q,c+p).normalize();b[2].setComponents(f+d,l+h,r+n,c+t).normalize();b[3].setComponents(f-d,l-h,r-n,c-t).normalize();b[4].setComponents(f-e,l-k,r-m,c-w).normalize();b[5].setComponents(f+e,l+k,r+m,c+w).normalize();return this},intersectsObject:function(){var a=new ra;return function(b){var c=b.geometry;null===c.boundingSphere&&c.computeBoundingSphere();a.copy(c.boundingSphere).applyMatrix4(b.matrixWorld);return this.intersectsSphere(a)}}(), +intersectsSprite:function(){var a=new ra;return function(b){a.center.set(0,0,0);a.radius=.7071067811865476;a.applyMatrix4(b.matrixWorld);return this.intersectsSphere(a)}}(),intersectsSphere:function(a){var b=this.planes,c=a.center;a=-a.radius;for(var d=0;6>d;d++)if(b[d].distanceToPoint(c)e;e++){var f=d[e];a.x=0g&&0>f)return!1}return!0}}(),containsPoint:function(a){for(var b=this.planes,c=0;6>c;c++)if(0>b[c].distanceToPoint(a))return!1;return!0}});Za.RotationOrders="XYZ YZX ZXY XZY YXZ ZYX".split(" ");Za.DefaultOrder="XYZ";Object.defineProperties(Za.prototype,{x:{get:function(){return this._x},set:function(a){this._x=a;this.onChangeCallback()}}, +y:{get:function(){return this._y},set:function(a){this._y=a;this.onChangeCallback()}},z:{get:function(){return this._z},set:function(a){this._z=a;this.onChangeCallback()}},order:{get:function(){return this._order},set:function(a){this._order=a;this.onChangeCallback()}}});Object.assign(Za.prototype,{isEuler:!0,set:function(a,b,c,d){this._x=a;this._y=b;this._z=c;this._order=d||this._order;this.onChangeCallback();return this},clone:function(){return new this.constructor(this._x,this._y,this._z,this._order)}, +copy:function(a){this._x=a._x;this._y=a._y;this._z=a._z;this._order=a._order;this.onChangeCallback();return this},setFromRotationMatrix:function(a,b,c){var d=R.clamp,e=a.elements;a=e[0];var f=e[4],g=e[8],h=e[1],k=e[5],l=e[9],q=e[2],n=e[6],e=e[10];b=b||this._order;"XYZ"===b?(this._y=Math.asin(d(g,-1,1)),.99999>Math.abs(g)?(this._x=Math.atan2(-l,e),this._z=Math.atan2(-f,a)):(this._x=Math.atan2(n,k),this._z=0)):"YXZ"===b?(this._x=Math.asin(-d(l,-1,1)),.99999>Math.abs(l)?(this._y=Math.atan2(g,e),this._z= +Math.atan2(h,k)):(this._y=Math.atan2(-q,a),this._z=0)):"ZXY"===b?(this._x=Math.asin(d(n,-1,1)),.99999>Math.abs(n)?(this._y=Math.atan2(-q,e),this._z=Math.atan2(-f,k)):(this._y=0,this._z=Math.atan2(h,a))):"ZYX"===b?(this._y=Math.asin(-d(q,-1,1)),.99999>Math.abs(q)?(this._x=Math.atan2(n,e),this._z=Math.atan2(h,a)):(this._x=0,this._z=Math.atan2(-f,k))):"YZX"===b?(this._z=Math.asin(d(h,-1,1)),.99999>Math.abs(h)?(this._x=Math.atan2(-l,k),this._y=Math.atan2(-q,a)):(this._x=0,this._y=Math.atan2(g,e))):"XZY"=== +b?(this._z=Math.asin(-d(f,-1,1)),.99999>Math.abs(f)?(this._x=Math.atan2(n,k),this._y=Math.atan2(g,a)):(this._x=Math.atan2(-l,e),this._y=0)):console.warn("THREE.Euler: .setFromRotationMatrix() given unsupported order: "+b);this._order=b;if(!1!==c)this.onChangeCallback();return this},setFromQuaternion:function(){var a=new K;return function(b,c,d){a.makeRotationFromQuaternion(b);return this.setFromRotationMatrix(a,c,d)}}(),setFromVector3:function(a,b){return this.set(a.x,a.y,a.z,b||this._order)},reorder:function(){var a= +new fa;return function(b){a.setFromEuler(this);return this.setFromQuaternion(a,b)}}(),equals:function(a){return a._x===this._x&&a._y===this._y&&a._z===this._z&&a._order===this._order},fromArray:function(a){this._x=a[0];this._y=a[1];this._z=a[2];void 0!==a[3]&&(this._order=a[3]);this.onChangeCallback();return this},toArray:function(a,b){void 0===a&&(a=[]);void 0===b&&(b=0);a[b]=this._x;a[b+1]=this._y;a[b+2]=this._z;a[b+3]=this._order;return a},toVector3:function(a){return a?a.set(this._x,this._y,this._z): +new p(this._x,this._y,this._z)},onChange:function(a){this.onChangeCallback=a;return this},onChangeCallback:function(){}});Object.assign(Qd.prototype,{set:function(a){this.mask=1<g;g++)if(d[g]===d[(g+1)%3]){a.push(f);break}for(f=a.length-1;0<=f;f--)for(d=a[f],this.faces.splice(d,1),c=0,e=this.faceVertexUvs.length;cb.far?null:{distance:c,point:y.clone(),object:a}}function c(c,d,e,f,m,l,u,q){g.fromBufferAttribute(f,l);h.fromBufferAttribute(f,u);k.fromBufferAttribute(f,q);if(c=b(c,d,e,g,h,k,x))m&&(n.fromBufferAttribute(m,l),t.fromBufferAttribute(m,u),z.fromBufferAttribute(m,q),c.uv=a(x,g,h,k,n,t,z)),c.face=new Va(l,u,q,Ua.normal(g,h,k)),c.faceIndex=l;return c}var d=new J,e=new hb,f=new Ga,g=new p,h=new p,k= -new p,m=new p,l=new p,q=new p,n=new E,t=new E,z=new E,r=new p,x=new p,y=new p;return function(p,r){var w=this.geometry,y=this.material,D=this.matrixWorld;if(void 0!==y&&(null===w.boundingSphere&&w.computeBoundingSphere(),f.copy(w.boundingSphere),f.applyMatrix4(D),!1!==p.ray.intersectsSphere(f)&&(d.getInverse(D),e.copy(p.ray).applyMatrix4(d),null===w.boundingBox||!1!==e.intersectsBox(w.boundingBox)))){var C;if(w.isBufferGeometry){var G,E,y=w.index,B=w.attributes.position,D=w.attributes.uv,ca,I;if(null!== -y)for(ca=0,I=y.count;caf||(f=d.ray.origin.distanceTo(a),fd.far||e.push({distance:f,point:a.clone(),face:null,object:this}))}}(),clone:function(){return(new this.constructor(this.material)).copy(this)}});Bc.prototype=Object.assign(Object.create(B.prototype),{constructor:Bc,copy:function(a){B.prototype.copy.call(this, -a,!1);a=a.levels;for(var b=0,c=a.length;b=d[e].distance)d[e-1].object.visible=!1,d[e].object.visible=!0;else break;for(;ef||(l.applyMatrix4(this.matrixWorld),r=d.ray.origin.distanceTo(l),rd.far||e.push({distance:r,point:h.clone().applyMatrix4(this.matrixWorld),index:g,face:null,faceIndex:null,object:this}))}else for(g=0,z=t.length/3-1;gf||(l.applyMatrix4(this.matrixWorld), -r=d.ray.origin.distanceTo(l),rd.far||e.push({distance:r,point:h.clone().applyMatrix4(this.matrixWorld),index:g,face:null,faceIndex:null,object:this}))}else if(g.isGeometry)for(k=g.vertices,m=k.length,g=0;gf||(l.applyMatrix4(this.matrixWorld),r=d.ray.origin.distanceTo(l),rd.far||e.push({distance:r,point:h.clone().applyMatrix4(this.matrixWorld),index:g,face:null,faceIndex:null,object:this}))}}}(),clone:function(){return(new this.constructor(this.geometry, -this.material)).copy(this)}});da.prototype=Object.assign(Object.create(ya.prototype),{constructor:da,isLineSegments:!0});pd.prototype=Object.assign(Object.create(ya.prototype),{constructor:pd,isLineLoop:!0});La.prototype=Object.create(Z.prototype);La.prototype.constructor=La;La.prototype.isPointsMaterial=!0;La.prototype.copy=function(a){Z.prototype.copy.call(this,a);this.color.copy(a.color);this.map=a.map;this.size=a.size;this.sizeAttenuation=a.sizeAttenuation;return this};Mb.prototype=Object.assign(Object.create(B.prototype), -{constructor:Mb,isPoints:!0,raycast:function(){var a=new J,b=new hb,c=new Ga;return function(d,e){function f(a,c){var f=b.distanceSqToPoint(a);if(fd.far||e.push({distance:m,distanceToRay:Math.sqrt(f),point:h.clone(),index:c,face:null,object:g})}}var g=this,h=this.geometry,k=this.matrixWorld,m=d.params.Points.threshold;null===h.boundingSphere&&h.computeBoundingSphere();c.copy(h.boundingSphere);c.applyMatrix4(k); -c.radius+=m;if(!1!==d.ray.intersectsSphere(c)){a.getInverse(k);b.copy(d.ray).applyMatrix4(a);var m=m/((this.scale.x+this.scale.y+this.scale.z)/3),l=m*m,m=new p;if(h.isBufferGeometry){var q=h.index,h=h.attributes.position.array;if(null!==q)for(var n=q.array,q=0,t=n.length;qc)return null;var d=[],e=[],f=[],g,h,k;if(0=m--){console.warn("THREE.ShapeUtils: Unable to triangulate polygon! in triangulate()"); -break}g=h;c<=g&&(g=0);h=g+1;c<=h&&(h=0);k=h+1;c<=k&&(k=0);var l;a:{var q,n,t,p,r,x,y,v;q=a[e[g]].x;n=a[e[g]].y;t=a[e[h]].x;p=a[e[h]].y;r=a[e[k]].x;x=a[e[k]].y;if(0>=(t-q)*(x-n)-(p-n)*(r-q))l=!1;else{var F,w,D,E,C,G,B,O,I,H;F=r-t;w=x-p;D=q-r;E=n-x;C=t-q;G=p-n;for(l=0;l=-Number.EPSILON&&O>=-Number.EPSILON&&B>=-Number.EPSILON)){l=!1;break a}l=!0}}if(l){d.push([a[e[g]], -a[e[h]],a[e[k]]]);f.push([e[g],e[h],e[k]]);g=h;for(k=h+1;kNumber.EPSILON){if(0u||u>q)return[];k=m*l-k* -n;if(0>k||k>q)return[]}else{if(0c?[]:k===c?f?[]:[g]:a<=c?[g,h]:[g,m]}function f(a,b,c,d){var e=b.x-a.x,f=b.y-a.y;b=c.x-a.x;c=c.y-a.y;var g=d.x-a.x;d=d.y-a.y;a=e*c-f*b;e=e*d-f*g;return Math.abs(a)>Number.EPSILON?(b=g*c-d*b,0e&&(e=d);var g=a+1;g>d&&(g=0);d=f(h[a],h[e],h[g],k[b]);if(!d)return!1;d=k.length-1;e=b-1;0>e&&(e=d);g=b+1;g>d&&(g=0);return(d=f(k[b],k[e],k[g],h[a]))?!0:!1}function d(a,b){var c,f;for(c=0;cJ){console.log("Infinite Loop! Holes left:"+m.length+", Probably Hole outside Shape!");break}for(n=E;nk;k++)l=m[k].x+":"+m[k].y,l=q[l],void 0!==l&&(m[k]=l);return n.concat()},isClockWise:function(a){return 0>za.area(a)}};db.prototype=Object.create(M.prototype);db.prototype.constructor=db;Fa.prototype=Object.create(I.prototype);Fa.prototype.constructor=Fa;Fa.prototype.getArrays= -function(){var a=this.getAttribute("position"),a=a?Array.prototype.slice.call(a.array):[],b=this.getAttribute("uv"),b=b?Array.prototype.slice.call(b.array):[],c=this.index,c=c?Array.prototype.slice.call(c.array):[];return{position:a,uv:b,index:c}};Fa.prototype.addShapeList=function(a,b){var c=a.length;b.arrays=this.getArrays();for(var d=0;dNumber.EPSILON){var k=Math.sqrt(h),m=Math.sqrt(d*d+g*g),h=b.x-f/k;b=b.y+e/k;g=((c.x-g/m-h)*g-(c.y+d/m-b)*d)/(e*g-f*d);d=h+e*g-a.x;e=b+f*g-a.y;f=d*d+e*e;if(2>=f)return new E(d,e);f=Math.sqrt(f/2)}else a=!1,e>Number.EPSILON?d>Number.EPSILON&& -(a=!0):e<-Number.EPSILON?d<-Number.EPSILON&&(a=!0):Math.sign(f)===Math.sign(g)&&(a=!0),a?(d=-f,f=Math.sqrt(h)):(d=e,e=f,f=Math.sqrt(h/2));return new E(d/f,e/f)}function e(a,b){var c,d;for(N=a.length;0<=--N;){c=N;d=N-1;0>d&&(d=a.length-1);var e,f=F+2*x;for(e=0;eMath.abs(g-k)?[new E(a,1-c),new E(h,1-d),new E(m,1-e),new E(q,1-b)]:[new E(g,1-c),new E(k,1-d),new E(l,1-e),new E(n,1-b)]}};Oc.prototype=Object.create(M.prototype);Oc.prototype.constructor=Oc;Wb.prototype=Object.create(Fa.prototype); -Wb.prototype.constructor=Wb;Pc.prototype=Object.create(M.prototype);Pc.prototype.constructor=Pc;nb.prototype=Object.create(I.prototype);nb.prototype.constructor=nb;Qc.prototype=Object.create(M.prototype);Qc.prototype.constructor=Qc;Xb.prototype=Object.create(I.prototype);Xb.prototype.constructor=Xb;Rc.prototype=Object.create(M.prototype);Rc.prototype.constructor=Rc;Yb.prototype=Object.create(I.prototype);Yb.prototype.constructor=Yb;Zb.prototype=Object.create(M.prototype);Zb.prototype.constructor= -Zb;$b.prototype=Object.create(I.prototype);$b.prototype.constructor=$b;ac.prototype=Object.create(I.prototype);ac.prototype.constructor=ac;ob.prototype=Object.create(M.prototype);ob.prototype.constructor=ob;Wa.prototype=Object.create(I.prototype);Wa.prototype.constructor=Wa;Sc.prototype=Object.create(ob.prototype);Sc.prototype.constructor=Sc;Tc.prototype=Object.create(Wa.prototype);Tc.prototype.constructor=Tc;Uc.prototype=Object.create(M.prototype);Uc.prototype.constructor=Uc;bc.prototype=Object.create(I.prototype); -bc.prototype.constructor=bc;var Ma=Object.freeze({WireframeGeometry:Ob,ParametricGeometry:Fc,ParametricBufferGeometry:Pb,TetrahedronGeometry:Hc,TetrahedronBufferGeometry:Qb,OctahedronGeometry:Ic,OctahedronBufferGeometry:mb,IcosahedronGeometry:Jc,IcosahedronBufferGeometry:Rb,DodecahedronGeometry:Kc,DodecahedronBufferGeometry:Sb,PolyhedronGeometry:Gc,PolyhedronBufferGeometry:ia,TubeGeometry:Lc,TubeBufferGeometry:Tb,TorusKnotGeometry:Mc,TorusKnotBufferGeometry:Ub,TorusGeometry:Nc,TorusBufferGeometry:Vb, -TextGeometry:Oc,TextBufferGeometry:Wb,SphereGeometry:Pc,SphereBufferGeometry:nb,RingGeometry:Qc,RingBufferGeometry:Xb,PlaneGeometry:xc,PlaneBufferGeometry:lb,LatheGeometry:Rc,LatheBufferGeometry:Yb,ShapeGeometry:Zb,ShapeBufferGeometry:$b,ExtrudeGeometry:db,ExtrudeBufferGeometry:Fa,EdgesGeometry:ac,ConeGeometry:Sc,ConeBufferGeometry:Tc,CylinderGeometry:ob,CylinderBufferGeometry:Wa,CircleGeometry:Uc,CircleBufferGeometry:bc,BoxGeometry:Ib,BoxBufferGeometry:kb});cc.prototype=Object.create(Ea.prototype); -cc.prototype.constructor=cc;cc.prototype.isShadowMaterial=!0;dc.prototype=Object.create(Ea.prototype);dc.prototype.constructor=dc;dc.prototype.isRawShaderMaterial=!0;Ra.prototype=Object.create(Z.prototype);Ra.prototype.constructor=Ra;Ra.prototype.isMeshStandardMaterial=!0;Ra.prototype.copy=function(a){Z.prototype.copy.call(this,a);this.defines={STANDARD:""};this.color.copy(a.color);this.roughness=a.roughness;this.metalness=a.metalness;this.map=a.map;this.lightMap=a.lightMap;this.lightMapIntensity= -a.lightMapIntensity;this.aoMap=a.aoMap;this.aoMapIntensity=a.aoMapIntensity;this.emissive.copy(a.emissive);this.emissiveMap=a.emissiveMap;this.emissiveIntensity=a.emissiveIntensity;this.bumpMap=a.bumpMap;this.bumpScale=a.bumpScale;this.normalMap=a.normalMap;this.normalScale.copy(a.normalScale);this.displacementMap=a.displacementMap;this.displacementScale=a.displacementScale;this.displacementBias=a.displacementBias;this.roughnessMap=a.roughnessMap;this.metalnessMap=a.metalnessMap;this.alphaMap=a.alphaMap; -this.envMap=a.envMap;this.envMapIntensity=a.envMapIntensity;this.refractionRatio=a.refractionRatio;this.wireframe=a.wireframe;this.wireframeLinewidth=a.wireframeLinewidth;this.wireframeLinecap=a.wireframeLinecap;this.wireframeLinejoin=a.wireframeLinejoin;this.skinning=a.skinning;this.morphTargets=a.morphTargets;this.morphNormals=a.morphNormals;return this};pb.prototype=Object.create(Ra.prototype);pb.prototype.constructor=pb;pb.prototype.isMeshPhysicalMaterial=!0;pb.prototype.copy=function(a){Ra.prototype.copy.call(this, -a);this.defines={PHYSICAL:""};this.reflectivity=a.reflectivity;this.clearCoat=a.clearCoat;this.clearCoatRoughness=a.clearCoatRoughness;return this};ta.prototype=Object.create(Z.prototype);ta.prototype.constructor=ta;ta.prototype.isMeshPhongMaterial=!0;ta.prototype.copy=function(a){Z.prototype.copy.call(this,a);this.color.copy(a.color);this.specular.copy(a.specular);this.shininess=a.shininess;this.map=a.map;this.lightMap=a.lightMap;this.lightMapIntensity=a.lightMapIntensity;this.aoMap=a.aoMap;this.aoMapIntensity= -a.aoMapIntensity;this.emissive.copy(a.emissive);this.emissiveMap=a.emissiveMap;this.emissiveIntensity=a.emissiveIntensity;this.bumpMap=a.bumpMap;this.bumpScale=a.bumpScale;this.normalMap=a.normalMap;this.normalScale.copy(a.normalScale);this.displacementMap=a.displacementMap;this.displacementScale=a.displacementScale;this.displacementBias=a.displacementBias;this.specularMap=a.specularMap;this.alphaMap=a.alphaMap;this.envMap=a.envMap;this.combine=a.combine;this.reflectivity=a.reflectivity;this.refractionRatio= -a.refractionRatio;this.wireframe=a.wireframe;this.wireframeLinewidth=a.wireframeLinewidth;this.wireframeLinecap=a.wireframeLinecap;this.wireframeLinejoin=a.wireframeLinejoin;this.skinning=a.skinning;this.morphTargets=a.morphTargets;this.morphNormals=a.morphNormals;return this};qb.prototype=Object.create(ta.prototype);qb.prototype.constructor=qb;qb.prototype.isMeshToonMaterial=!0;qb.prototype.copy=function(a){ta.prototype.copy.call(this,a);this.gradientMap=a.gradientMap;return this};rb.prototype=Object.create(Z.prototype); -rb.prototype.constructor=rb;rb.prototype.isMeshNormalMaterial=!0;rb.prototype.copy=function(a){Z.prototype.copy.call(this,a);this.bumpMap=a.bumpMap;this.bumpScale=a.bumpScale;this.normalMap=a.normalMap;this.normalScale.copy(a.normalScale);this.displacementMap=a.displacementMap;this.displacementScale=a.displacementScale;this.displacementBias=a.displacementBias;this.wireframe=a.wireframe;this.wireframeLinewidth=a.wireframeLinewidth;this.skinning=a.skinning;this.morphTargets=a.morphTargets;this.morphNormals= -a.morphNormals;return this};sb.prototype=Object.create(Z.prototype);sb.prototype.constructor=sb;sb.prototype.isMeshLambertMaterial=!0;sb.prototype.copy=function(a){Z.prototype.copy.call(this,a);this.color.copy(a.color);this.map=a.map;this.lightMap=a.lightMap;this.lightMapIntensity=a.lightMapIntensity;this.aoMap=a.aoMap;this.aoMapIntensity=a.aoMapIntensity;this.emissive.copy(a.emissive);this.emissiveMap=a.emissiveMap;this.emissiveIntensity=a.emissiveIntensity;this.specularMap=a.specularMap;this.alphaMap= -a.alphaMap;this.envMap=a.envMap;this.combine=a.combine;this.reflectivity=a.reflectivity;this.refractionRatio=a.refractionRatio;this.wireframe=a.wireframe;this.wireframeLinewidth=a.wireframeLinewidth;this.wireframeLinecap=a.wireframeLinecap;this.wireframeLinejoin=a.wireframeLinejoin;this.skinning=a.skinning;this.morphTargets=a.morphTargets;this.morphNormals=a.morphNormals;return this};tb.prototype=Object.create(Z.prototype);tb.prototype.constructor=tb;tb.prototype.isLineDashedMaterial=!0;tb.prototype.copy= -function(a){Z.prototype.copy.call(this,a);this.color.copy(a.color);this.linewidth=a.linewidth;this.scale=a.scale;this.dashSize=a.dashSize;this.gapSize=a.gapSize;return this};var lg=Object.freeze({ShadowMaterial:cc,SpriteMaterial:cb,RawShaderMaterial:dc,ShaderMaterial:Ea,PointsMaterial:La,MeshPhysicalMaterial:pb,MeshStandardMaterial:Ra,MeshPhongMaterial:ta,MeshToonMaterial:qb,MeshNormalMaterial:rb,MeshLambertMaterial:sb,MeshDepthMaterial:$a,MeshBasicMaterial:Na,LineDashedMaterial:tb,LineBasicMaterial:ha, -Material:Z}),hd={enabled:!1,files:{},add:function(a,b){!1!==this.enabled&&(this.files[a]=b)},get:function(a){if(!1!==this.enabled)return this.files[a]},remove:function(a){delete this.files[a]},clear:function(){this.files={}}},Aa=new Zd;Object.assign(ua.prototype,{load:function(a,b,c,d){void 0===a&&(a="");void 0!==this.path&&(a=this.path+a);var e=this,f=hd.get(a);if(void 0!==f)return e.manager.itemStart(a),setTimeout(function(){b&&b(f);e.manager.itemEnd(a)},0),f;var g=a.match(/^data:(.*?)(;base64)?,(.*)$/); -if(g){var h=g[1],k=!!g[2],g=g[3],g=window.decodeURIComponent(g);k&&(g=window.atob(g));try{var m,l=(this.responseType||"").toLowerCase();switch(l){case "arraybuffer":case "blob":m=new ArrayBuffer(g.length);for(var q=new Uint8Array(m),k=0;k=e)break a;else{f=b[1];a=e)break b}d=c;c= -0}}for(;c>>1,ab;)--f;++f;if(0!==e||f!==d)e>=f&&(f=Math.max(f, -1),e=f-1),d=this.getValueSize(),this.times=va.arraySlice(c,e,f),this.values=va.arraySlice(this.values,e*d,f*d);return this},validate:function(){var a=!0,b=this.getValueSize();0!==b-Math.floor(b)&&(console.error("THREE.KeyframeTrackPrototype: Invalid value size in track.",this),a=!1);var c=this.times,b=this.values,d=c.length;0===d&&(console.error("THREE.KeyframeTrackPrototype: Track is empty.",this),a=!1);for(var e=null,f=0;f!==d;f++){var g=c[f];if("number"===typeof g&&isNaN(g)){console.error("THREE.KeyframeTrackPrototype: Time is not a valid number.", -this,f,g);a=!1;break}if(null!==e&&e>g){console.error("THREE.KeyframeTrackPrototype: Out of order keys.",this,f,g,e);a=!1;break}e=g}if(void 0!==b&&va.isTypedArray(b))for(f=0,c=b.length;f!==c;++f)if(d=b[f],isNaN(d)){console.error("THREE.KeyframeTrackPrototype: Value is not a valid number.",this,f,d);a=!1;break}return a},optimize:function(){for(var a=this.times,b=this.values,c=this.getValueSize(),d=2302===this.getInterpolation(),e=1,f=a.length-1,g=1;gm.opacity&&(m.transparent=!0);d.setTextures(k);return d.parse(m)}}()});Object.assign(ce.prototype,{load:function(a,b,c,d){var e=this,f=this.texturePath&&"string"===typeof this.texturePath?this.texturePath:gc.prototype.extractUrlBase(a),g=new ua(this.manager); -g.setWithCredentials(this.withCredentials);g.load(a,function(c){c=JSON.parse(c);var d=c.metadata;if(void 0!==d&&(d=d.type,void 0!==d)){if("object"===d.toLowerCase()){console.error("THREE.JSONLoader: "+a+" should be loaded with THREE.ObjectLoader instead.");return}if("scene"===d.toLowerCase()){console.error("THREE.JSONLoader: "+a+" should be loaded with THREE.SceneLoader instead.");return}}c=e.parse(c,f);b(c.geometry,c.materials)},c,d)},setTexturePath:function(a){this.texturePath=a},parse:function(){return function(a, -b){void 0!==a.data&&(a=a.data);a.scale=void 0!==a.scale?1/a.scale:1;var c=new M,d=a,e,f,g,h,k,m,l,q,n,t,z,r,x,y,v=d.faces;n=d.vertices;var F=d.normals,w=d.colors;m=d.scale;var B=0;if(void 0!==d.uvs){for(e=0;ef;f++)q=v[h++],y=x[2*q],q=x[2*q+1],y=new E(y,q),2!==f&&c.faceVertexUvs[e][g].push(y),0!==f&&c.faceVertexUvs[e][g+1].push(y);l&&(l=3*v[h++],t.normal.set(F[l++],F[l++],F[l]),r.normal.copy(t.normal));if(z)for(e=0;4>e;e++)l=3*v[h++],z=new p(F[l++],F[l++],F[l]),2!==e&&t.vertexNormals.push(z),0!==e&& -r.vertexNormals.push(z);m&&(m=v[h++],m=w[m],t.color.setHex(m),r.color.setHex(m));if(n)for(e=0;4>e;e++)m=v[h++],m=w[m],2!==e&&t.vertexColors.push(new H(m)),0!==e&&r.vertexColors.push(new H(m));c.faces.push(t);c.faces.push(r)}else{t=new Va;t.a=v[h++];t.b=v[h++];t.c=v[h++];g&&(g=v[h++],t.materialIndex=g);g=c.faces.length;if(e)for(e=0;ef;f++)q=v[h++],y=x[2*q],q=x[2*q+1],y=new E(y,q),c.faceVertexUvs[e][g].push(y);l&&(l=3*v[h++],t.normal.set(F[l++],F[l++], -F[l]));if(z)for(e=0;3>e;e++)l=3*v[h++],z=new p(F[l++],F[l++],F[l]),t.vertexNormals.push(z);m&&(m=v[h++],t.color.setHex(w[m]));if(n)for(e=0;3>e;e++)m=v[h++],t.vertexColors.push(new H(w[m]));c.faces.push(t)}d=a;h=void 0!==d.influencesPerVertex?d.influencesPerVertex:2;if(d.skinWeights)for(k=0,v=d.skinWeights.length;kk)g=d+1;else if(0b&&(b=0);1Number.EPSILON&&(g.normalize(),c=Math.acos(Y.clamp(d[k-1].dot(d[k]),-1,1)),e[k].applyMatrix4(h.makeRotationAxis(g,c))),f[k].crossVectors(d[k],e[k]);if(!0=== -b)for(c=Math.acos(Y.clamp(e[0].dot(e[a]),-1,1)),c/=a,0=b)return b=c[a]-b,a=this.curves[a],c=a.getLength(),a.getPointAt(0=== -c?0:1-b/c);a++}return null},getLength:function(){var a=this.getCurveLengths();return a[a.length-1]},updateArcLengths:function(){this.needsUpdate=!0;this.cacheLengths=null;this.getCurveLengths()},getCurveLengths:function(){if(this.cacheLengths&&this.cacheLengths.length===this.curves.length)return this.cacheLengths;for(var a=[],b=0,c=0,d=this.curves.length;cc;)c+=b;for(;c>b;)c-=b;cb.length-2?b.length-1:a+1],b=b[a>b.length-3?b.length- -1:a+2];return new E(Se(c,d.x,e.x,f.x,b.x),Se(c,d.y,e.y,f.y,b.y))};hc.prototype=Object.create(na.prototype);hc.prototype.constructor=hc;hc.prototype.getPoint=function(a){var b=this.v0,c=this.v1,d=this.v2,e=this.v3;return new E(yb(a,b.x,c.x,d.x,e.x),yb(a,b.y,c.y,d.y,e.y))};ic.prototype=Object.create(na.prototype);ic.prototype.constructor=ic;ic.prototype.getPoint=function(a){var b=this.v0,c=this.v1,d=this.v2;return new E(xb(a,b.x,c.x,d.x),xb(a,b.y,c.y,d.y))};var ue=Object.assign(Object.create(Yc.prototype), -{fromPoints:function(a){this.moveTo(a[0].x,a[0].y);for(var b=1,c=a.length;bNumber.EPSILON){if(0>l&&(g=b[f],k=-k,h=b[e],l=-l),!(a.yh.y))if(a.y===g.y){if(a.x===g.x)return!0}else{e=l*(a.x-g.x)-k*(a.y-g.y);if(0===e)return!0;0>e||(d=!d)}}else if(a.y===g.y&&(h.x<=a.x&&a.x<=g.x||g.x<=a.x&&a.x<=h.x))return!0}return d}var e=za.isClockWise,f=this.subPaths;if(0===f.length)return[];if(!0===b)return c(f);var g,h,k,l=[];if(1===f.length)return h= -f[0],k=new Ab,k.curves=h.curves,l.push(k),l;var p=!e(f[0].getPoints()),p=a?!p:p;k=[];var q=[],n=[],t=0,z;q[t]=void 0;n[t]=[];for(var r=0,x=f.length;rd&&this._mixBufferRegion(c,a,3*b,1-d,b);for(var d=b,f=b+b;d!==f;++d)if(c[d]!==c[d+b]){e.setValue(c,a);break}},saveOriginalState:function(){var a= -this.buffer,b=this.valueSize,c=3*b;this.binding.getValue(a,c);for(var d=b;d!==c;++d)a[d]=a[c+d%b];this.cumulativeWeight=0},restoreOriginalState:function(){this.binding.setValue(this.buffer,3*this.valueSize)},_select:function(a,b,c,d,e){if(.5<=d)for(d=0;d!==e;++d)a[b+d]=a[c+d]},_slerp:function(a,b,c,d){qa.slerpFlat(a,b,a,b,a,c,d)},_lerp:function(a,b,c,d,e){for(var f=1-d,g=0;g!==e;++g){var h=b+g;a[h]=a[h]*f+a[c+g]*d}}});Object.assign(Ve.prototype,{getValue:function(a,b){this.bind();var c=this._bindings[this._targetGroup.nCachedObjects_]; -void 0!==c&&c.getValue(a,b)},setValue:function(a,b){for(var c=this._bindings,d=this._targetGroup.nCachedObjects_,e=c.length;d!==e;++d)c[d].setValue(a,b)},bind:function(){for(var a=this._bindings,b=this._targetGroup.nCachedObjects_,c=a.length;b!==c;++b)a[b].bind()},unbind:function(){for(var a=this._bindings,b=this._targetGroup.nCachedObjects_,c=a.length;b!==c;++b)a[b].unbind()}});Object.assign(oa,{Composite:Ve,create:function(a,b,c){return a&&a.isAnimationObjectGroup?new oa.Composite(a,b,c):new oa(a, -b,c)},parseTrackName:function(){var a=new RegExp("^"+/((?:[\w-]+[\/:])*)/.source+/([\w-\.]+)?/.source+/(?:\.([\w-]+)(?:\[(.+)\])?)?/.source+/\.([\w-]+)(?:\[(.+)\])?/.source+"$"),b=["material","materials","bones"];return function(c){var d=a.exec(c);if(!d)throw Error("PropertyBinding: Cannot parse trackName: "+c);var d={nodeName:d[2],objectName:d[3],objectIndex:d[4],propertyName:d[5],propertyIndex:d[6]},e=d.nodeName&&d.nodeName.lastIndexOf(".");if(void 0!==e&&-1!==e){var f=d.nodeName.substring(e+1); --1!==b.indexOf(f)&&(d.nodeName=d.nodeName.substring(0,e),d.objectName=f)}if(null===d.propertyName||0===d.propertyName.length)throw Error("PropertyBinding: can not parse propertyName from trackName: "+c);return d}}(),findNode:function(a,b){if(!b||""===b||"root"===b||"."===b||-1===b||b===a.name||b===a.uuid)return a;if(a.skeleton){var c=function(a){for(var c=0;c=c){var q=c++,n=b[q];d[n.uuid]=p;b[p]=n;d[l]=q;b[q]=k;k=0;for(l=f;k!==l;++k){var n=e[k],t=n[p];n[p]=n[q];n[q]=t}}}this.nCachedObjects_=c},uncache:function(a){for(var b=this._objects,c=b.length,d=this.nCachedObjects_,e=this._indicesByUUID,f=this._bindings,g=f.length,h=0,k=arguments.length;h!==k;++h){var l=arguments[h].uuid,p=e[l];if(void 0!==p)if(delete e[l],pa?b.copy(this.origin):b.copy(this.direction).multiplyScalar(a).add(this.origin)},distanceToPoint:function(a){return Math.sqrt(this.distanceSqToPoint(a))},distanceSqToPoint:function(){var a=new p;return function(b){var c=a.subVectors(b,this.origin).dot(this.direction);if(0>c)return this.origin.distanceToSquared(b);a.copy(this.direction).multiplyScalar(c).add(this.origin);return a.distanceToSquared(b)}}(),distanceSqToSegment:function(){var a= +new p,b=new p,c=new p;return function(d,e,f,g){a.copy(d).add(e).multiplyScalar(.5);b.copy(e).sub(d).normalize();c.copy(this.origin).sub(a);var h=.5*d.distanceTo(e),k=-this.direction.dot(b),l=c.dot(this.direction),q=-c.dot(b),n=c.lengthSq(),m=Math.abs(1-k*k);if(0=-p?e<=p?(h=1/m,d*=h,e*=h,k=d*(d+k*e+2*l)+e*(k*d+e+2*q)+n):(e=h,d=Math.max(0,-(k*e+l)),k=-d*d+e*(e+2*q)+n):(e=-h,d=Math.max(0,-(k*e+l)),k=-d*d+e*(e+2*q)+n):e<=-p?(d=Math.max(0,-(-k*h+l)),e=0b)return null; +b=Math.sqrt(b-e);e=d-b;d+=b;return 0>e&&0>d?null:0>e?this.at(d,c):this.at(e,c)}}(),intersectsSphere:function(a){return this.distanceToPoint(a.center)<=a.radius},distanceToPlane:function(a){var b=a.normal.dot(this.direction);if(0===b)return 0===a.distanceToPoint(this.origin)?0:null;a=-(this.origin.dot(a.normal)+a.constant)/b;return 0<=a?a:null},intersectPlane:function(a,b){a=this.distanceToPlane(a);return null===a?null:this.at(a,b)},intersectsPlane:function(a){var b=a.distanceToPoint(this.origin); +return 0===b||0>a.normal.dot(this.direction)*b?!0:!1},intersectBox:function(a,b){var c=1/this.direction.x;var d=1/this.direction.y;var e=1/this.direction.z,f=this.origin;if(0<=c){var g=(a.min.x-f.x)*c;c*=a.max.x-f.x}else g=(a.max.x-f.x)*c,c*=a.min.x-f.x;if(0<=d){var h=(a.min.y-f.y)*d;d*=a.max.y-f.y}else h=(a.max.y-f.y)*d,d*=a.min.y-f.y;if(g>d||h>c)return null;if(h>g||g!==g)g=h;if(da||h>c)return null; +if(h>g||g!==g)g=h;if(ac?null:this.at(0<=g?g:c,b)},intersectsBox:function(){var a=new p;return function(b){return null!==this.intersectBox(b,a)}}(),intersectTriangle:function(){var a=new p,b=new p,c=new p,d=new p;return function(e,f,g,h,k){b.subVectors(f,e);c.subVectors(g,e);d.crossVectors(b,c);f=this.direction.dot(d);if(0f)h=-1,f=-f;else return null;a.subVectors(this.origin,e);e=h*this.direction.dot(c.crossVectors(a,c));if(0>e)return null; +g=h*this.direction.dot(b.cross(a));if(0>g||e+g>f)return null;e=-h*a.dot(d);return 0>e?null:this.at(e/f,k)}}(),applyMatrix4:function(a){this.origin.applyMatrix4(a);this.direction.transformDirection(a);return this},equals:function(a){return a.origin.equals(this.origin)&&a.direction.equals(this.direction)}});Object.assign(Gb.prototype,{set:function(a,b){this.start.copy(a);this.end.copy(b);return this},clone:function(){return(new this.constructor).copy(this)},copy:function(a){this.start.copy(a.start); +this.end.copy(a.end);return this},getCenter:function(a){return(a||new p).addVectors(this.start,this.end).multiplyScalar(.5)},delta:function(a){return(a||new p).subVectors(this.end,this.start)},distanceSq:function(){return this.start.distanceToSquared(this.end)},distance:function(){return this.start.distanceTo(this.end)},at:function(a,b){b=b||new p;return this.delta(b).multiplyScalar(a).add(this.start)},closestPointToPointParameter:function(){var a=new p,b=new p;return function(c,d){a.subVectors(c, +this.start);b.subVectors(this.end,this.start);c=b.dot(b);c=b.dot(a)/c;d&&(c=R.clamp(c,0,1));return c}}(),closestPointToPoint:function(a,b,c){a=this.closestPointToPointParameter(a,b);c=c||new p;return this.delta(c).multiplyScalar(a).add(this.start)},applyMatrix4:function(a){this.start.applyMatrix4(a);this.end.applyMatrix4(a);return this},equals:function(a){return a.start.equals(this.start)&&a.end.equals(this.end)}});Object.assign(Ra,{normal:function(){var a=new p;return function(b,c,d,e){e=e||new p; +e.subVectors(d,c);a.subVectors(b,c);e.cross(a);b=e.lengthSq();return 0=b.x+b.y}}()});Object.assign(Ra.prototype,{set:function(a,b,c){this.a.copy(a);this.b.copy(b);this.c.copy(c);return this},setFromPointsAndIndices:function(a,b,c,d){this.a.copy(a[b]);this.b.copy(a[c]);this.c.copy(a[d]);return this},clone:function(){return(new this.constructor).copy(this)},copy:function(a){this.a.copy(a.a);this.b.copy(a.b);this.c.copy(a.c);return this},area:function(){var a=new p,b=new p;return function(){a.subVectors(this.c, +this.b);b.subVectors(this.a,this.b);return.5*a.cross(b).length()}}(),midpoint:function(a){return(a||new p).addVectors(this.a,this.b).add(this.c).multiplyScalar(1/3)},normal:function(a){return Ra.normal(this.a,this.b,this.c,a)},plane:function(a){return(a||new za).setFromCoplanarPoints(this.a,this.b,this.c)},barycoordFromPoint:function(a,b){return Ra.barycoordFromPoint(a,this.a,this.b,this.c,b)},containsPoint:function(a){return Ra.containsPoint(a,this.a,this.b,this.c)},closestPointToPoint:function(){var a= +new za,b=[new Gb,new Gb,new Gb],c=new p,d=new p;return function(e,f){f=f||new p;var g=Infinity;a.setFromCoplanarPoints(this.a,this.b,this.c);a.projectPoint(e,c);if(!0===this.containsPoint(c))f.copy(c);else for(b[0].set(this.a,this.b),b[1].set(this.b,this.c),b[2].set(this.c,this.a),e=0;ec.far?null:{distance:b,point:x.clone(),object:a}}function c(c,d,e,f,l,q,m,n){g.fromBufferAttribute(f,q);h.fromBufferAttribute(f,m);k.fromBufferAttribute(f,n);if(c=b(c,c.material,d,e,g,h,k,w))l&&(u.fromBufferAttribute(l,q),r.fromBufferAttribute(l,m),v.fromBufferAttribute(l,n),c.uv=a(w,g,h,k,u,r,v)),c.face=new Qa(q,m,n,Ra.normal(g,h,k)),c.faceIndex=q;return c}var d=new K,e=new ib,f=new ra, +g=new p,h=new p,k=new p,l=new p,q=new p,m=new p,u=new D,r=new D,v=new D,t=new p,w=new p,x=new p;return function(n,p){var t=this.geometry,x=this.material,A=this.matrixWorld;if(void 0!==x&&(null===t.boundingSphere&&t.computeBoundingSphere(),f.copy(t.boundingSphere),f.applyMatrix4(A),!1!==n.ray.intersectsSphere(f)&&(d.getInverse(A),e.copy(n.ray).applyMatrix4(d),null===t.boundingBox||!1!==e.intersectsBox(t.boundingBox)))){var y;if(t.isBufferGeometry){var x=t.index,I=t.attributes.position,A=t.attributes.uv, +z;if(null!==x){var D=0;for(z=x.count;Df||(f=d.ray.origin.distanceTo(a),fd.far||e.push({distance:f,point:a.clone(),face:null,object:this}))}}(),clone:function(){return(new this.constructor(this.material)).copy(this)}});zc.prototype=Object.assign(Object.create(z.prototype),{constructor:zc,copy:function(a){z.prototype.copy.call(this,a,!1);a=a.levels;for(var b=0,c=a.length;b=d[e].distance)d[e-1].object.visible=!1,d[e].object.visible=!0;else break;for(;ef||(q.applyMatrix4(this.matrixWorld),m=d.ray.origin.distanceTo(q),md.far||e.push({distance:m,point:h.clone().applyMatrix4(this.matrixWorld),index:g,face:null,faceIndex:null,object:this}));else for(g=0,t=r.length/3-1;gf||(q.applyMatrix4(this.matrixWorld),m=d.ray.origin.distanceTo(q),md.far||e.push({distance:m,point:h.clone().applyMatrix4(this.matrixWorld),index:g, +face:null,faceIndex:null,object:this}))}else if(g.isGeometry)for(k=g.vertices,l=k.length,g=0;gf||(q.applyMatrix4(this.matrixWorld),m=d.ray.origin.distanceTo(q),md.far||e.push({distance:m,point:h.clone().applyMatrix4(this.matrixWorld),index:g,face:null,faceIndex:null,object:this}))}}}(),clone:function(){return(new this.constructor(this.geometry,this.material)).copy(this)}});T.prototype=Object.assign(Object.create(ua.prototype),{constructor:T, +isLineSegments:!0});qd.prototype=Object.assign(Object.create(ua.prototype),{constructor:qd,isLineLoop:!0});ma.prototype=Object.create(P.prototype);ma.prototype.constructor=ma;ma.prototype.isPointsMaterial=!0;ma.prototype.copy=function(a){P.prototype.copy.call(this,a);this.color.copy(a.color);this.map=a.map;this.size=a.size;this.sizeAttenuation=a.sizeAttenuation;return this};Kb.prototype=Object.assign(Object.create(z.prototype),{constructor:Kb,isPoints:!0,raycast:function(){var a=new K,b=new ib,c= +new ra;return function(d,e){function f(a,c){var f=b.distanceSqToPoint(a);if(fd.far||e.push({distance:h,distanceToRay:Math.sqrt(f),point:a.clone(),index:c,face:null,object:g})}}var g=this,h=this.geometry,k=this.matrixWorld,l=d.params.Points.threshold;null===h.boundingSphere&&h.computeBoundingSphere();c.copy(h.boundingSphere);c.applyMatrix4(k);c.radius+=l;if(!1!==d.ray.intersectsSphere(c)){a.getInverse(k); +b.copy(d.ray).applyMatrix4(a);var l=l/((this.scale.x+this.scale.y+this.scale.z)/3),m=l*l,l=new p;if(h.isBufferGeometry){var n=h.index,h=h.attributes.position.array;if(null!==n)for(var u=n.array,n=0,r=u.length;nc)return null;var d=[],e=[],f=[],g;if(0=h--){console.warn("THREE.ShapeUtils: Unable to triangulate polygon! in triangulate()");break}var k=g;c<=k&&(k=0);g=k+ +1;c<=g&&(g=0);var l=g+1;c<=l&&(l=0);a:{var m;var n=a[e[k]].x;var p=a[e[k]].y;var r=a[e[g]].x;var v=a[e[g]].y;var t=a[e[l]].x;var w=a[e[l]].y;if(0>=(r-n)*(w-p)-(v-p)*(t-n))var x=!1;else{var A=t-r;var y=w-v;var C=n-t;var z=p-w;var D=r-n;x=v-p;for(m=0;m=-Number.EPSILON&&B>=-Number.EPSILON&&K>=-Number.EPSILON){x=!1;break a}}}x=!0}}if(x){d.push([a[e[k]], +a[e[g]],a[e[l]]]);f.push([e[k],e[g],e[l]]);k=g;for(l=g+1;lNumber.EPSILON){if(0p||p>n)return[];k=l*m-k* +q;if(0>k||k>n)return[]}else{if(0c?[]:k===c?f?[]:[g]:a<=c?[g,h]:[g,l]}function f(a,b,c,d){var e=b.x-a.x,f=b.y-a.y;b=c.x-a.x;c=c.y-a.y;var g=d.x-a.x;d=d.y-a.y;a=e*c-f*b;e=e*d-f*g;return Math.abs(a)>Number.EPSILON?(b=g*c-d*b,0d&&(d=c);var e=a+1;e>c&&(e=0);c=f(h[a],h[d],h[e],B[b]);if(!c)return!1;c=B.length-1;d=b-1;0>d&&(d=c);e=b+1;e>c&&(e=0);return(c=f(B[b],B[d],B[e],h[a]))?!0:!1}function d(a,b){var c;for(c=0;cu){console.log('THREE.ShapeUtils: Infinite Loop! Holes left:" + indepHoles.length + ", Probably Hole outside Shape!');break}for(m=p;ma;a++)m=b[a].x+":"+b[a].y,m=h[m],void 0!==m&&(b[a]=m);return k.concat()},isClockWise:function(a){return 0>Ea.area(a)}};ab.prototype=Object.create(L.prototype);ab.prototype.constructor=ab;Da.prototype=Object.create(E.prototype); +Da.prototype.constructor=Da;Da.prototype.getArrays=function(){var a=this.getAttribute("position"),a=a?Array.prototype.slice.call(a.array):[],b=this.getAttribute("uv"),b=b?Array.prototype.slice.call(b.array):[],c=this.index,c=c?Array.prototype.slice.call(c.array):[];return{position:a,uv:b,index:c}};Da.prototype.addShapeList=function(a,b){var c=a.length;b.arrays=this.getArrays();for(var d=0;dNumber.EPSILON){var k=Math.sqrt(h),l=Math.sqrt(f*f+g*g),h=b.x-e/k;b=b.y+d/k;g=((c.x-g/l-h)*g-(c.y+f/l-b)*f)/(d*g-e*f);f=h+d*g-a.x;d=b+e*g-a.y;e=f*f+d*d;if(2>=e)return new D(f,d);e=Math.sqrt(e/ +2)}else a=!1,d>Number.EPSILON?f>Number.EPSILON&&(a=!0):d<-Number.EPSILON?f<-Number.EPSILON&&(a=!0):Math.sign(e)===Math.sign(g)&&(a=!0),a?(f=-e,e=Math.sqrt(h)):(f=d,d=e,e=Math.sqrt(h/2));return new D(f/e,d/e)}function e(a,b){for(G=a.length;0<=--G;){var c=G;var d=G-1;0>d&&(d=a.length-1);var e,f=z+2*w;for(e=0;eMath.abs(g-k)?[new D(a,1-c),new D(h,1-d),new D(l,1-e),new D(n,1-b)]:[new D(g,1-c),new D(k,1-d),new D(m,1-e),new D(p,1-b)]}};Mc.prototype=Object.create(L.prototype);Mc.prototype.constructor=Mc;Ub.prototype= +Object.create(Da.prototype);Ub.prototype.constructor=Ub;Nc.prototype=Object.create(L.prototype);Nc.prototype.constructor=Nc;lb.prototype=Object.create(E.prototype);lb.prototype.constructor=lb;Oc.prototype=Object.create(L.prototype);Oc.prototype.constructor=Oc;Vb.prototype=Object.create(E.prototype);Vb.prototype.constructor=Vb;Pc.prototype=Object.create(L.prototype);Pc.prototype.constructor=Pc;Wb.prototype=Object.create(E.prototype);Wb.prototype.constructor=Wb;Xb.prototype=Object.create(L.prototype); +Xb.prototype.constructor=Xb;Yb.prototype=Object.create(E.prototype);Yb.prototype.constructor=Yb;Zb.prototype=Object.create(E.prototype);Zb.prototype.constructor=Zb;mb.prototype=Object.create(L.prototype);mb.prototype.constructor=mb;Ta.prototype=Object.create(E.prototype);Ta.prototype.constructor=Ta;Qc.prototype=Object.create(mb.prototype);Qc.prototype.constructor=Qc;Rc.prototype=Object.create(Ta.prototype);Rc.prototype.constructor=Rc;Sc.prototype=Object.create(L.prototype);Sc.prototype.constructor= +Sc;$b.prototype=Object.create(E.prototype);$b.prototype.constructor=$b;var Ka=Object.freeze({WireframeGeometry:Mb,ParametricGeometry:Dc,ParametricBufferGeometry:Nb,TetrahedronGeometry:Fc,TetrahedronBufferGeometry:Ob,OctahedronGeometry:Gc,OctahedronBufferGeometry:kb,IcosahedronGeometry:Hc,IcosahedronBufferGeometry:Pb,DodecahedronGeometry:Ic,DodecahedronBufferGeometry:Qb,PolyhedronGeometry:Ec,PolyhedronBufferGeometry:na,TubeGeometry:Jc,TubeBufferGeometry:Rb,TorusKnotGeometry:Kc,TorusKnotBufferGeometry:Sb, +TorusGeometry:Lc,TorusBufferGeometry:Tb,TextGeometry:Mc,TextBufferGeometry:Ub,SphereGeometry:Nc,SphereBufferGeometry:lb,RingGeometry:Oc,RingBufferGeometry:Vb,PlaneGeometry:wc,PlaneBufferGeometry:hb,LatheGeometry:Pc,LatheBufferGeometry:Wb,ShapeGeometry:Xb,ShapeBufferGeometry:Yb,ExtrudeGeometry:ab,ExtrudeBufferGeometry:Da,EdgesGeometry:Zb,ConeGeometry:Qc,ConeBufferGeometry:Rc,CylinderGeometry:mb,CylinderBufferGeometry:Ta,CircleGeometry:Sc,CircleBufferGeometry:$b,BoxGeometry:Fb,BoxBufferGeometry:gb}); +ac.prototype=Object.create(P.prototype);ac.prototype.constructor=ac;ac.prototype.isShadowMaterial=!0;bc.prototype=Object.create(ya.prototype);bc.prototype.constructor=bc;bc.prototype.isRawShaderMaterial=!0;Na.prototype=Object.create(P.prototype);Na.prototype.constructor=Na;Na.prototype.isMeshStandardMaterial=!0;Na.prototype.copy=function(a){P.prototype.copy.call(this,a);this.defines={STANDARD:""};this.color.copy(a.color);this.roughness=a.roughness;this.metalness=a.metalness;this.map=a.map;this.lightMap= +a.lightMap;this.lightMapIntensity=a.lightMapIntensity;this.aoMap=a.aoMap;this.aoMapIntensity=a.aoMapIntensity;this.emissive.copy(a.emissive);this.emissiveMap=a.emissiveMap;this.emissiveIntensity=a.emissiveIntensity;this.bumpMap=a.bumpMap;this.bumpScale=a.bumpScale;this.normalMap=a.normalMap;this.normalScale.copy(a.normalScale);this.displacementMap=a.displacementMap;this.displacementScale=a.displacementScale;this.displacementBias=a.displacementBias;this.roughnessMap=a.roughnessMap;this.metalnessMap= +a.metalnessMap;this.alphaMap=a.alphaMap;this.envMap=a.envMap;this.envMapIntensity=a.envMapIntensity;this.refractionRatio=a.refractionRatio;this.wireframe=a.wireframe;this.wireframeLinewidth=a.wireframeLinewidth;this.wireframeLinecap=a.wireframeLinecap;this.wireframeLinejoin=a.wireframeLinejoin;this.skinning=a.skinning;this.morphTargets=a.morphTargets;this.morphNormals=a.morphNormals;return this};nb.prototype=Object.create(Na.prototype);nb.prototype.constructor=nb;nb.prototype.isMeshPhysicalMaterial= +!0;nb.prototype.copy=function(a){Na.prototype.copy.call(this,a);this.defines={PHYSICAL:""};this.reflectivity=a.reflectivity;this.clearCoat=a.clearCoat;this.clearCoatRoughness=a.clearCoatRoughness;return this};Aa.prototype=Object.create(P.prototype);Aa.prototype.constructor=Aa;Aa.prototype.isMeshPhongMaterial=!0;Aa.prototype.copy=function(a){P.prototype.copy.call(this,a);this.color.copy(a.color);this.specular.copy(a.specular);this.shininess=a.shininess;this.map=a.map;this.lightMap=a.lightMap;this.lightMapIntensity= +a.lightMapIntensity;this.aoMap=a.aoMap;this.aoMapIntensity=a.aoMapIntensity;this.emissive.copy(a.emissive);this.emissiveMap=a.emissiveMap;this.emissiveIntensity=a.emissiveIntensity;this.bumpMap=a.bumpMap;this.bumpScale=a.bumpScale;this.normalMap=a.normalMap;this.normalScale.copy(a.normalScale);this.displacementMap=a.displacementMap;this.displacementScale=a.displacementScale;this.displacementBias=a.displacementBias;this.specularMap=a.specularMap;this.alphaMap=a.alphaMap;this.envMap=a.envMap;this.combine= +a.combine;this.reflectivity=a.reflectivity;this.refractionRatio=a.refractionRatio;this.wireframe=a.wireframe;this.wireframeLinewidth=a.wireframeLinewidth;this.wireframeLinecap=a.wireframeLinecap;this.wireframeLinejoin=a.wireframeLinejoin;this.skinning=a.skinning;this.morphTargets=a.morphTargets;this.morphNormals=a.morphNormals;return this};ob.prototype=Object.create(Aa.prototype);ob.prototype.constructor=ob;ob.prototype.isMeshToonMaterial=!0;ob.prototype.copy=function(a){Aa.prototype.copy.call(this, +a);this.gradientMap=a.gradientMap;return this};pb.prototype=Object.create(P.prototype);pb.prototype.constructor=pb;pb.prototype.isMeshNormalMaterial=!0;pb.prototype.copy=function(a){P.prototype.copy.call(this,a);this.bumpMap=a.bumpMap;this.bumpScale=a.bumpScale;this.normalMap=a.normalMap;this.normalScale.copy(a.normalScale);this.displacementMap=a.displacementMap;this.displacementScale=a.displacementScale;this.displacementBias=a.displacementBias;this.wireframe=a.wireframe;this.wireframeLinewidth=a.wireframeLinewidth; +this.skinning=a.skinning;this.morphTargets=a.morphTargets;this.morphNormals=a.morphNormals;return this};qb.prototype=Object.create(P.prototype);qb.prototype.constructor=qb;qb.prototype.isMeshLambertMaterial=!0;qb.prototype.copy=function(a){P.prototype.copy.call(this,a);this.color.copy(a.color);this.map=a.map;this.lightMap=a.lightMap;this.lightMapIntensity=a.lightMapIntensity;this.aoMap=a.aoMap;this.aoMapIntensity=a.aoMapIntensity;this.emissive.copy(a.emissive);this.emissiveMap=a.emissiveMap;this.emissiveIntensity= +a.emissiveIntensity;this.specularMap=a.specularMap;this.alphaMap=a.alphaMap;this.envMap=a.envMap;this.combine=a.combine;this.reflectivity=a.reflectivity;this.refractionRatio=a.refractionRatio;this.wireframe=a.wireframe;this.wireframeLinewidth=a.wireframeLinewidth;this.wireframeLinecap=a.wireframeLinecap;this.wireframeLinejoin=a.wireframeLinejoin;this.skinning=a.skinning;this.morphTargets=a.morphTargets;this.morphNormals=a.morphNormals;return this};rb.prototype=Object.create(X.prototype);rb.prototype.constructor= +rb;rb.prototype.isLineDashedMaterial=!0;rb.prototype.copy=function(a){X.prototype.copy.call(this,a);this.scale=a.scale;this.dashSize=a.dashSize;this.gapSize=a.gapSize;return this};var rg=Object.freeze({ShadowMaterial:ac,SpriteMaterial:$a,RawShaderMaterial:bc,ShaderMaterial:ya,PointsMaterial:ma,MeshPhysicalMaterial:nb,MeshStandardMaterial:Na,MeshPhongMaterial:Aa,MeshToonMaterial:ob,MeshNormalMaterial:pb,MeshLambertMaterial:qb,MeshDepthMaterial:Xa,MeshDistanceMaterial:Ya,MeshBasicMaterial:oa,LineDashedMaterial:rb, +LineBasicMaterial:X,Material:P}),id={enabled:!1,files:{},add:function(a,b){!1!==this.enabled&&(this.files[a]=b)},get:function(a){if(!1!==this.enabled)return this.files[a]},remove:function(a){delete this.files[a]},clear:function(){this.files={}}},va=new $d;Object.assign(Ia.prototype,{load:function(a,b,c,d){void 0===a&&(a="");void 0!==this.path&&(a=this.path+a);var e=this,f=id.get(a);if(void 0!==f)return e.manager.itemStart(a),setTimeout(function(){b&&b(f);e.manager.itemEnd(a)},0),f;var g=a.match(/^data:(.*?)(;base64)?,(.*)$/); +if(g){var h=g[1],k=!!g[2],g=g[3],g=window.decodeURIComponent(g);k&&(g=window.atob(g));try{var l=(this.responseType||"").toLowerCase();switch(l){case "arraybuffer":case "blob":for(var m=new Uint8Array(g.length),k=0;k=e)break a;else{f=b[1];a=e)break b}d=c;c=0}}for(;c>>1,ab;)--f;++f;if(0!==e||f!==d)e>=f&&(f=Math.max(f,1),e=f-1),a=this.getValueSize(),this.times=V.arraySlice(c,e,f),this.values=V.arraySlice(this.values,e*a,f*a);return this},validate:function(){var a=!0,b=this.getValueSize();0!==b-Math.floor(b)&&(console.error("THREE.KeyframeTrackPrototype: Invalid value size in track.",this),a=!1);var c=this.times,b=this.values,d=c.length;0===d&&(console.error("THREE.KeyframeTrackPrototype: Track is empty.", +this),a=!1);for(var e=null,f=0;f!==d;f++){var g=c[f];if("number"===typeof g&&isNaN(g)){console.error("THREE.KeyframeTrackPrototype: Time is not a valid number.",this,f,g);a=!1;break}if(null!==e&&e>g){console.error("THREE.KeyframeTrackPrototype: Out of order keys.",this,f,g,e);a=!1;break}e=g}if(void 0!==b&&V.isTypedArray(b))for(f=0,c=b.length;f!==c;++f)if(d=b[f],isNaN(d)){console.error("THREE.KeyframeTrackPrototype: Value is not a valid number.",this,f,d);a=!1;break}return a},optimize:function(){for(var a, +b,c=this.times,d=this.values,e=this.getValueSize(),f=2302===this.getInterpolation(),g=1,h=c.length-1,k=1;kl.opacity&&(l.transparent=!0);d.setTextures(k);return d.parse(l)}}()});Object.assign(de.prototype,{load:function(a,b,c,d){var e=this,f=this.texturePath&&"string"===typeof this.texturePath?this.texturePath:ec.prototype.extractUrlBase(a),g=new Ia(this.manager);g.setWithCredentials(this.withCredentials); +g.load(a,function(c){c=JSON.parse(c);var d=c.metadata;if(void 0!==d&&(d=d.type,void 0!==d)){if("object"===d.toLowerCase()){console.error("THREE.JSONLoader: "+a+" should be loaded with THREE.ObjectLoader instead.");return}if("scene"===d.toLowerCase()){console.error("THREE.JSONLoader: "+a+" should be loaded with THREE.SceneLoader instead.");return}}c=e.parse(c,f);b(c.geometry,c.materials)},c,d)},setTexturePath:function(a){this.texturePath=a},parse:function(){return function(a,b){void 0!==a.data&&(a= +a.data);a.scale=void 0!==a.scale?1/a.scale:1;var c=new L,d=a,e,f,g,h=d.faces;var k=d.vertices;var l=d.normals,m=d.colors;var n=d.scale;var u=0;if(void 0!==d.uvs){for(e=0;ef;f++){var z=h[r++];var B=y[2*z];z=y[2*z+1];B=new D(B,z);2!==f&&c.faceVertexUvs[e][t].push(B);0!==f&&c.faceVertexUvs[e][t+1].push(B)}}w&&(w=3*h[r++],v.normal.set(l[w++],l[w++],l[w]),A.normal.copy(v.normal));if(x)for(e=0;4>e;e++)w=3*h[r++],x=new p(l[w++],l[w++],l[w]),2!==e&&v.vertexNormals.push(x),0!== +e&&A.vertexNormals.push(x);n&&(n=h[r++],n=m[n],v.color.setHex(n),A.color.setHex(n));if(k)for(e=0;4>e;e++)n=h[r++],n=m[n],2!==e&&v.vertexColors.push(new H(n)),0!==e&&A.vertexColors.push(new H(n));c.faces.push(v);c.faces.push(A)}else{v=new Qa;v.a=h[r++];v.b=h[r++];v.c=h[r++];t&&(t=h[r++],v.materialIndex=t);t=c.faces.length;if(e)for(e=0;ef;f++)z=h[r++],B=y[2*z],z=y[2*z+1],B=new D(B,z),c.faceVertexUvs[e][t].push(B);w&&(w=3*h[r++],v.normal.set(l[w++], +l[w++],l[w]));if(x)for(e=0;3>e;e++)w=3*h[r++],x=new p(l[w++],l[w++],l[w]),v.vertexNormals.push(x);n&&(n=h[r++],v.color.setHex(m[n]));if(k)for(e=0;3>e;e++)n=h[r++],v.vertexColors.push(new H(m[n]));c.faces.push(v)}}d=a;r=void 0!==d.influencesPerVertex?d.influencesPerVertex:2;if(d.skinWeights)for(g=0,h=d.skinWeights.length;gg)e=a+1;else if(0b&&(b=0);1Number.EPSILON&&(g.normalize(), +c=Math.acos(R.clamp(d[k-1].dot(d[k]),-1,1)),e[k].applyMatrix4(h.makeRotationAxis(g,c))),f[k].crossVectors(d[k],e[k]);if(!0===b)for(c=Math.acos(R.clamp(e[0].dot(e[a]),-1,1)),c/=a,0=b)return b=c[a]-b,a=this.curves[a],c=a.getLength(),a.getPointAt(0===c?0:1-b/c);a++}return null},getLength:function(){var a=this.getCurveLengths();return a[a.length-1]},updateArcLengths:function(){this.needsUpdate=!0;this.cacheLengths=null;this.getCurveLengths()},getCurveLengths:function(){if(this.cacheLengths&&this.cacheLengths.length===this.curves.length)return this.cacheLengths;for(var a=[],b=0,c=0,d=this.curves.length;c< +d;c++)b+=this.curves[c].getLength(),a.push(b);return this.cacheLengths=a},getSpacedPoints:function(a){void 0===a&&(a=40);for(var b=[],c=0;c<=a;c++)b.push(this.getPoint(c/a));this.autoClose&&b.push(b[0]);return b},getPoints:function(a){a=a||12;for(var b=[],c,d=0,e=this.curves;dc;)c+=b;for(;c>b;)c-=b;cb.length-2?b.length-1:a+1],b=b[a>b.length-3?b.length-1:a+2];return new D(Se(c,d.x,e.x,f.x,b.x),Se(c,d.y,e.y,f.y,b.y))};fc.prototype=Object.create(pa.prototype);fc.prototype.constructor=fc;fc.prototype.getPoint=function(a){var b=this.v0,c=this.v1,d=this.v2,e=this.v3;return new D(wb(a,b.x,c.x,d.x,e.x),wb(a,b.y,c.y,d.y,e.y))};gc.prototype=Object.create(pa.prototype);gc.prototype.constructor= +gc;gc.prototype.getPoint=function(a){var b=this.v0,c=this.v1,d=this.v2;return new D(vb(a,b.x,c.x,d.x),vb(a,b.y,c.y,d.y))};var ue=Object.assign(Object.create(Wc.prototype),{fromPoints:function(a){this.moveTo(a[0].x,a[0].y);for(var b=1,c=a.length;bNumber.EPSILON){if(0>l&&(g=b[f],k=-k,h=b[e],l=-l),!(a.yh.y))if(a.y===g.y){if(a.x===g.x)return!0}else{e=l*(a.x-g.x)-k*(a.y-g.y);if(0===e)return!0; +0>e||(d=!d)}}else if(a.y===g.y&&(h.x<=a.x&&a.x<=g.x||g.x<=a.x&&a.x<=h.x))return!0}return d}var e=Ea.isClockWise,f=this.subPaths;if(0===f.length)return[];if(!0===b)return c(f);b=[];if(1===f.length){var g=f[0];var h=new yb;h.curves=g.curves;b.push(h);return b}var k=!e(f[0].getPoints()),k=a?!k:k;h=[];var l=[],m=[],n=0;l[n]=void 0;m[n]=[];for(var p=0,r=f.length;pd&&this._mixBufferRegion(c,a,3*b,1-d,b);for(var d=b,f=b+b;d!==f;++d)if(c[d]!==c[d+b]){e.setValue(c,a);break}},saveOriginalState:function(){var a=this.buffer,b=this.valueSize,c=3*b;this.binding.getValue(a,c);for(var d=b;d!==c;++d)a[d]=a[c+d%b];this.cumulativeWeight=0},restoreOriginalState:function(){this.binding.setValue(this.buffer,3*this.valueSize)},_select:function(a,b,c,d,e){if(.5<=d)for(d= +0;d!==e;++d)a[b+d]=a[c+d]},_slerp:function(a,b,c,d){fa.slerpFlat(a,b,a,b,a,c,d)},_lerp:function(a,b,c,d,e){for(var f=1-d,g=0;g!==e;++g){var h=b+g;a[h]=a[h]*f+a[c+g]*d}}});Object.assign(Ve.prototype,{getValue:function(a,b){this.bind();var c=this._bindings[this._targetGroup.nCachedObjects_];void 0!==c&&c.getValue(a,b)},setValue:function(a,b){for(var c=this._bindings,d=this._targetGroup.nCachedObjects_,e=c.length;d!==e;++d)c[d].setValue(a,b)},bind:function(){for(var a=this._bindings,b=this._targetGroup.nCachedObjects_, +c=a.length;b!==c;++b)a[b].bind()},unbind:function(){for(var a=this._bindings,b=this._targetGroup.nCachedObjects_,c=a.length;b!==c;++b)a[b].unbind()}});Object.assign(Y,{Composite:Ve,create:function(a,b,c){return a&&a.isAnimationObjectGroup?new Y.Composite(a,b,c):new Y(a,b,c)},sanitizeNodeName:function(a){return a.replace(/\s/g,"_").replace(/[^\w-]/g,"")},parseTrackName:function(){var a=new RegExp("^"+/((?:[\w-]+[\/:])*)/.source+/([\w-\.]+)?/.source+/(?:\.([\w-]+)(?:\[(.+)\])?)?/.source+/\.([\w-]+)(?:\[(.+)\])?/.source+ +"$"),b=["material","materials","bones"];return function(c){var d=a.exec(c);if(!d)throw Error("PropertyBinding: Cannot parse trackName: "+c);var d={nodeName:d[2],objectName:d[3],objectIndex:d[4],propertyName:d[5],propertyIndex:d[6]},e=d.nodeName&&d.nodeName.lastIndexOf(".");if(void 0!==e&&-1!==e){var f=d.nodeName.substring(e+1);-1!==b.indexOf(f)&&(d.nodeName=d.nodeName.substring(0,e),d.objectName=f)}if(null===d.propertyName||0===d.propertyName.length)throw Error("PropertyBinding: can not parse propertyName from trackName: "+ +c);return d}}(),findNode:function(a,b){if(!b||""===b||"root"===b||"."===b||-1===b||b===a.name||b===a.uuid)return a;if(a.skeleton){var c=function(a){for(var c=0;c=c){var n=c++,p=b[n];d[p.uuid]=m;b[m]=p;d[l]=n;b[n]=k;k=0;for(l=f;k!==l;++k){var p=e[k], +r=p[m];p[m]=p[n];p[n]=r}}}this.nCachedObjects_=c},uncache:function(a){for(var b,c,d=this._objects,e=d.length,f=this.nCachedObjects_,g=this._indicesByUUID,h=this._bindings,k=h.length,l=0,m=arguments.length;l!==m;++l){c=arguments[l].uuid;var n=g[c];if(void 0!==n)if(delete g[c],nb||0===c)return;this._startTime=null;b*=c}b*=this._updateTimeScale(a);c=this._updateTime(b);a=this._updateWeight(a);if(0c.parameterPositions[1]&&(this.stopFading(),0===d&&(this.enabled=!1))}}return this._effectiveWeight=b},_updateTimeScale:function(a){var b=0;if(!this.paused){var b=this.timeScale,c=this._timeScaleInterpolant;if(null!==c){var d=c.evaluate(a)[0], b=b*d;a>c.parameterPositions[1]&&(this.stopWarping(),0===b?this.paused=!0:this.timeScale=b)}}return this._effectiveTimeScale=b},_updateTime:function(a){var b=this.time+a;if(0===a)return b;var c=this._clip.duration,d=this.loop,e=this._loopCount;if(2200===d)a:{if(-1===e&&(this._loopCount=0,this._setEndings(!0,!0,!1)),b>=c)b=c;else if(0>b)b=0;else break a;this.clampWhenFinished?this.paused=!0:this.enabled=!1;this._mixer.dispatchEvent({type:"finished",action:this,direction:0>a?-1:1})}else{d=2202===d; -1===e&&(0<=a?(e=0,this._setEndings(!0,0===this.repetitions,d)):this._setEndings(0===this.repetitions,!0,d));if(b>=c||0>b){var f=Math.floor(b/c),b=b-c*f,e=e+Math.abs(f),g=this.repetitions-e;0>g?(this.clampWhenFinished?this.paused=!0:this.enabled=!1,b=0a,this._setEndings(a,!a,d)):this._setEndings(!1,!1,d),this._loopCount=e,this._mixer.dispatchEvent({type:"loop",action:this,loopDelta:f}))}if(d&&1===(e&1))return this.time= b,c-b}return this.time=b},_setEndings:function(a,b,c){var d=this._interpolantSettings;c?(d.endingStart=2401,d.endingEnd=2401):(d.endingStart=a?this.zeroSlopeAtStart?2401:2400:2402,d.endingEnd=b?this.zeroSlopeAtEnd?2401:2400:2402)},_scheduleFading:function(a,b,c){var d=this._mixer,e=d.time,f=this._weightInterpolant;null===f&&(this._weightInterpolant=f=d._lendControlInterpolant());d=f.parameterPositions;f=f.sampleValues;d[0]=e;f[0]=b;d[1]=e+a;f[1]=c;return this}});Object.assign(Ye.prototype,sa.prototype, -{_bindAction:function(a,b){var c=a._localRoot||this._root,d=a._clip.tracks,e=d.length,f=a._propertyBindings,g=a._interpolants,h=c.uuid,k=this._bindingsByRootAndName,l=k[h];void 0===l&&(l={},k[h]=l);for(k=0;k!==e;++k){var p=d[k],q=p.name,n=l[q];if(void 0===n){n=f[k];if(void 0!==n){null===n._cacheIndex&&(++n.referenceCount,this._addInactiveBinding(n,h,q));continue}n=new le(oa.create(c,q,b&&b._propertyBindings[k].binding.parsedPath),p.ValueTypeName,p.getValueSize());++n.referenceCount;this._addInactiveBinding(n, -h,q)}f[k]=n;g[k].resultBuffer=n.buffer}},_activateAction:function(a){if(!this._isActiveAction(a)){if(null===a._cacheIndex){var b=(a._localRoot||this._root).uuid,c=a._clip.uuid,d=this._actionsByClip[c];this._bindAction(a,d&&d.knownActions[0]);this._addInactiveAction(a,c,b)}b=a._propertyBindings;c=0;for(d=b.length;c!==d;++c){var e=b[c];0===e.useCount++&&(this._lendBinding(e),e.saveOriginalState())}this._lendAction(a)}},_deactivateAction:function(a){if(this._isActiveAction(a)){for(var b=a._propertyBindings, +{_bindAction:function(a,b){var c=a._localRoot||this._root,d=a._clip.tracks,e=d.length,f=a._propertyBindings;a=a._interpolants;var g=c.uuid,h=this._bindingsByRootAndName,k=h[g];void 0===k&&(k={},h[g]=k);for(h=0;h!==e;++h){var l=d[h],m=l.name,n=k[m];if(void 0===n){n=f[h];if(void 0!==n){null===n._cacheIndex&&(++n.referenceCount,this._addInactiveBinding(n,g,m));continue}n=new le(Y.create(c,m,b&&b._propertyBindings[h].binding.parsedPath),l.ValueTypeName,l.getValueSize());++n.referenceCount;this._addInactiveBinding(n, +g,m)}f[h]=n;a[h].resultBuffer=n.buffer}},_activateAction:function(a){if(!this._isActiveAction(a)){if(null===a._cacheIndex){var b=(a._localRoot||this._root).uuid,c=a._clip.uuid,d=this._actionsByClip[c];this._bindAction(a,d&&d.knownActions[0]);this._addInactiveAction(a,c,b)}b=a._propertyBindings;c=0;for(d=b.length;c!==d;++c){var e=b[c];0===e.useCount++&&(this._lendBinding(e),e.saveOriginalState())}this._lendAction(a)}},_deactivateAction:function(a){if(this._isActiveAction(a)){for(var b=a._propertyBindings, c=0,d=b.length;c!==d;++c){var e=b[c];0===--e.useCount&&(e.restoreOriginalState(),this._takeBackBinding(e))}this._takeBackAction(a)}},_initMemoryManager:function(){this._actions=[];this._nActiveActions=0;this._actionsByClip={};this._bindings=[];this._nActiveBindings=0;this._bindingsByRootAndName={};this._controlInterpolants=[];this._nActiveControlInterpolants=0;var a=this;this.stats={actions:{get total(){return a._actions.length},get inUse(){return a._nActiveActions}},bindings:{get total(){return a._bindings.length}, get inUse(){return a._nActiveBindings}},controlInterpolants:{get total(){return a._controlInterpolants.length},get inUse(){return a._nActiveControlInterpolants}}}},_isActiveAction:function(a){a=a._cacheIndex;return null!==a&&ah.end&& -(h.end=f);c||(c=k)}}for(k in d)h=d[k],this.createAnimation(k,h.start,h.end,a);this.firstAnimation=c};ra.prototype.setAnimationDirectionForward=function(a){if(a=this.animationsMap[a])a.direction=1,a.directionBackwards=!1};ra.prototype.setAnimationDirectionBackward=function(a){if(a=this.animationsMap[a])a.direction=-1,a.directionBackwards=!0};ra.prototype.setAnimationFPS=function(a,b){var c=this.animationsMap[a];c&&(c.fps=b,c.duration=(c.end-c.start)/c.fps)};ra.prototype.setAnimationDuration=function(a, -b){var c=this.animationsMap[a];c&&(c.duration=b,c.fps=(c.end-c.start)/c.duration)};ra.prototype.setAnimationWeight=function(a,b){var c=this.animationsMap[a];c&&(c.weight=b)};ra.prototype.setAnimationTime=function(a,b){var c=this.animationsMap[a];c&&(c.time=b)};ra.prototype.getAnimationTime=function(a){var b=0;if(a=this.animationsMap[a])b=a.time;return b};ra.prototype.getAnimationDuration=function(a){var b=-1;if(a=this.animationsMap[a])b=a.duration;return b};ra.prototype.playAnimation=function(a){var b= -this.animationsMap[a];b?(b.time=0,b.active=!0):console.warn("THREE.MorphBlendMesh: animation["+a+"] undefined in .playAnimation()")};ra.prototype.stopAnimation=function(a){if(a=this.animationsMap[a])a.active=!1};ra.prototype.update=function(a){for(var b=0,c=this.animationsList.length;bd.duration||0>d.time)d.direction*=-1,d.time>d.duration&&(d.time=d.duration,d.directionBackwards= -!0),0>d.time&&(d.time=0,d.directionBackwards=!1)}else d.time%=d.duration,0>d.time&&(d.time+=d.duration);var f=d.start+Y.clamp(Math.floor(d.time/e),0,d.length-1),g=d.weight;f!==d.currentFrame&&(this.morphTargetInfluences[d.lastFrame]=0,this.morphTargetInfluences[d.currentFrame]=1*g,this.morphTargetInfluences[f]=0,d.lastFrame=d.currentFrame,d.currentFrame=f);e=d.time%e/e;d.directionBackwards&&(e=1-e);d.currentFrame!==d.lastFrame?(this.morphTargetInfluences[d.currentFrame]=e*g,this.morphTargetInfluences[d.lastFrame]= -(1-e)*g):this.morphTargetInfluences[d.currentFrame]=g}}};$c.prototype=Object.create(B.prototype);$c.prototype.constructor=$c;$c.prototype.isImmediateRenderObject=!0;ad.prototype=Object.create(da.prototype);ad.prototype.constructor=ad;ad.prototype.update=function(){var a=new p,b=new p,c=new Ka;return function(){var d=["a","b","c"];this.object.updateMatrixWorld(!0);c.getNormalMatrix(this.object.matrixWorld);var e=this.object.matrixWorld,f=this.geometry.attributes.position,g=this.object.geometry;if(g&& -g.isGeometry)for(var h=g.vertices,k=g.faces,l=g=0,p=k.length;lc.y?this.quaternion.set(1,0,0,0):(a.set(c.z,0,-c.x).normalize(),b=Math.acos(c.y),this.quaternion.setFromAxisAngle(a, -b))}}();Cb.prototype.setLength=function(a,b,c){void 0===b&&(b=.2*a);void 0===c&&(c=.2*b);this.line.scale.set(1,Math.max(0,a-b),1);this.line.updateMatrix();this.cone.scale.set(c,b,c);this.cone.position.y=a;this.cone.updateMatrix()};Cb.prototype.setColor=function(a){this.line.material.color.copy(a);this.cone.material.color.copy(a)};Md.prototype=Object.create(da.prototype);Md.prototype.constructor=Md;var Pd=new p,ve=new se,we=new se,xe=new se;Ja.prototype=Object.create(na.prototype);Ja.prototype.constructor= -Ja;Ja.prototype.getPoint=function(a){var b=this.points,c=b.length;a*=c-(this.closed?0:1);var d=Math.floor(a);a-=d;this.closed?d+=0d&&(d=1);1E-4>c&&(c=d);1E-4>h&&(h=d);ve.initNonuniformCatmullRom(e.x,f.x,g.x,b.x,c,d,h);we.initNonuniformCatmullRom(e.y,f.y,g.y,b.y,c,d,h);xe.initNonuniformCatmullRom(e.z,f.z,g.z,b.z,c,d,h)}else"catmullrom"===this.type&&(c=void 0!==this.tension?this.tension:.5,ve.initCatmullRom(e.x,f.x,g.x,b.x,c),we.initCatmullRom(e.y,f.y,g.y,b.y,c),xe.initCatmullRom(e.z,f.z,g.z,b.z,c));return new p(ve.calc(a), -we.calc(a),xe.calc(a))};ed.prototype=Object.create(na.prototype);ed.prototype.constructor=ed;ed.prototype.getPoint=function(a){var b=this.v0,c=this.v1,d=this.v2,e=this.v3;return new p(yb(a,b.x,c.x,d.x,e.x),yb(a,b.y,c.y,d.y,e.y),yb(a,b.z,c.z,d.z,e.z))};fd.prototype=Object.create(na.prototype);fd.prototype.constructor=fd;fd.prototype.getPoint=function(a){var b=this.v0,c=this.v1,d=this.v2;return new p(xb(a,b.x,c.x,d.x),xb(a,b.y,c.y,d.y),xb(a,b.z,c.z,d.z))};gd.prototype=Object.create(na.prototype);gd.prototype.constructor= -gd;gd.prototype.getPoint=function(a){if(1===a)return this.v2.clone();var b=new p;b.subVectors(this.v2,this.v1);b.multiplyScalar(a);b.add(this.v1);return b};Nd.prototype=Object.create(Xa.prototype);Nd.prototype.constructor=Nd;na.create=function(a,b){console.log("THREE.Curve.create() has been deprecated");a.prototype=Object.create(na.prototype);a.prototype.constructor=a;a.prototype.getPoint=b;return a};df.prototype=Object.create(Ja.prototype);ef.prototype=Object.create(Ja.prototype);te.prototype=Object.create(Ja.prototype); -Object.assign(te.prototype,{initFromArray:function(a){console.error("THREE.Spline: .initFromArray() has been removed.")},getControlPointsArray:function(a){console.error("THREE.Spline: .getControlPointsArray() has been removed.")},reparametrizeByArcLength:function(a){console.error("THREE.Spline: .reparametrizeByArcLength() has been removed.")}});bd.prototype.setColors=function(){console.error("THREE.GridHelper: setColors() has been deprecated, pass them in the constructor instead.")};Object.assign(id.prototype, -{center:function(a){console.warn("THREE.Box2: .center() has been renamed to .getCenter().");return this.getCenter(a)},empty:function(){console.warn("THREE.Box2: .empty() has been renamed to .isEmpty().");return this.isEmpty()},isIntersectionBox:function(a){console.warn("THREE.Box2: .isIntersectionBox() has been renamed to .intersectsBox().");return this.intersectsBox(a)},size:function(a){console.warn("THREE.Box2: .size() has been renamed to .getSize().");return this.getSize(a)}});Object.assign(Ta.prototype, -{center:function(a){console.warn("THREE.Box3: .center() has been renamed to .getCenter().");return this.getCenter(a)},empty:function(){console.warn("THREE.Box3: .empty() has been renamed to .isEmpty().");return this.isEmpty()},isIntersectionBox:function(a){console.warn("THREE.Box3: .isIntersectionBox() has been renamed to .intersectsBox().");return this.intersectsBox(a)},isIntersectionSphere:function(a){console.warn("THREE.Box3: .isIntersectionSphere() has been renamed to .intersectsSphere().");return this.intersectsSphere(a)}, -size:function(a){console.warn("THREE.Box3: .size() has been renamed to .getSize().");return this.getSize(a)}});Hb.prototype.center=function(a){console.warn("THREE.Line3: .center() has been renamed to .getCenter().");return this.getCenter(a)};Y.random16=function(){console.warn("THREE.Math.random16() has been deprecated. Use Math.random() instead.");return Math.random()};Object.assign(Ka.prototype,{flattenToArrayOffset:function(a,b){console.warn("THREE.Matrix3: .flattenToArrayOffset() has been deprecated. Use .toArray() instead."); -return this.toArray(a,b)},multiplyVector3:function(a){console.warn("THREE.Matrix3: .multiplyVector3() has been removed. Use vector.applyMatrix3( matrix ) instead.");return a.applyMatrix3(this)},multiplyVector3Array:function(a){console.warn("THREE.Matrix3: .multiplyVector3Array() has been renamed. Use matrix.applyToVector3Array( array ) instead.");return this.applyToVector3Array(a)},applyToBuffer:function(a,b,c){console.warn("THREE.Matrix3: .applyToBuffer() has been removed. Use matrix.applyToBufferAttribute( attribute ) instead."); -return this.applyToBufferAttribute(a)},applyToVector3Array:function(a,b,c){console.error("THREE.Matrix3: .applyToVector3Array() has been removed.")}});Object.assign(J.prototype,{extractPosition:function(a){console.warn("THREE.Matrix4: .extractPosition() has been renamed to .copyPosition().");return this.copyPosition(a)},flattenToArrayOffset:function(a,b){console.warn("THREE.Matrix4: .flattenToArrayOffset() has been deprecated. Use .toArray() instead.");return this.toArray(a,b)},getPosition:function(){var a; -return function(){void 0===a&&(a=new p);console.warn("THREE.Matrix4: .getPosition() has been removed. Use Vector3.setFromMatrixPosition( matrix ) instead.");return a.setFromMatrixColumn(this,3)}}(),setRotationFromQuaternion:function(a){console.warn("THREE.Matrix4: .setRotationFromQuaternion() has been renamed to .makeRotationFromQuaternion().");return this.makeRotationFromQuaternion(a)},multiplyToArray:function(){console.warn("THREE.Matrix4: .multiplyToArray() has been removed.")},multiplyVector3:function(a){console.warn("THREE.Matrix4: .multiplyVector3() has been removed. Use vector.applyMatrix4( matrix ) instead."); -return a.applyMatrix4(this)},multiplyVector4:function(a){console.warn("THREE.Matrix4: .multiplyVector4() has been removed. Use vector.applyMatrix4( matrix ) instead.");return a.applyMatrix4(this)},multiplyVector3Array:function(a){console.warn("THREE.Matrix4: .multiplyVector3Array() has been renamed. Use matrix.applyToVector3Array( array ) instead.");return this.applyToVector3Array(a)},rotateAxis:function(a){console.warn("THREE.Matrix4: .rotateAxis() has been removed. Use Vector3.transformDirection( matrix ) instead."); -a.transformDirection(this)},crossVector:function(a){console.warn("THREE.Matrix4: .crossVector() has been removed. Use vector.applyMatrix4( matrix ) instead.");return a.applyMatrix4(this)},translate:function(){console.error("THREE.Matrix4: .translate() has been removed.")},rotateX:function(){console.error("THREE.Matrix4: .rotateX() has been removed.")},rotateY:function(){console.error("THREE.Matrix4: .rotateY() has been removed.")},rotateZ:function(){console.error("THREE.Matrix4: .rotateZ() has been removed.")}, -rotateByAxis:function(){console.error("THREE.Matrix4: .rotateByAxis() has been removed.")},applyToBuffer:function(a,b,c){console.warn("THREE.Matrix4: .applyToBuffer() has been removed. Use matrix.applyToBufferAttribute( attribute ) instead.");return this.applyToBufferAttribute(a)},applyToVector3Array:function(a,b,c){console.error("THREE.Matrix4: .applyToVector3Array() has been removed.")},makeFrustum:function(a,b,c,d,e,f){console.warn("THREE.Matrix4: .makeFrustum() has been removed. Use .makePerspective( left, right, top, bottom, near, far ) instead."); -return this.makePerspective(a,b,d,c,e,f)}});wa.prototype.isIntersectionLine=function(a){console.warn("THREE.Plane: .isIntersectionLine() has been renamed to .intersectsLine().");return this.intersectsLine(a)};qa.prototype.multiplyVector3=function(a){console.warn("THREE.Quaternion: .multiplyVector3() has been removed. Use is now vector.applyQuaternion( quaternion ) instead.");return a.applyQuaternion(this)};Object.assign(hb.prototype,{isIntersectionBox:function(a){console.warn("THREE.Ray: .isIntersectionBox() has been renamed to .intersectsBox()."); -return this.intersectsBox(a)},isIntersectionPlane:function(a){console.warn("THREE.Ray: .isIntersectionPlane() has been renamed to .intersectsPlane().");return this.intersectsPlane(a)},isIntersectionSphere:function(a){console.warn("THREE.Ray: .isIntersectionSphere() has been renamed to .intersectsSphere().");return this.intersectsSphere(a)}});Object.assign(Ab.prototype,{extrude:function(a){console.warn("THREE.Shape: .extrude() has been removed. Use ExtrudeGeometry() instead.");return new db(this,a)}, -makeGeometry:function(a){console.warn("THREE.Shape: .makeGeometry() has been removed. Use ShapeGeometry() instead.");return new Zb(this,a)}});Object.assign(E.prototype,{fromAttribute:function(a,b,c){console.error("THREE.Vector2: .fromAttribute() has been renamed to .fromBufferAttribute().");return this.fromBufferAttribute(a,b,c)}});Object.assign(p.prototype,{setEulerFromRotationMatrix:function(){console.error("THREE.Vector3: .setEulerFromRotationMatrix() has been removed. Use Euler.setFromRotationMatrix() instead.")}, -setEulerFromQuaternion:function(){console.error("THREE.Vector3: .setEulerFromQuaternion() has been removed. Use Euler.setFromQuaternion() instead.")},getPositionFromMatrix:function(a){console.warn("THREE.Vector3: .getPositionFromMatrix() has been renamed to .setFromMatrixPosition().");return this.setFromMatrixPosition(a)},getScaleFromMatrix:function(a){console.warn("THREE.Vector3: .getScaleFromMatrix() has been renamed to .setFromMatrixScale().");return this.setFromMatrixScale(a)},getColumnFromMatrix:function(a, -b){console.warn("THREE.Vector3: .getColumnFromMatrix() has been renamed to .setFromMatrixColumn().");return this.setFromMatrixColumn(b,a)},applyProjection:function(a){console.warn("THREE.Vector3: .applyProjection() has been removed. Use .applyMatrix4( m ) instead.");return this.applyMatrix4(a)},fromAttribute:function(a,b,c){console.error("THREE.Vector3: .fromAttribute() has been renamed to .fromBufferAttribute().");return this.fromBufferAttribute(a,b,c)}});Object.assign(ga.prototype,{fromAttribute:function(a, -b,c){console.error("THREE.Vector4: .fromAttribute() has been renamed to .fromBufferAttribute().");return this.fromBufferAttribute(a,b,c)}});M.prototype.computeTangents=function(){console.warn("THREE.Geometry: .computeTangents() has been removed.")};Object.assign(B.prototype,{getChildByName:function(a){console.warn("THREE.Object3D: .getChildByName() has been renamed to .getObjectByName().");return this.getObjectByName(a)},renderDepth:function(){console.warn("THREE.Object3D: .renderDepth has been removed. Use .renderOrder, instead.")}, -translate:function(a,b){console.warn("THREE.Object3D: .translate() has been removed. Use .translateOnAxis( axis, distance ) instead.");return this.translateOnAxis(b,a)}});Object.defineProperties(B.prototype,{eulerOrder:{get:function(){console.warn("THREE.Object3D: .eulerOrder is now .rotation.order.");return this.rotation.order},set:function(a){console.warn("THREE.Object3D: .eulerOrder is now .rotation.order.");this.rotation.order=a}},useQuaternion:{get:function(){console.warn("THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.")}, -set:function(){console.warn("THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.")}}});Object.defineProperties(Bc.prototype,{objects:{get:function(){console.warn("THREE.LOD: .objects has been renamed to .levels.");return this.levels}}});Object.defineProperty(Cc.prototype,"useVertexTexture",{get:function(){console.warn("THREE.Skeleton: useVertexTexture has been removed.")},set:function(){console.warn("THREE.Skeleton: useVertexTexture has been removed.")}}); -Object.defineProperty(na.prototype,"__arcLengthDivisions",{get:function(){console.warn("THREE.Curve: .__arcLengthDivisions is now .arcLengthDivisions.");return this.arcLengthDivisions},set:function(a){console.warn("THREE.Curve: .__arcLengthDivisions is now .arcLengthDivisions.");this.arcLengthDivisions=a}});xa.prototype.setLens=function(a,b){console.warn("THREE.PerspectiveCamera.setLens is deprecated. Use .setFocalLength and .filmGauge for a photographic setup.");void 0!==b&&(this.filmGauge=b);this.setFocalLength(a)}; -Object.defineProperties(ma.prototype,{onlyShadow:{set:function(){console.warn("THREE.Light: .onlyShadow has been removed.")}},shadowCameraFov:{set:function(a){console.warn("THREE.Light: .shadowCameraFov is now .shadow.camera.fov.");this.shadow.camera.fov=a}},shadowCameraLeft:{set:function(a){console.warn("THREE.Light: .shadowCameraLeft is now .shadow.camera.left.");this.shadow.camera.left=a}},shadowCameraRight:{set:function(a){console.warn("THREE.Light: .shadowCameraRight is now .shadow.camera.right."); +return c}});Object.assign(af.prototype,{start:function(){this.oldTime=this.startTime=("undefined"===typeof performance?Date:performance).now();this.elapsedTime=0;this.running=!0},stop:function(){this.getElapsedTime();this.autoStart=this.running=!1},getElapsedTime:function(){this.getDelta();return this.elapsedTime},getDelta:function(){var a=0;if(this.autoStart&&!this.running)return this.start(),0;if(this.running){var b=("undefined"===typeof performance?Date:performance).now(),a=(b-this.oldTime)/1E3; +this.oldTime=b;this.elapsedTime+=a}return a}});Object.assign(bf.prototype,{set:function(a,b,c){this.radius=a;this.phi=b;this.theta=c;return this},clone:function(){return(new this.constructor).copy(this)},copy:function(a){this.radius=a.radius;this.phi=a.phi;this.theta=a.theta;return this},makeSafe:function(){this.phi=Math.max(1E-6,Math.min(Math.PI-1E-6,this.phi));return this},setFromVector3:function(a){this.radius=a.length();0===this.radius?this.phi=this.theta=0:(this.theta=Math.atan2(a.x,a.z),this.phi= +Math.acos(R.clamp(a.y/this.radius,-1,1)));return this}});Object.assign(cf.prototype,{set:function(a,b,c){this.radius=a;this.theta=b;this.y=c;return this},clone:function(){return(new this.constructor).copy(this)},copy:function(a){this.radius=a.radius;this.theta=a.theta;this.y=a.y;return this},setFromVector3:function(a){this.radius=Math.sqrt(a.x*a.x+a.z*a.z);this.theta=Math.atan2(a.x,a.z);this.y=a.y;return this}});Zc.prototype=Object.create(z.prototype);Zc.prototype.constructor=Zc;Zc.prototype.isImmediateRenderObject= +!0;$c.prototype=Object.create(T.prototype);$c.prototype.constructor=$c;$c.prototype.update=function(){var a=new p,b=new p,c=new qa;return function(){var d,e=["a","b","c"];this.object.updateMatrixWorld(!0);c.getNormalMatrix(this.object.matrixWorld);var f=this.object.matrixWorld,g=this.geometry.attributes.position;if((d=this.object.geometry)&&d.isGeometry)for(var h=d.vertices,k=d.faces,l=d=0,m=k.length;lMath.abs(b)&&(b=1E-8);this.scale.set(.5*this.size,.5*this.size,b);this.lookAt(this.plane.normal);z.prototype.updateMatrixWorld.call(this,a)};var Kd,re;Ab.prototype=Object.create(z.prototype);Ab.prototype.constructor= +Ab;Ab.prototype.setDirection=function(){var a=new p,b;return function(c){.99999c.y?this.quaternion.set(1,0,0,0):(a.set(c.z,0,-c.x).normalize(),b=Math.acos(c.y),this.quaternion.setFromAxisAngle(a,b))}}();Ab.prototype.setLength=function(a,b,c){void 0===b&&(b=.2*a);void 0===c&&(c=.2*b);this.line.scale.set(1,Math.max(0,a-b),1);this.line.updateMatrix();this.cone.scale.set(c,b,c);this.cone.position.y=a;this.cone.updateMatrix()};Ab.prototype.setColor=function(a){this.line.material.color.copy(a); +this.cone.material.color.copy(a)};Ld.prototype=Object.create(T.prototype);Ld.prototype.constructor=Ld;var Od=new p,ve=new se,we=new se,xe=new se;Ja.prototype=Object.create(pa.prototype);Ja.prototype.constructor=Ja;Ja.prototype.getPoint=function(a){var b=this.points,c=b.length;a*=c-(this.closed?0:1);var d=Math.floor(a);a-=d;this.closed?d+=0d&&(d=1);1E-4>c&&(c=d);1E-4>h&&(h=d);ve.initNonuniformCatmullRom(e.x,f.x,g.x,b.x,c,d,h);we.initNonuniformCatmullRom(e.y,f.y,g.y,b.y,c,d,h);xe.initNonuniformCatmullRom(e.z, +f.z,g.z,b.z,c,d,h)}else"catmullrom"===this.type&&(c=void 0!==this.tension?this.tension:.5,ve.initCatmullRom(e.x,f.x,g.x,b.x,c),we.initCatmullRom(e.y,f.y,g.y,b.y,c),xe.initCatmullRom(e.z,f.z,g.z,b.z,c));return new p(ve.calc(a),we.calc(a),xe.calc(a))};fd.prototype=Object.create(pa.prototype);fd.prototype.constructor=fd;fd.prototype.getPoint=function(a){var b=this.v0,c=this.v1,d=this.v2,e=this.v3;return new p(wb(a,b.x,c.x,d.x,e.x),wb(a,b.y,c.y,d.y,e.y),wb(a,b.z,c.z,d.z,e.z))};gd.prototype=Object.create(pa.prototype); +gd.prototype.constructor=gd;gd.prototype.getPoint=function(a){var b=this.v0,c=this.v1,d=this.v2;return new p(vb(a,b.x,c.x,d.x),vb(a,b.y,c.y,d.y),vb(a,b.z,c.z,d.z))};hd.prototype=Object.create(pa.prototype);hd.prototype.constructor=hd;hd.prototype.getPoint=function(a){if(1===a)return this.v2.clone();var b=new p;b.subVectors(this.v2,this.v1);b.multiplyScalar(a);b.add(this.v1);return b};Md.prototype=Object.create(Ua.prototype);Md.prototype.constructor=Md;pa.create=function(a,b){console.log("THREE.Curve.create() has been deprecated"); +a.prototype=Object.create(pa.prototype);a.prototype.constructor=a;a.prototype.getPoint=b;return a};ef.prototype=Object.create(Ja.prototype);ff.prototype=Object.create(Ja.prototype);te.prototype=Object.create(Ja.prototype);Object.assign(te.prototype,{initFromArray:function(a){console.error("THREE.Spline: .initFromArray() has been removed.")},getControlPointsArray:function(a){console.error("THREE.Spline: .getControlPointsArray() has been removed.")},reparametrizeByArcLength:function(a){console.error("THREE.Spline: .reparametrizeByArcLength() has been removed.")}}); +ad.prototype.setColors=function(){console.error("THREE.GridHelper: setColors() has been deprecated, pass them in the constructor instead.")};kc.prototype.update=function(){console.error("THREE.SkeletonHelper: update() no longer needs to be called.")};Object.assign(jd.prototype,{center:function(a){console.warn("THREE.Box2: .center() has been renamed to .getCenter().");return this.getCenter(a)},empty:function(){console.warn("THREE.Box2: .empty() has been renamed to .isEmpty().");return this.isEmpty()}, +isIntersectionBox:function(a){console.warn("THREE.Box2: .isIntersectionBox() has been renamed to .intersectsBox().");return this.intersectsBox(a)},size:function(a){console.warn("THREE.Box2: .size() has been renamed to .getSize().");return this.getSize(a)}});Object.assign(Pa.prototype,{center:function(a){console.warn("THREE.Box3: .center() has been renamed to .getCenter().");return this.getCenter(a)},empty:function(){console.warn("THREE.Box3: .empty() has been renamed to .isEmpty().");return this.isEmpty()}, +isIntersectionBox:function(a){console.warn("THREE.Box3: .isIntersectionBox() has been renamed to .intersectsBox().");return this.intersectsBox(a)},isIntersectionSphere:function(a){console.warn("THREE.Box3: .isIntersectionSphere() has been renamed to .intersectsSphere().");return this.intersectsSphere(a)},size:function(a){console.warn("THREE.Box3: .size() has been renamed to .getSize().");return this.getSize(a)}});Gb.prototype.center=function(a){console.warn("THREE.Line3: .center() has been renamed to .getCenter()."); +return this.getCenter(a)};R.random16=function(){console.warn("THREE.Math.random16() has been deprecated. Use Math.random() instead.");return Math.random()};Object.assign(qa.prototype,{flattenToArrayOffset:function(a,b){console.warn("THREE.Matrix3: .flattenToArrayOffset() has been deprecated. Use .toArray() instead.");return this.toArray(a,b)},multiplyVector3:function(a){console.warn("THREE.Matrix3: .multiplyVector3() has been removed. Use vector.applyMatrix3( matrix ) instead.");return a.applyMatrix3(this)}, +multiplyVector3Array:function(a){console.error("THREE.Matrix3: .multiplyVector3Array() has been removed.")},applyToBuffer:function(a,b,c){console.warn("THREE.Matrix3: .applyToBuffer() has been removed. Use matrix.applyToBufferAttribute( attribute ) instead.");return this.applyToBufferAttribute(a)},applyToVector3Array:function(a,b,c){console.error("THREE.Matrix3: .applyToVector3Array() has been removed.")}});Object.assign(K.prototype,{extractPosition:function(a){console.warn("THREE.Matrix4: .extractPosition() has been renamed to .copyPosition()."); +return this.copyPosition(a)},flattenToArrayOffset:function(a,b){console.warn("THREE.Matrix4: .flattenToArrayOffset() has been deprecated. Use .toArray() instead.");return this.toArray(a,b)},getPosition:function(){var a;return function(){void 0===a&&(a=new p);console.warn("THREE.Matrix4: .getPosition() has been removed. Use Vector3.setFromMatrixPosition( matrix ) instead.");return a.setFromMatrixColumn(this,3)}}(),setRotationFromQuaternion:function(a){console.warn("THREE.Matrix4: .setRotationFromQuaternion() has been renamed to .makeRotationFromQuaternion()."); +return this.makeRotationFromQuaternion(a)},multiplyToArray:function(){console.warn("THREE.Matrix4: .multiplyToArray() has been removed.")},multiplyVector3:function(a){console.warn("THREE.Matrix4: .multiplyVector3() has been removed. Use vector.applyMatrix4( matrix ) instead.");return a.applyMatrix4(this)},multiplyVector4:function(a){console.warn("THREE.Matrix4: .multiplyVector4() has been removed. Use vector.applyMatrix4( matrix ) instead.");return a.applyMatrix4(this)},multiplyVector3Array:function(a){console.error("THREE.Matrix4: .multiplyVector3Array() has been removed.")}, +rotateAxis:function(a){console.warn("THREE.Matrix4: .rotateAxis() has been removed. Use Vector3.transformDirection( matrix ) instead.");a.transformDirection(this)},crossVector:function(a){console.warn("THREE.Matrix4: .crossVector() has been removed. Use vector.applyMatrix4( matrix ) instead.");return a.applyMatrix4(this)},translate:function(){console.error("THREE.Matrix4: .translate() has been removed.")},rotateX:function(){console.error("THREE.Matrix4: .rotateX() has been removed.")},rotateY:function(){console.error("THREE.Matrix4: .rotateY() has been removed.")}, +rotateZ:function(){console.error("THREE.Matrix4: .rotateZ() has been removed.")},rotateByAxis:function(){console.error("THREE.Matrix4: .rotateByAxis() has been removed.")},applyToBuffer:function(a,b,c){console.warn("THREE.Matrix4: .applyToBuffer() has been removed. Use matrix.applyToBufferAttribute( attribute ) instead.");return this.applyToBufferAttribute(a)},applyToVector3Array:function(a,b,c){console.error("THREE.Matrix4: .applyToVector3Array() has been removed.")},makeFrustum:function(a,b,c,d, +e,f){console.warn("THREE.Matrix4: .makeFrustum() has been removed. Use .makePerspective( left, right, top, bottom, near, far ) instead.");return this.makePerspective(a,b,d,c,e,f)}});za.prototype.isIntersectionLine=function(a){console.warn("THREE.Plane: .isIntersectionLine() has been renamed to .intersectsLine().");return this.intersectsLine(a)};fa.prototype.multiplyVector3=function(a){console.warn("THREE.Quaternion: .multiplyVector3() has been removed. Use is now vector.applyQuaternion( quaternion ) instead."); +return a.applyQuaternion(this)};Object.assign(ib.prototype,{isIntersectionBox:function(a){console.warn("THREE.Ray: .isIntersectionBox() has been renamed to .intersectsBox().");return this.intersectsBox(a)},isIntersectionPlane:function(a){console.warn("THREE.Ray: .isIntersectionPlane() has been renamed to .intersectsPlane().");return this.intersectsPlane(a)},isIntersectionSphere:function(a){console.warn("THREE.Ray: .isIntersectionSphere() has been renamed to .intersectsSphere().");return this.intersectsSphere(a)}}); +Object.assign(yb.prototype,{extrude:function(a){console.warn("THREE.Shape: .extrude() has been removed. Use ExtrudeGeometry() instead.");return new ab(this,a)},makeGeometry:function(a){console.warn("THREE.Shape: .makeGeometry() has been removed. Use ShapeGeometry() instead.");return new Xb(this,a)}});Object.assign(D.prototype,{fromAttribute:function(a,b,c){console.error("THREE.Vector2: .fromAttribute() has been renamed to .fromBufferAttribute().");return this.fromBufferAttribute(a,b,c)}});Object.assign(p.prototype, +{setEulerFromRotationMatrix:function(){console.error("THREE.Vector3: .setEulerFromRotationMatrix() has been removed. Use Euler.setFromRotationMatrix() instead.")},setEulerFromQuaternion:function(){console.error("THREE.Vector3: .setEulerFromQuaternion() has been removed. Use Euler.setFromQuaternion() instead.")},getPositionFromMatrix:function(a){console.warn("THREE.Vector3: .getPositionFromMatrix() has been renamed to .setFromMatrixPosition().");return this.setFromMatrixPosition(a)},getScaleFromMatrix:function(a){console.warn("THREE.Vector3: .getScaleFromMatrix() has been renamed to .setFromMatrixScale()."); +return this.setFromMatrixScale(a)},getColumnFromMatrix:function(a,b){console.warn("THREE.Vector3: .getColumnFromMatrix() has been renamed to .setFromMatrixColumn().");return this.setFromMatrixColumn(b,a)},applyProjection:function(a){console.warn("THREE.Vector3: .applyProjection() has been removed. Use .applyMatrix4( m ) instead.");return this.applyMatrix4(a)},fromAttribute:function(a,b,c){console.error("THREE.Vector3: .fromAttribute() has been renamed to .fromBufferAttribute().");return this.fromBufferAttribute(a, +b,c)}});Object.assign(da.prototype,{fromAttribute:function(a,b,c){console.error("THREE.Vector4: .fromAttribute() has been renamed to .fromBufferAttribute().");return this.fromBufferAttribute(a,b,c)}});L.prototype.computeTangents=function(){console.warn("THREE.Geometry: .computeTangents() has been removed.")};Object.assign(z.prototype,{getChildByName:function(a){console.warn("THREE.Object3D: .getChildByName() has been renamed to .getObjectByName().");return this.getObjectByName(a)},renderDepth:function(){console.warn("THREE.Object3D: .renderDepth has been removed. Use .renderOrder, instead.")}, +translate:function(a,b){console.warn("THREE.Object3D: .translate() has been removed. Use .translateOnAxis( axis, distance ) instead.");return this.translateOnAxis(b,a)}});Object.defineProperties(z.prototype,{eulerOrder:{get:function(){console.warn("THREE.Object3D: .eulerOrder is now .rotation.order.");return this.rotation.order},set:function(a){console.warn("THREE.Object3D: .eulerOrder is now .rotation.order.");this.rotation.order=a}},useQuaternion:{get:function(){console.warn("THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.")}, +set:function(){console.warn("THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.")}}});Object.defineProperties(zc.prototype,{objects:{get:function(){console.warn("THREE.LOD: .objects has been renamed to .levels.");return this.levels}}});Object.defineProperty(Ac.prototype,"useVertexTexture",{get:function(){console.warn("THREE.Skeleton: useVertexTexture has been removed.")},set:function(){console.warn("THREE.Skeleton: useVertexTexture has been removed.")}}); +Object.defineProperty(pa.prototype,"__arcLengthDivisions",{get:function(){console.warn("THREE.Curve: .__arcLengthDivisions is now .arcLengthDivisions.");return this.arcLengthDivisions},set:function(a){console.warn("THREE.Curve: .__arcLengthDivisions is now .arcLengthDivisions.");this.arcLengthDivisions=a}});ha.prototype.setLens=function(a,b){console.warn("THREE.PerspectiveCamera.setLens is deprecated. Use .setFocalLength and .filmGauge for a photographic setup.");void 0!==b&&(this.filmGauge=b);this.setFocalLength(a)}; +Object.defineProperties(ea.prototype,{onlyShadow:{set:function(){console.warn("THREE.Light: .onlyShadow has been removed.")}},shadowCameraFov:{set:function(a){console.warn("THREE.Light: .shadowCameraFov is now .shadow.camera.fov.");this.shadow.camera.fov=a}},shadowCameraLeft:{set:function(a){console.warn("THREE.Light: .shadowCameraLeft is now .shadow.camera.left.");this.shadow.camera.left=a}},shadowCameraRight:{set:function(a){console.warn("THREE.Light: .shadowCameraRight is now .shadow.camera.right."); this.shadow.camera.right=a}},shadowCameraTop:{set:function(a){console.warn("THREE.Light: .shadowCameraTop is now .shadow.camera.top.");this.shadow.camera.top=a}},shadowCameraBottom:{set:function(a){console.warn("THREE.Light: .shadowCameraBottom is now .shadow.camera.bottom.");this.shadow.camera.bottom=a}},shadowCameraNear:{set:function(a){console.warn("THREE.Light: .shadowCameraNear is now .shadow.camera.near.");this.shadow.camera.near=a}},shadowCameraFar:{set:function(a){console.warn("THREE.Light: .shadowCameraFar is now .shadow.camera.far."); this.shadow.camera.far=a}},shadowCameraVisible:{set:function(){console.warn("THREE.Light: .shadowCameraVisible has been removed. Use new THREE.CameraHelper( light.shadow.camera ) instead.")}},shadowBias:{set:function(a){console.warn("THREE.Light: .shadowBias is now .shadow.bias.");this.shadow.bias=a}},shadowDarkness:{set:function(){console.warn("THREE.Light: .shadowDarkness has been removed.")}},shadowMapWidth:{set:function(a){console.warn("THREE.Light: .shadowMapWidth is now .shadow.mapSize.width."); -this.shadow.mapSize.width=a}},shadowMapHeight:{set:function(a){console.warn("THREE.Light: .shadowMapHeight is now .shadow.mapSize.height.");this.shadow.mapSize.height=a}}});Object.defineProperties(L.prototype,{length:{get:function(){console.warn("THREE.BufferAttribute: .length has been deprecated. Use .count instead.");return this.array.length}}});Object.assign(I.prototype,{addIndex:function(a){console.warn("THREE.BufferGeometry: .addIndex() has been renamed to .setIndex().");this.setIndex(a)},addDrawCall:function(a, +this.shadow.mapSize.width=a}},shadowMapHeight:{set:function(a){console.warn("THREE.Light: .shadowMapHeight is now .shadow.mapSize.height.");this.shadow.mapSize.height=a}}});Object.defineProperties(Q.prototype,{length:{get:function(){console.warn("THREE.BufferAttribute: .length has been deprecated. Use .count instead.");return this.array.length}}});Object.assign(E.prototype,{addIndex:function(a){console.warn("THREE.BufferGeometry: .addIndex() has been renamed to .setIndex().");this.setIndex(a)},addDrawCall:function(a, b,c){void 0!==c&&console.warn("THREE.BufferGeometry: .addDrawCall() no longer supports indexOffset.");console.warn("THREE.BufferGeometry: .addDrawCall() is now .addGroup().");this.addGroup(a,b)},clearDrawCalls:function(){console.warn("THREE.BufferGeometry: .clearDrawCalls() is now .clearGroups().");this.clearGroups()},computeTangents:function(){console.warn("THREE.BufferGeometry: .computeTangents() has been removed.")},computeOffsets:function(){console.warn("THREE.BufferGeometry: .computeOffsets() has been removed.")}}); -Object.defineProperties(I.prototype,{drawcalls:{get:function(){console.error("THREE.BufferGeometry: .drawcalls has been renamed to .groups.");return this.groups}},offsets:{get:function(){console.warn("THREE.BufferGeometry: .offsets has been renamed to .groups.");return this.groups}}});Object.defineProperties(Jd.prototype,{dynamic:{set:function(){console.warn("THREE.Uniform: .dynamic has been removed. Use object.onBeforeRender() instead.")}},onUpdate:{value:function(){console.warn("THREE.Uniform: .onUpdate() has been removed. Use object.onBeforeRender() instead."); -return this}}});Object.defineProperties(Z.prototype,{wrapAround:{get:function(){console.warn("THREE.Material: .wrapAround has been removed.")},set:function(){console.warn("THREE.Material: .wrapAround has been removed.")}},wrapRGB:{get:function(){console.warn("THREE.Material: .wrapRGB has been removed.");return new H}}});Object.defineProperties(ta.prototype,{metal:{get:function(){console.warn("THREE.MeshPhongMaterial: .metal has been removed. Use THREE.MeshStandardMaterial instead.");return!1},set:function(){console.warn("THREE.MeshPhongMaterial: .metal has been removed. Use THREE.MeshStandardMaterial instead")}}}); -Object.defineProperties(Ea.prototype,{derivatives:{get:function(){console.warn("THREE.ShaderMaterial: .derivatives has been moved to .extensions.derivatives.");return this.extensions.derivatives},set:function(a){console.warn("THREE. ShaderMaterial: .derivatives has been moved to .extensions.derivatives.");this.extensions.derivatives=a}}});Object.assign(Xd.prototype,{getCurrentRenderTarget:function(){console.warn("THREE.WebGLRenderer: .getCurrentRenderTarget() is now .getRenderTarget().");return this.getRenderTarget()}, -supportsFloatTextures:function(){console.warn("THREE.WebGLRenderer: .supportsFloatTextures() is now .extensions.get( 'OES_texture_float' ).");return this.extensions.get("OES_texture_float")},supportsHalfFloatTextures:function(){console.warn("THREE.WebGLRenderer: .supportsHalfFloatTextures() is now .extensions.get( 'OES_texture_half_float' ).");return this.extensions.get("OES_texture_half_float")},supportsStandardDerivatives:function(){console.warn("THREE.WebGLRenderer: .supportsStandardDerivatives() is now .extensions.get( 'OES_standard_derivatives' )."); -return this.extensions.get("OES_standard_derivatives")},supportsCompressedTextureS3TC:function(){console.warn("THREE.WebGLRenderer: .supportsCompressedTextureS3TC() is now .extensions.get( 'WEBGL_compressed_texture_s3tc' ).");return this.extensions.get("WEBGL_compressed_texture_s3tc")},supportsCompressedTexturePVRTC:function(){console.warn("THREE.WebGLRenderer: .supportsCompressedTexturePVRTC() is now .extensions.get( 'WEBGL_compressed_texture_pvrtc' ).");return this.extensions.get("WEBGL_compressed_texture_pvrtc")}, -supportsBlendMinMax:function(){console.warn("THREE.WebGLRenderer: .supportsBlendMinMax() is now .extensions.get( 'EXT_blend_minmax' ).");return this.extensions.get("EXT_blend_minmax")},supportsVertexTextures:function(){console.warn("THREE.WebGLRenderer: .supportsVertexTextures() is now .capabilities.vertexTextures.");return this.capabilities.vertexTextures},supportsInstancedArrays:function(){console.warn("THREE.WebGLRenderer: .supportsInstancedArrays() is now .extensions.get( 'ANGLE_instanced_arrays' )."); -return this.extensions.get("ANGLE_instanced_arrays")},enableScissorTest:function(a){console.warn("THREE.WebGLRenderer: .enableScissorTest() is now .setScissorTest().");this.setScissorTest(a)},initMaterial:function(){console.warn("THREE.WebGLRenderer: .initMaterial() has been removed.")},addPrePlugin:function(){console.warn("THREE.WebGLRenderer: .addPrePlugin() has been removed.")},addPostPlugin:function(){console.warn("THREE.WebGLRenderer: .addPostPlugin() has been removed.")},updateShadowMap:function(){console.warn("THREE.WebGLRenderer: .updateShadowMap() has been removed.")}}); -Object.defineProperties(Xd.prototype,{shadowMapEnabled:{get:function(){return this.shadowMap.enabled},set:function(a){console.warn("THREE.WebGLRenderer: .shadowMapEnabled is now .shadowMap.enabled.");this.shadowMap.enabled=a}},shadowMapType:{get:function(){return this.shadowMap.type},set:function(a){console.warn("THREE.WebGLRenderer: .shadowMapType is now .shadowMap.type.");this.shadowMap.type=a}},shadowMapCullFace:{get:function(){return this.shadowMap.cullFace},set:function(a){console.warn("THREE.WebGLRenderer: .shadowMapCullFace is now .shadowMap.cullFace."); -this.shadowMap.cullFace=a}}});Object.defineProperties(Je.prototype,{cullFace:{get:function(){return this.renderReverseSided?2:1},set:function(a){a=1!==a;console.warn("WebGLRenderer: .shadowMap.cullFace is deprecated. Set .shadowMap.renderReverseSided to "+a+".");this.renderReverseSided=a}}});Object.defineProperties(Db.prototype,{wrapS:{get:function(){console.warn("THREE.WebGLRenderTarget: .wrapS is now .texture.wrapS.");return this.texture.wrapS},set:function(a){console.warn("THREE.WebGLRenderTarget: .wrapS is now .texture.wrapS."); -this.texture.wrapS=a}},wrapT:{get:function(){console.warn("THREE.WebGLRenderTarget: .wrapT is now .texture.wrapT.");return this.texture.wrapT},set:function(a){console.warn("THREE.WebGLRenderTarget: .wrapT is now .texture.wrapT.");this.texture.wrapT=a}},magFilter:{get:function(){console.warn("THREE.WebGLRenderTarget: .magFilter is now .texture.magFilter.");return this.texture.magFilter},set:function(a){console.warn("THREE.WebGLRenderTarget: .magFilter is now .texture.magFilter.");this.texture.magFilter= -a}},minFilter:{get:function(){console.warn("THREE.WebGLRenderTarget: .minFilter is now .texture.minFilter.");return this.texture.minFilter},set:function(a){console.warn("THREE.WebGLRenderTarget: .minFilter is now .texture.minFilter.");this.texture.minFilter=a}},anisotropy:{get:function(){console.warn("THREE.WebGLRenderTarget: .anisotropy is now .texture.anisotropy.");return this.texture.anisotropy},set:function(a){console.warn("THREE.WebGLRenderTarget: .anisotropy is now .texture.anisotropy.");this.texture.anisotropy= -a}},offset:{get:function(){console.warn("THREE.WebGLRenderTarget: .offset is now .texture.offset.");return this.texture.offset},set:function(a){console.warn("THREE.WebGLRenderTarget: .offset is now .texture.offset.");this.texture.offset=a}},repeat:{get:function(){console.warn("THREE.WebGLRenderTarget: .repeat is now .texture.repeat.");return this.texture.repeat},set:function(a){console.warn("THREE.WebGLRenderTarget: .repeat is now .texture.repeat.");this.texture.repeat=a}},format:{get:function(){console.warn("THREE.WebGLRenderTarget: .format is now .texture.format."); -return this.texture.format},set:function(a){console.warn("THREE.WebGLRenderTarget: .format is now .texture.format.");this.texture.format=a}},type:{get:function(){console.warn("THREE.WebGLRenderTarget: .type is now .texture.type.");return this.texture.type},set:function(a){console.warn("THREE.WebGLRenderTarget: .type is now .texture.type.");this.texture.type=a}},generateMipmaps:{get:function(){console.warn("THREE.WebGLRenderTarget: .generateMipmaps is now .texture.generateMipmaps.");return this.texture.generateMipmaps}, -set:function(a){console.warn("THREE.WebGLRenderTarget: .generateMipmaps is now .texture.generateMipmaps.");this.texture.generateMipmaps=a}}});jc.prototype.load=function(a){console.warn("THREE.Audio: .load has been deprecated. Use THREE.AudioLoader instead.");var b=this;(new fe).load(a,function(a){b.setBuffer(a)});return this};ke.prototype.getData=function(){console.warn("THREE.AudioAnalyser: .getData() is now .getFrequencyData().");return this.getFrequencyData()};l.WebGLRenderTargetCube=Eb;l.WebGLRenderTarget= -Db;l.WebGLRenderer=Xd;l.ShaderLib=ab;l.UniformsLib=U;l.UniformsUtils=Ha;l.ShaderChunk=T;l.FogExp2=Kb;l.Fog=Lb;l.Scene=md;l.LensFlare=Yd;l.Sprite=Ac;l.LOD=Bc;l.SkinnedMesh=od;l.Skeleton=Cc;l.Bone=nd;l.Mesh=Ca;l.LineSegments=da;l.LineLoop=pd;l.Line=ya;l.Points=Mb;l.Group=Dc;l.VideoTexture=qd;l.DataTexture=eb;l.CompressedTexture=Nb;l.CubeTexture=Za;l.CanvasTexture=rd;l.DepthTexture=Ec;l.Texture=X;l.CompressedTextureLoader=Qe;l.DataTextureLoader=$d;l.CubeTextureLoader=ae;l.TextureLoader=sd;l.ObjectLoader= -Re;l.MaterialLoader=Hd;l.BufferGeometryLoader=be;l.DefaultLoadingManager=Aa;l.LoadingManager=Zd;l.JSONLoader=ce;l.ImageLoader=Vc;l.FontLoader=Te;l.FileLoader=ua;l.Loader=gc;l.Cache=hd;l.AudioLoader=fe;l.SpotLightShadow=ud;l.SpotLight=vd;l.PointLight=wd;l.RectAreaLight=Ad;l.HemisphereLight=td;l.DirectionalLightShadow=xd;l.DirectionalLight=yd;l.AmbientLight=zd;l.LightShadow=ub;l.Light=ma;l.StereoCamera=Ue;l.PerspectiveCamera=xa;l.OrthographicCamera=Jb;l.CubeCamera=Id;l.ArrayCamera=ge;l.Camera=Oa;l.AudioListener= -he;l.PositionalAudio=je;l.AudioContext=ie;l.AudioAnalyser=ke;l.Audio=jc;l.VectorKeyframeTrack=ec;l.StringKeyframeTrack=Ed;l.QuaternionKeyframeTrack=Xc;l.NumberKeyframeTrack=fc;l.ColorKeyframeTrack=Gd;l.BooleanKeyframeTrack=Fd;l.PropertyMixer=le;l.PropertyBinding=oa;l.KeyframeTrack=wb;l.AnimationUtils=va;l.AnimationObjectGroup=We;l.AnimationMixer=Ye;l.AnimationClip=Ba;l.Uniform=Jd;l.InstancedBufferGeometry=me;l.BufferGeometry=I;l.GeometryIdCount=function(){return Td++};l.Geometry=M;l.InterleavedBufferAttribute= -ne;l.InstancedInterleavedBuffer=oe;l.InterleavedBuffer=kc;l.InstancedBufferAttribute=pe;l.Face3=Va;l.Object3D=B;l.Raycaster=Ze;l.Layers=Rd;l.EventDispatcher=sa;l.Clock=af;l.QuaternionLinearInterpolant=Dd;l.LinearInterpolant=Wc;l.DiscreteInterpolant=Cd;l.CubicInterpolant=Bd;l.Interpolant=Da;l.Triangle=Ua;l.Math=Y;l.Spherical=bf;l.Cylindrical=cf;l.Plane=wa;l.Frustum=jd;l.Sphere=Ga;l.Ray=hb;l.Matrix4=J;l.Matrix3=Ka;l.Box3=Ta;l.Box2=id;l.Line3=Hb;l.Euler=bb;l.Vector4=ga;l.Vector3=p;l.Vector2=E;l.Quaternion= -qa;l.Color=H;l.MorphBlendMesh=ra;l.ImmediateRenderObject=$c;l.VertexNormalsHelper=ad;l.SpotLightHelper=lc;l.SkeletonHelper=mc;l.PointLightHelper=nc;l.RectAreaLightHelper=oc;l.HemisphereLightHelper=pc;l.GridHelper=bd;l.PolarGridHelper=Kd;l.FaceNormalsHelper=cd;l.DirectionalLightHelper=qc;l.CameraHelper=dd;l.BoxHelper=Bb;l.ArrowHelper=Cb;l.AxisHelper=Md;l.CatmullRomCurve3=Ja;l.CubicBezierCurve3=ed;l.QuadraticBezierCurve3=fd;l.LineCurve3=gd;l.ArcCurve=Nd;l.EllipseCurve=Xa;l.SplineCurve=zb;l.CubicBezierCurve= -hc;l.QuadraticBezierCurve=ic;l.LineCurve=Sa;l.Shape=Ab;l.Path=Zc;l.ShapePath=de;l.Font=ee;l.CurvePath=Yc;l.Curve=na;l.ShapeUtils=za;l.SceneUtils={createMultiMaterialObject:function(a,b){for(var c=new Dc,d=0,e=b.length;d 0 ) { - this.image = image !== undefined ? image : Texture.DEFAULT_IMAGE; - this.mipmaps = []; + console.error( 'THREE.Matrix4: the constructor no longer reads arguments. use .set() instead.' ); - this.mapping = mapping !== undefined ? mapping : Texture.DEFAULT_MAPPING; + } - this.wrapS = wrapS !== undefined ? wrapS : ClampToEdgeWrapping; - this.wrapT = wrapT !== undefined ? wrapT : ClampToEdgeWrapping; +} - this.magFilter = magFilter !== undefined ? magFilter : LinearFilter; - this.minFilter = minFilter !== undefined ? minFilter : LinearMipMapLinearFilter; +Object.assign( Matrix4.prototype, { - this.anisotropy = anisotropy !== undefined ? anisotropy : 1; + isMatrix4: true, - this.format = format !== undefined ? format : RGBAFormat; - this.type = type !== undefined ? type : UnsignedByteType; + set: function ( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) { - this.offset = new Vector2( 0, 0 ); - this.repeat = new Vector2( 1, 1 ); + var te = this.elements; - 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) + 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; - // 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; + return this; - this.version = 0; - this.onUpdate = null; + }, -} + identity: function () { -Texture.DEFAULT_IMAGE = undefined; -Texture.DEFAULT_MAPPING = UVMapping; + this.set( -Object.defineProperty( Texture.prototype, "needsUpdate", { + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 - set: function ( value ) { + ); - if ( value === true ) this.version ++; + return this; - } + }, -} ); + clone: function () { -Object.assign( Texture.prototype, EventDispatcher.prototype, { + return new Matrix4().fromArray( this.elements ); - constructor: Texture, + }, - isTexture: true, + copy: function ( m ) { - clone: function () { + var te = this.elements; + var me = m.elements; - return new this.constructor().copy( this ); + 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; }, - copy: function ( source ) { + copyPosition: function ( m ) { - this.name = source.name; + var te = this.elements, me = m.elements; - this.image = source.image; - this.mipmaps = source.mipmaps.slice( 0 ); + te[ 12 ] = me[ 12 ]; + te[ 13 ] = me[ 13 ]; + te[ 14 ] = me[ 14 ]; - this.mapping = source.mapping; + return this; - this.wrapS = source.wrapS; - this.wrapT = source.wrapT; + }, - this.magFilter = source.magFilter; - this.minFilter = source.minFilter; + extractBasis: function ( xAxis, yAxis, zAxis ) { - this.anisotropy = source.anisotropy; + xAxis.setFromMatrixColumn( this, 0 ); + yAxis.setFromMatrixColumn( this, 1 ); + zAxis.setFromMatrixColumn( this, 2 ); - this.format = source.format; - this.type = source.type; + return this; - this.offset.copy( source.offset ); - this.repeat.copy( source.repeat ); + }, - this.generateMipmaps = source.generateMipmaps; - this.premultiplyAlpha = source.premultiplyAlpha; - this.flipY = source.flipY; - this.unpackAlignment = source.unpackAlignment; - this.encoding = source.encoding; + makeBasis: function ( xAxis, yAxis, zAxis ) { + + 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; }, - toJSON: function ( meta ) { + extractRotation: function () { - if ( meta.textures[ this.uuid ] !== undefined ) { + var v1 = new Vector3(); - return meta.textures[ this.uuid ]; + return function extractRotation( m ) { - } + var te = this.elements; + var me = m.elements; - function getDataURL( image ) { + var scaleX = 1 / v1.setFromMatrixColumn( m, 0 ).length(); + var scaleY = 1 / v1.setFromMatrixColumn( m, 1 ).length(); + var scaleZ = 1 / v1.setFromMatrixColumn( m, 2 ).length(); - var canvas; + te[ 0 ] = me[ 0 ] * scaleX; + te[ 1 ] = me[ 1 ] * scaleX; + te[ 2 ] = me[ 2 ] * scaleX; - if ( image.toDataURL !== undefined ) { + te[ 4 ] = me[ 4 ] * scaleY; + te[ 5 ] = me[ 5 ] * scaleY; + te[ 6 ] = me[ 6 ] * scaleY; - canvas = image; + te[ 8 ] = me[ 8 ] * scaleZ; + te[ 9 ] = me[ 9 ] * scaleZ; + te[ 10 ] = me[ 10 ] * scaleZ; - } else { + return this; - canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' ); - canvas.width = image.width; - canvas.height = image.height; + }; - canvas.getContext( '2d' ).drawImage( image, 0, 0, image.width, image.height ); + }(), - } + makeRotationFromEuler: function ( euler ) { - if ( canvas.width > 2048 || canvas.height > 2048 ) { + if ( ! ( euler && euler.isEuler ) ) { - return canvas.toDataURL( 'image/jpeg', 0.6 ); + console.error( 'THREE.Matrix4: .makeRotationFromEuler() now expects a Euler rotation rather than a Vector3 and order.' ); - } else { + } - return canvas.toDataURL( 'image/png' ); + var te = this.elements; - } + 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 ); - } + if ( euler.order === 'XYZ' ) { - var output = { - metadata: { - version: 4.5, - type: 'Texture', - generator: 'Texture.toJSON' - }, + var ae = a * e, af = a * f, be = b * e, bf = b * f; - uuid: this.uuid, - name: this.name, + te[ 0 ] = c * e; + te[ 4 ] = - c * f; + te[ 8 ] = d; - mapping: this.mapping, + te[ 1 ] = af + be * d; + te[ 5 ] = ae - bf * d; + te[ 9 ] = - b * c; - repeat: [ this.repeat.x, this.repeat.y ], - offset: [ this.offset.x, this.offset.y ], - wrap: [ this.wrapS, this.wrapT ], + te[ 2 ] = bf - ae * d; + te[ 6 ] = be + af * d; + te[ 10 ] = a * c; - minFilter: this.minFilter, - magFilter: this.magFilter, - anisotropy: this.anisotropy, + } else if ( euler.order === 'YXZ' ) { - flipY: this.flipY - }; + var ce = c * e, cf = c * f, de = d * e, df = d * f; - if ( this.image !== undefined ) { + te[ 0 ] = ce + df * b; + te[ 4 ] = de * b - cf; + te[ 8 ] = a * d; - // TODO: Move to THREE.Image + te[ 1 ] = a * f; + te[ 5 ] = a * e; + te[ 9 ] = - b; - var image = this.image; + te[ 2 ] = cf * b - de; + te[ 6 ] = df + ce * b; + te[ 10 ] = a * c; - if ( image.uuid === undefined ) { + } else if ( euler.order === 'ZXY' ) { - image.uuid = _Math.generateUUID(); // UGH + var ce = c * e, cf = c * f, de = d * e, df = d * f; - } + te[ 0 ] = ce - df * b; + te[ 4 ] = - a * f; + te[ 8 ] = de + cf * b; - if ( meta.images[ image.uuid ] === undefined ) { + te[ 1 ] = cf + de * b; + te[ 5 ] = a * e; + te[ 9 ] = df - ce * b; - meta.images[ image.uuid ] = { - uuid: image.uuid, - url: getDataURL( image ) - }; + te[ 2 ] = - a * d; + te[ 6 ] = b; + te[ 10 ] = a * c; - } + } else if ( euler.order === 'ZYX' ) { - output.image = image.uuid; + var ae = a * e, af = a * f, be = b * e, bf = b * f; - } + te[ 0 ] = c * e; + te[ 4 ] = be * d - af; + te[ 8 ] = ae * d + bf; - meta.textures[ this.uuid ] = output; + te[ 1 ] = c * f; + te[ 5 ] = bf * d + ae; + te[ 9 ] = af * d - be; - return output; + te[ 2 ] = - d; + te[ 6 ] = b * c; + te[ 10 ] = a * c; - }, + } else if ( euler.order === 'YZX' ) { - dispose: function () { + var ac = a * c, ad = a * d, bc = b * c, bd = b * d; - this.dispatchEvent( { type: 'dispose' } ); + te[ 0 ] = c * e; + te[ 4 ] = bd - ac * f; + te[ 8 ] = bc * f + ad; - }, + te[ 1 ] = f; + te[ 5 ] = a * e; + te[ 9 ] = - b * e; - transformUv: function ( uv ) { + te[ 2 ] = - d * e; + te[ 6 ] = ad * f + bc; + te[ 10 ] = ac - bd * f; - if ( this.mapping !== UVMapping ) return; + } else if ( euler.order === 'XZY' ) { - uv.multiply( this.repeat ); - uv.add( this.offset ); + var ac = a * c, ad = a * d, bc = b * c, bd = b * d; - if ( uv.x < 0 || uv.x > 1 ) { + te[ 0 ] = c * e; + te[ 4 ] = - f; + te[ 8 ] = d * e; - switch ( this.wrapS ) { + te[ 1 ] = ac * f + bd; + te[ 5 ] = a * e; + te[ 9 ] = ad * f - bc; - case RepeatWrapping: + te[ 2 ] = bc * f - ad; + te[ 6 ] = b * e; + te[ 10 ] = bd * f + ac; - uv.x = uv.x - Math.floor( uv.x ); - break; + } - case ClampToEdgeWrapping: + // last column + te[ 3 ] = 0; + te[ 7 ] = 0; + te[ 11 ] = 0; - uv.x = uv.x < 0 ? 0 : 1; - break; + // bottom row + te[ 12 ] = 0; + te[ 13 ] = 0; + te[ 14 ] = 0; + te[ 15 ] = 1; - case MirroredRepeatWrapping: + return this; - if ( Math.abs( Math.floor( uv.x ) % 2 ) === 1 ) { + }, - uv.x = Math.ceil( uv.x ) - uv.x; + makeRotationFromQuaternion: function ( q ) { - } else { + var te = this.elements; - uv.x = uv.x - Math.floor( uv.x ); + var x = q._x, y = q._y, z = q._z, w = q._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; - } - break; + te[ 0 ] = 1 - ( yy + zz ); + te[ 4 ] = xy - wz; + te[ 8 ] = xz + wy; - } + te[ 1 ] = xy + wz; + te[ 5 ] = 1 - ( xx + zz ); + te[ 9 ] = yz - wx; - } + te[ 2 ] = xz - wy; + te[ 6 ] = yz + wx; + te[ 10 ] = 1 - ( xx + yy ); - if ( uv.y < 0 || uv.y > 1 ) { + // last column + te[ 3 ] = 0; + te[ 7 ] = 0; + te[ 11 ] = 0; - switch ( this.wrapT ) { + // bottom row + te[ 12 ] = 0; + te[ 13 ] = 0; + te[ 14 ] = 0; + te[ 15 ] = 1; - case RepeatWrapping: + return this; - uv.y = uv.y - Math.floor( uv.y ); - break; + }, - case ClampToEdgeWrapping: + lookAt: function () { - uv.y = uv.y < 0 ? 0 : 1; - break; + var x = new Vector3(); + var y = new Vector3(); + var z = new Vector3(); - case MirroredRepeatWrapping: + return function lookAt( eye, target, up ) { - if ( Math.abs( Math.floor( uv.y ) % 2 ) === 1 ) { + var te = this.elements; - uv.y = Math.ceil( uv.y ) - uv.y; + z.subVectors( eye, target ); - } else { + if ( z.lengthSq() === 0 ) { - uv.y = uv.y - Math.floor( uv.y ); + // eye and target are in the same position - } - break; + z.z = 1; } - } + z.normalize(); + x.crossVectors( up, z ); - if ( this.flipY ) { + if ( x.lengthSq() === 0 ) { - uv.y = 1 - uv.y; + // up and z are parallel - } + if ( Math.abs( up.z ) === 1 ) { - } + z.x += 0.0001; -} ); + } else { -/** - * @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 - */ + z.z += 0.0001; -function Vector4( x, y, z, w ) { + } - this.x = x || 0; - this.y = y || 0; - this.z = z || 0; - this.w = ( w !== undefined ) ? w : 1; + z.normalize(); + x.crossVectors( up, z ); -} + } -Object.assign( Vector4.prototype, { + x.normalize(); + y.crossVectors( z, x ); - isVector4: true, + 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; - set: function ( x, y, z, w ) { + return this; - this.x = x; - this.y = y; - this.z = z; - this.w = w; + }; - return this; + }(), - }, + multiply: function ( m, n ) { - setScalar: function ( scalar ) { + if ( n !== undefined ) { - this.x = scalar; - this.y = scalar; - this.z = scalar; - this.w = scalar; + console.warn( 'THREE.Matrix4: .multiply() now only accepts one argument. Use .multiplyMatrices( a, b ) instead.' ); + return this.multiplyMatrices( m, n ); - return this; + } - }, + return this.multiplyMatrices( this, m ); - setX: function ( x ) { + }, - this.x = x; + premultiply: function ( m ) { - return this; + return this.multiplyMatrices( m, this ); }, - setY: function ( y ) { - - this.y = y; - - return this; + multiplyMatrices: function ( a, b ) { - }, + var ae = a.elements; + var be = b.elements; + var te = this.elements; - setZ: function ( z ) { + 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 ]; - this.z = z; + 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 ]; - return this; + 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; - }, + 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; - setW: function ( w ) { + 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; - this.w = w; + 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; }, - setComponent: function ( index, value ) { - - switch ( index ) { + multiplyScalar: function ( s ) { - 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 ); + var 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; }, - getComponent: function ( index ) { + applyToBufferAttribute: function () { - switch ( index ) { + var v1 = new Vector3(); - 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 ); + return function applyToBufferAttribute( attribute ) { - } + for ( var i = 0, l = attribute.count; i < l; i ++ ) { - }, + v1.x = attribute.getX( i ); + v1.y = attribute.getY( i ); + v1.z = attribute.getZ( i ); - clone: function () { + v1.applyMatrix4( this ); - return new this.constructor( this.x, this.y, this.z, this.w ); - - }, + attribute.setXYZ( i, v1.x, v1.y, v1.z ); - copy: function ( v ) { + } - this.x = v.x; - this.y = v.y; - this.z = v.z; - this.w = ( v.w !== undefined ) ? v.w : 1; + return attribute; - return this; + }; - }, + }(), - add: function ( v, w ) { + determinant: function () { - if ( w !== undefined ) { + var te = this.elements; - console.warn( 'THREE.Vector4: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' ); - return this.addVectors( v, w ); + 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 ) - this.x += v.x; - this.y += v.y; - this.z += v.z; - this.w += v.w; + 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; + ); }, - addScalar: function ( s ) { - - this.x += s; - this.y += s; - this.z += s; - this.w += s; - - return this; + transpose: function () { - }, + var te = this.elements; + var tmp; - addVectors: function ( a, b ) { + 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; - this.x = a.x + b.x; - this.y = a.y + b.y; - this.z = a.z + b.z; - this.w = a.w + b.w; + 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; return this; }, - addScaledVector: function ( v, s ) { + setPosition: function ( v ) { - this.x += v.x * s; - this.y += v.y * s; - this.z += v.z * s; - this.w += v.w * s; + var te = this.elements; + + te[ 12 ] = v.x; + te[ 13 ] = v.y; + te[ 14 ] = v.z; return this; }, - sub: function ( v, w ) { + getInverse: function ( m, throwOnDegenerate ) { - if ( w !== undefined ) { + // based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm + var te = this.elements, + me = m.elements, - console.warn( 'THREE.Vector4: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' ); - return this.subVectors( v, w ); + 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 ], - } + 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; - this.x -= v.x; - this.y -= v.y; - this.z -= v.z; - this.w -= v.w; + var det = n11 * t11 + n21 * t12 + n31 * t13 + n41 * t14; - return this; + if ( det === 0 ) { - }, + var msg = "THREE.Matrix4: .getInverse() can't invert matrix, determinant is 0"; - subScalar: function ( s ) { + if ( throwOnDegenerate === true ) { - this.x -= s; - this.y -= s; - this.z -= s; - this.w -= s; + throw new Error( msg ); - return this; + } else { - }, + console.warn( msg ); - subVectors: function ( a, b ) { + } - 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(); - return this; + } - }, + var detInv = 1 / det; - multiplyScalar: function ( scalar ) { + 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; - this.x *= scalar; - this.y *= scalar; - this.z *= scalar; - this.w *= scalar; + 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; + + 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; + + 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; }, - applyMatrix4: function ( m ) { + scale: function ( v ) { - var x = this.x, y = this.y, z = this.z, w = this.w; - var e = m.elements; + var te = this.elements; + var x = v.x, y = v.y, z = v.z; - 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; + 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; return this; }, - divideScalar: function ( scalar ) { - - return this.multiplyScalar( 1 / scalar ); - - }, - - setAxisAngleFromQuaternion: function ( q ) { - - // http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm + getMaxScaleOnAxis: function () { - // q is assumed to be normalized + var te = this.elements; - this.w = 2 * Math.acos( q.w ); + 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 ]; - var s = Math.sqrt( 1 - q.w * q.w ); + return Math.sqrt( Math.max( scaleXSq, scaleYSq, scaleZSq ) ); - if ( s < 0.0001 ) { + }, - this.x = 1; - this.y = 0; - this.z = 0; + makeTranslation: function ( x, y, z ) { - } else { + this.set( - this.x = q.x / s; - this.y = q.y / s; - this.z = q.z / s; + 1, 0, 0, x, + 0, 1, 0, y, + 0, 0, 1, z, + 0, 0, 0, 1 - } + ); return this; }, - setAxisAngleFromRotationMatrix: function ( m ) { - - // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm - - // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) - - 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 - - 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 ]; - - if ( ( Math.abs( m12 - m21 ) < epsilon ) && - ( Math.abs( m13 - m31 ) < epsilon ) && - ( Math.abs( m23 - m32 ) < epsilon ) ) { - - // singularity found - // first check for identity matrix which must have +1 for all terms - // in leading diagonal and zero in other terms + makeRotationX: function ( theta ) { - if ( ( Math.abs( m12 + m21 ) < epsilon2 ) && - ( Math.abs( m13 + m31 ) < epsilon2 ) && - ( Math.abs( m23 + m32 ) < epsilon2 ) && - ( Math.abs( m11 + m22 + m33 - 3 ) < epsilon2 ) ) { + var c = Math.cos( theta ), s = Math.sin( theta ); - // this singularity is identity matrix so angle = 0 + this.set( - this.set( 1, 0, 0, 0 ); + 1, 0, 0, 0, + 0, c, - s, 0, + 0, s, c, 0, + 0, 0, 0, 1 - return this; // zero angle, arbitrary axis + ); - } + return this; - // otherwise this singularity is angle = 180 + }, - angle = Math.PI; + makeRotationY: function ( theta ) { - 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; + var c = Math.cos( theta ), s = Math.sin( theta ); - if ( ( xx > yy ) && ( xx > zz ) ) { + this.set( - // m11 is the largest diagonal term + c, 0, s, 0, + 0, 1, 0, 0, + - s, 0, c, 0, + 0, 0, 0, 1 - if ( xx < epsilon ) { + ); - x = 0; - y = 0.707106781; - z = 0.707106781; + return this; - } else { + }, - x = Math.sqrt( xx ); - y = xy / x; - z = xz / x; + makeRotationZ: function ( theta ) { - } + var c = Math.cos( theta ), s = Math.sin( theta ); - } else if ( yy > zz ) { + this.set( - // m22 is the largest diagonal term + c, - s, 0, 0, + s, c, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 - if ( yy < epsilon ) { + ); - x = 0.707106781; - y = 0; - z = 0.707106781; + return this; - } else { + }, - y = Math.sqrt( yy ); - x = xy / y; - z = yz / y; + makeRotationAxis: function ( axis, angle ) { - } + // Based on http://www.gamedev.net/reference/articles/article1199.asp - } else { + 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; - // m33 is the largest diagonal term so base result on this + this.set( - if ( zz < epsilon ) { + 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 - x = 0.707106781; - y = 0.707106781; - z = 0; + ); - } else { + return this; - z = Math.sqrt( zz ); - x = xz / z; - y = yz / z; + }, - } + makeScale: function ( x, y, z ) { - } + this.set( - this.set( x, y, z, angle ); + x, 0, 0, 0, + 0, y, 0, 0, + 0, 0, z, 0, + 0, 0, 0, 1 - return this; // return 180 deg rotation + ); - } + return this; - // as we have reached here there are no singularities so we can handle normally + }, - var s = Math.sqrt( ( m32 - m23 ) * ( m32 - m23 ) + - ( m13 - m31 ) * ( m13 - m31 ) + - ( m21 - m12 ) * ( m21 - m12 ) ); // used to normalize + makeShear: function ( x, y, z ) { - if ( Math.abs( s ) < 0.001 ) s = 1; + this.set( - // 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 + 1, y, z, 0, + x, 1, z, 0, + x, y, 1, 0, + 0, 0, 0, 1 - 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; }, - min: function ( v ) { + compose: function ( position, quaternion, scale ) { - 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 ); + this.makeRotationFromQuaternion( quaternion ); + this.scale( scale ); + this.setPosition( position ); return this; }, - max: function ( v ) { + decompose: function () { - 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 ); + var vector = new Vector3(); + var matrix = new Matrix4(); - return this; + return function decompose( position, quaternion, scale ) { - }, + var te = this.elements; - clamp: function ( min, max ) { + var sx = vector.set( te[ 0 ], te[ 1 ], te[ 2 ] ).length(); + var sy = vector.set( te[ 4 ], te[ 5 ], te[ 6 ] ).length(); + var sz = vector.set( te[ 8 ], te[ 9 ], te[ 10 ] ).length(); - // This function assumes min < max, if this assumption isn't true it will not operate correctly + // if determine is negative, we need to invert one scale + var det = this.determinant(); + if ( det < 0 ) sx = - sx; - 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 ) ); + position.x = te[ 12 ]; + position.y = te[ 13 ]; + position.z = te[ 14 ]; - return this; + // scale the rotation part + matrix.copy( this ); - }, + var invSX = 1 / sx; + var invSY = 1 / sy; + var invSZ = 1 / sz; - clampScalar: function () { + matrix.elements[ 0 ] *= invSX; + matrix.elements[ 1 ] *= invSX; + matrix.elements[ 2 ] *= invSX; + + matrix.elements[ 4 ] *= invSY; + matrix.elements[ 5 ] *= invSY; + matrix.elements[ 6 ] *= invSY; - var min = new Vector4(); - var max = new Vector4(); + matrix.elements[ 8 ] *= invSZ; + matrix.elements[ 9 ] *= invSZ; + matrix.elements[ 10 ] *= invSZ; - return function clampScalar( minVal, maxVal ) { + quaternion.setFromRotationMatrix( matrix ); - min.set( minVal, minVal, minVal, minVal ); - max.set( maxVal, maxVal, maxVal, maxVal ); + scale.x = sx; + scale.y = sy; + scale.z = sz; - return this.clamp( min, max ); + return this; }; }(), - floor: function () { + makePerspective: function ( left, right, top, bottom, near, far ) { - this.x = Math.floor( this.x ); - this.y = Math.floor( this.y ); - this.z = Math.floor( this.z ); - this.w = Math.floor( this.w ); + if ( far === undefined ) { - return this; + console.warn( 'THREE.Matrix4: .makePerspective() has been redefined and has a new signature. Please check the docs.' ); - }, + } - ceil: function () { + var te = this.elements; + var x = 2 * near / ( right - left ); + var y = 2 * near / ( top - bottom ); - this.x = Math.ceil( this.x ); - this.y = Math.ceil( this.y ); - this.z = Math.ceil( this.z ); - this.w = Math.ceil( this.w ); + 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 ); + + 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; return this; }, - 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 ); - - return this; + makeOrthographic: function ( left, right, top, bottom, near, far ) { - }, + var te = this.elements; + var w = 1.0 / ( right - left ); + var h = 1.0 / ( top - bottom ); + var p = 1.0 / ( far - near ); - roundToZero: function () { + var x = ( right + left ) * w; + var y = ( top + bottom ) * h; + var z = ( far + near ) * p; - 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 ); + 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; }, - negate: function () { + equals: function ( matrix ) { - this.x = - this.x; - this.y = - this.y; - this.z = - this.z; - this.w = - this.w; + var te = this.elements; + var me = matrix.elements; - return this; + for ( var i = 0; i < 16; i ++ ) { - }, + if ( te[ i ] !== me[ i ] ) return false; - dot: function ( v ) { + } - return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w; + return true; }, - lengthSq: function () { + fromArray: function ( array, offset ) { - return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w; + if ( offset === undefined ) offset = 0; - }, + for ( var i = 0; i < 16; i ++ ) { - length: function () { + this.elements[ i ] = array[ i + offset ]; - return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w ); - - }, - - lengthManhattan: function () { - - return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ) + Math.abs( this.w ); - - }, - - normalize: function () { - - return this.divideScalar( this.length() ); - - }, - - setLength: function ( length ) { - - return this.multiplyScalar( length / this.length() ); - - }, - - lerp: function ( v, alpha ) { - - 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: function ( v1, v2, alpha ) { - - return this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 ); - - }, - - equals: function ( v ) { - - return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) && ( v.w === this.w ) ); - - }, - - fromArray: function ( array, offset ) { - - if ( offset === undefined ) offset = 0; - - this.x = array[ offset ]; - this.y = array[ offset + 1 ]; - this.z = array[ offset + 2 ]; - this.w = array[ offset + 3 ]; - - return this; + } + + return this; }, @@ -1830,138 +1858,34 @@ Object.assign( Vector4.prototype, { if ( array === undefined ) array = []; if ( offset === undefined ) offset = 0; - array[ offset ] = this.x; - array[ offset + 1 ] = this.y; - array[ offset + 2 ] = this.z; - array[ offset + 3 ] = this.w; - - return array; - - }, - - fromBufferAttribute: function ( attribute, index, offset ) { - - if ( offset !== undefined ) { - - console.warn( 'THREE.Vector4: offset has been removed from .fromBufferAttribute().' ); - - } - - this.x = attribute.getX( index ); - this.y = attribute.getY( index ); - this.z = attribute.getZ( index ); - this.w = attribute.getW( index ); - - return this; - - } - -} ); - -/** - * @author szimek / https://github.com/szimek/ - * @author alteredq / http://alteredqualia.com/ - * @author Marius Kintel / https://github.com/kintel - */ - -/* - 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 ) { - - this.uuid = _Math.generateUUID(); - - this.width = width; - this.height = height; - - this.scissor = new Vector4( 0, 0, width, height ); - this.scissorTest = false; - - this.viewport = new Vector4( 0, 0, width, height ); - - options = options || {}; - - if ( options.minFilter === undefined ) options.minFilter = LinearFilter; - - this.texture = new Texture( undefined, undefined, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding ); - - this.depthBuffer = options.depthBuffer !== undefined ? options.depthBuffer : true; - this.stencilBuffer = options.stencilBuffer !== undefined ? options.stencilBuffer : true; - this.depthTexture = options.depthTexture !== undefined ? options.depthTexture : null; - -} - -Object.assign( WebGLRenderTarget.prototype, EventDispatcher.prototype, { - - isWebGLRenderTarget: true, - - setSize: function ( width, height ) { - - if ( this.width !== width || this.height !== height ) { - - this.width = width; - this.height = height; - - this.dispose(); - - } - - this.viewport.set( 0, 0, width, height ); - this.scissor.set( 0, 0, width, height ); - - }, - - clone: function () { - - return new this.constructor().copy( this ); - - }, - - copy: function ( source ) { - - this.width = source.width; - this.height = source.height; - - this.viewport.copy( source.viewport ); - - this.texture = source.texture.clone(); + var te = this.elements; - this.depthBuffer = source.depthBuffer; - this.stencilBuffer = source.stencilBuffer; - this.depthTexture = source.depthTexture; + array[ offset ] = te[ 0 ]; + array[ offset + 1 ] = te[ 1 ]; + array[ offset + 2 ] = te[ 2 ]; + array[ offset + 3 ] = te[ 3 ]; - return this; + 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 ]; + array[ offset + 9 ] = te[ 9 ]; + array[ offset + 10 ] = te[ 10 ]; + array[ offset + 11 ] = te[ 11 ]; - dispose: function () { + array[ offset + 12 ] = te[ 12 ]; + array[ offset + 13 ] = te[ 13 ]; + array[ offset + 14 ] = te[ 14 ]; + array[ offset + 15 ] = te[ 15 ]; - this.dispatchEvent( { type: 'dispose' } ); + return array; } } ); -/** - * @author alteredq / http://alteredqualia.com - */ - -function WebGLRenderTargetCube( width, height, options ) { - - WebGLRenderTarget.call( this, width, height, options ); - - this.activeCubeFace = 0; // PX 0, NX 1, PY 2, NY 3, PZ 4, NZ 5 - this.activeMipMapLevel = 0; - -} - -WebGLRenderTargetCube.prototype = Object.create( WebGLRenderTarget.prototype ); -WebGLRenderTargetCube.prototype.constructor = WebGLRenderTargetCube; - -WebGLRenderTargetCube.prototype.isWebGLRenderTargetCube = true; - /** * @author mikael emtinger / http://gomo.se/ * @author alteredq / http://alteredqualia.com/ @@ -2158,7 +2082,7 @@ Object.assign( Quaternion.prototype, { setFromEuler: function ( euler, update ) { - if ( ( euler && euler.isEuler ) === false ) { + if ( ! ( euler && euler.isEuler ) ) { throw new Error( 'THREE.Quaternion: .setFromEuler() now expects an Euler rotation rather than a Vector3 and order.' ); @@ -2570,7 +2494,7 @@ Object.assign( Quaternion.prototype, { /** * @author mrdoob / http://mrdoob.com/ - * @author *kile / http://kile.stravaganza.org/ + * @author kile / http://kile.stravaganza.org/ * @author philogb / http://blog.thejit.org/ * @author mikael emtinger / http://gomo.se/ * @author egraether / http://egraether.com/ @@ -2804,7 +2728,7 @@ Object.assign( Vector3.prototype, { return function applyEuler( euler ) { - if ( ( euler && euler.isEuler ) === false ) { + if ( ! ( euler && euler.isEuler ) ) { console.error( 'THREE.Vector3: .applyEuler() now expects an Euler rotation rather than a Vector3 and order.' ); @@ -2846,12 +2770,13 @@ Object.assign( Vector3.prototype, { var x = this.x, y = this.y, z = this.z; var e = m.elements; - this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ]; - this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ]; - this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ]; - var w = e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ]; + 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.divideScalar( w ); + return this; }, @@ -2957,7 +2882,7 @@ Object.assign( Vector3.prototype, { clamp: function ( min, max ) { - // This function assumes min < max, if this assumption isn't true it will not operate correctly + // 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 ) ); @@ -2987,7 +2912,7 @@ Object.assign( Vector3.prototype, { var length = this.length(); - return this.multiplyScalar( Math.max( min, Math.min( max, length ) ) / length ); + return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) ); }, @@ -3069,13 +2994,13 @@ Object.assign( Vector3.prototype, { normalize: function () { - return this.divideScalar( this.length() ); + return this.divideScalar( this.length() || 1 ); }, setLength: function ( length ) { - return this.multiplyScalar( length / this.length() ); + return this.normalize().multiplyScalar( length ); }, @@ -3218,7 +3143,13 @@ Object.assign( Vector3.prototype, { setFromMatrixPosition: function ( m ) { - return this.setFromMatrixColumn( m, 3 ); + var e = m.elements; + + this.x = e[ 12 ]; + this.y = e[ 13 ]; + this.z = e[ 14 ]; + + return this; }, @@ -3238,7 +3169,6 @@ Object.assign( Vector3.prototype, { setFromMatrixColumn: function ( m, index ) { - return this.fromArray( m.elements, index * 4 ); }, @@ -3293,49 +3223,41 @@ Object.assign( Vector3.prototype, { } ); /** - * @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 + * @author bhouston / http://clara.io + * @author tschw */ -function Matrix4() { +function Matrix3() { this.elements = [ - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1 + 1, 0, 0, + 0, 1, 0, + 0, 0, 1 ]; if ( arguments.length > 0 ) { - console.error( 'THREE.Matrix4: the constructor no longer reads arguments. use .set() instead.' ); + console.error( 'THREE.Matrix3: the constructor no longer reads arguments. use .set() instead.' ); } } -Object.assign( Matrix4.prototype, { +Object.assign( Matrix3.prototype, { - isMatrix4: true, + isMatrix3: true, - set: function ( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) { + set: function ( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) { 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; + 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; @@ -3345,10 +3267,9 @@ Object.assign( Matrix4.prototype, { this.set( - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1 + 1, 0, 0, + 0, 1, 0, + 0, 0, 1 ); @@ -3358,7 +3279,7 @@ Object.assign( Matrix4.prototype, { clone: function () { - return new Matrix4().fromArray( this.elements ); + return new this.constructor().fromArray( this.elements ); }, @@ -3367,842 +3288,1359 @@ Object.assign( Matrix4.prototype, { var te = this.elements; var me = m.elements; - 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; - - }, - - copyPosition: function ( m ) { - - var te = this.elements, me = m.elements; - - te[ 12 ] = me[ 12 ]; - te[ 13 ] = me[ 13 ]; - te[ 14 ] = me[ 14 ]; + 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; }, - extractBasis: function ( xAxis, yAxis, zAxis ) { - - xAxis.setFromMatrixColumn( this, 0 ); - yAxis.setFromMatrixColumn( this, 1 ); - zAxis.setFromMatrixColumn( this, 2 ); + setFromMatrix4: function ( m ) { - return this; + var me = m.elements; - }, + this.set( - makeBasis: function ( xAxis, yAxis, zAxis ) { + me[ 0 ], me[ 4 ], me[ 8 ], + me[ 1 ], me[ 5 ], me[ 9 ], + me[ 2 ], me[ 6 ], me[ 10 ] - 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; }, - extractRotation: function () { + applyToBufferAttribute: function () { var v1 = new Vector3(); - return function extractRotation( m ) { + return function applyToBufferAttribute( attribute ) { - var te = this.elements; - var me = m.elements; + for ( var i = 0, l = attribute.count; i < l; i ++ ) { - var scaleX = 1 / v1.setFromMatrixColumn( m, 0 ).length(); - var scaleY = 1 / v1.setFromMatrixColumn( m, 1 ).length(); - var scaleZ = 1 / v1.setFromMatrixColumn( m, 2 ).length(); + v1.x = attribute.getX( i ); + v1.y = attribute.getY( i ); + v1.z = attribute.getZ( i ); - te[ 0 ] = me[ 0 ] * scaleX; - te[ 1 ] = me[ 1 ] * scaleX; - te[ 2 ] = me[ 2 ] * scaleX; + v1.applyMatrix3( this ); - te[ 4 ] = me[ 4 ] * scaleY; - te[ 5 ] = me[ 5 ] * scaleY; - te[ 6 ] = me[ 6 ] * scaleY; + attribute.setXYZ( i, v1.x, v1.y, v1.z ); - te[ 8 ] = me[ 8 ] * scaleZ; - te[ 9 ] = me[ 9 ] * scaleZ; - te[ 10 ] = me[ 10 ] * scaleZ; + } - return this; + return attribute; }; }(), - makeRotationFromEuler: function ( euler ) { - - if ( ( euler && euler.isEuler ) === false ) { - - console.error( 'THREE.Matrix: .makeRotationFromEuler() now expects a Euler rotation rather than a Vector3 and order.' ); - - } + multiply: function ( m ) { - var te = this.elements; + return this.multiplyMatrices( this, m ); - 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 ); + }, - if ( euler.order === 'XYZ' ) { + premultiply: function ( m ) { - var ae = a * e, af = a * f, be = b * e, bf = b * f; + return this.multiplyMatrices( m, this ); - 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; + multiplyMatrices: function ( a, b ) { - te[ 2 ] = bf - ae * d; - te[ 6 ] = be + af * d; - te[ 10 ] = a * c; + var ae = a.elements; + var be = b.elements; + var te = this.elements; - } else if ( euler.order === 'YXZ' ) { + 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 ]; - var ce = c * e, cf = c * f, de = d * e, df = d * f; + 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 ]; - te[ 0 ] = ce + df * b; - te[ 4 ] = de * b - cf; - te[ 8 ] = a * d; + te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31; + te[ 3 ] = a11 * b12 + a12 * b22 + a13 * b32; + te[ 6 ] = a11 * b13 + a12 * b23 + a13 * b33; - te[ 1 ] = a * f; - te[ 5 ] = a * e; - te[ 9 ] = - b; + te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31; + te[ 4 ] = a21 * b12 + a22 * b22 + a23 * b32; + te[ 7 ] = a21 * b13 + a22 * b23 + a23 * b33; - te[ 2 ] = cf * b - de; - te[ 6 ] = df + ce * b; - te[ 10 ] = a * c; + te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31; + te[ 5 ] = a31 * b12 + a32 * b22 + a33 * b32; + te[ 8 ] = a31 * b13 + a32 * b23 + a33 * b33; - } else if ( euler.order === 'ZXY' ) { + return this; - var ce = c * e, cf = c * f, de = d * e, df = d * f; + }, - te[ 0 ] = ce - df * b; - te[ 4 ] = - a * f; - te[ 8 ] = de + cf * b; + multiplyScalar: function ( s ) { - te[ 1 ] = cf + de * b; - te[ 5 ] = a * e; - te[ 9 ] = df - ce * b; + var te = this.elements; - te[ 2 ] = - a * d; - te[ 6 ] = b; - te[ 10 ] = a * c; + 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; - } else if ( euler.order === 'ZYX' ) { + return this; - var ae = a * e, af = a * f, be = b * e, bf = b * f; + }, - te[ 0 ] = c * e; - te[ 4 ] = be * d - af; - te[ 8 ] = ae * d + bf; + determinant: function () { - te[ 1 ] = c * f; - te[ 5 ] = bf * d + ae; - te[ 9 ] = af * d - be; + var te = this.elements; - te[ 2 ] = - d; - te[ 6 ] = b * c; - te[ 10 ] = a * c; + 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 ]; - } else if ( euler.order === 'YZX' ) { + return a * e * i - a * f * h - b * d * i + b * f * g + c * d * h - c * e * g; - 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; + getInverse: function ( matrix, throwOnDegenerate ) { - te[ 1 ] = f; - te[ 5 ] = a * e; - te[ 9 ] = - b * e; + if ( matrix && matrix.isMatrix4 ) { - te[ 2 ] = - d * e; - te[ 6 ] = ad * f + bc; - te[ 10 ] = ac - bd * f; + console.error( "THREE.Matrix3: .getInverse() no longer takes a Matrix4 argument." ); - } else if ( euler.order === 'XZY' ) { + } - var ac = a * c, ad = a * d, bc = b * c, bd = b * d; + var me = matrix.elements, + te = this.elements, - te[ 0 ] = c * e; - te[ 4 ] = - f; - te[ 8 ] = d * e; + 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 ], - te[ 1 ] = ac * f + bd; - te[ 5 ] = a * e; - te[ 9 ] = ad * f - bc; + t11 = n33 * n22 - n32 * n23, + t12 = n32 * n13 - n33 * n12, + t13 = n23 * n12 - n22 * n13, - te[ 2 ] = bc * f - ad; - te[ 6 ] = b * e; - te[ 10 ] = bd * f + ac; + det = n11 * t11 + n21 * t12 + n31 * t13; - } + if ( det === 0 ) { - // last column - te[ 3 ] = 0; - te[ 7 ] = 0; - te[ 11 ] = 0; + var msg = "THREE.Matrix3: .getInverse() can't invert matrix, determinant is 0"; - // bottom row - te[ 12 ] = 0; - te[ 13 ] = 0; - te[ 14 ] = 0; - te[ 15 ] = 1; + if ( throwOnDegenerate === true ) { - return this; + throw new Error( msg ); - }, + } else { - makeRotationFromQuaternion: function ( q ) { + console.warn( msg ); - var te = this.elements; + } - var x = q._x, y = q._y, z = q._z, w = q._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.identity(); - te[ 0 ] = 1 - ( yy + zz ); - te[ 4 ] = xy - wz; - te[ 8 ] = xz + wy; + } - te[ 1 ] = xy + wz; - te[ 5 ] = 1 - ( xx + zz ); - te[ 9 ] = yz - wx; + var detInv = 1 / det; - te[ 2 ] = xz - wy; - te[ 6 ] = yz + wx; - te[ 10 ] = 1 - ( xx + yy ); + te[ 0 ] = t11 * detInv; + te[ 1 ] = ( n31 * n23 - n33 * n21 ) * detInv; + te[ 2 ] = ( n32 * n21 - n31 * n22 ) * detInv; - // last column - te[ 3 ] = 0; - te[ 7 ] = 0; - te[ 11 ] = 0; + te[ 3 ] = t12 * detInv; + te[ 4 ] = ( n33 * n11 - n31 * n13 ) * detInv; + te[ 5 ] = ( n31 * n12 - n32 * n11 ) * detInv; - // bottom row - te[ 12 ] = 0; - te[ 13 ] = 0; - te[ 14 ] = 0; - te[ 15 ] = 1; + te[ 6 ] = t13 * detInv; + te[ 7 ] = ( n21 * n13 - n23 * n11 ) * detInv; + te[ 8 ] = ( n22 * n11 - n21 * n12 ) * detInv; return this; }, - lookAt: function () { + transpose: function () { - var x = new Vector3(); - var y = new Vector3(); - var z = new Vector3(); + var tmp, m = this.elements; - return function lookAt( eye, target, up ) { + 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; - var te = this.elements; + return this; - z.subVectors( eye, target ); + }, - if ( z.lengthSq() === 0 ) { + getNormalMatrix: function ( matrix4 ) { - // eye and target are in the same position + return this.setFromMatrix4( matrix4 ).getInverse( this ).transpose(); - z.z = 1; + }, + + transposeIntoArray: function ( r ) { + + 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 ]; + + return this; + + }, + + setUvTransform: function ( tx, ty, sx, sy, rotation, cx, cy ) { + + var c = Math.cos( rotation ); + var s = Math.sin( rotation ); + + this.set( + sx * c, sx * s, - sx * ( c * cx + s * cy ) + cx + tx, + - sy * s, sy * c, - sy * ( - s * cx + c * cy ) + cy + ty, + 0, 0, 1 + ); + + }, + + scale: function ( sx, sy ) { + + var te = this.elements; + + te[ 0 ] *= sx; te[ 3 ] *= sx; te[ 6 ] *= sx; + te[ 1 ] *= sy; te[ 4 ] *= sy; te[ 7 ] *= sy; + + 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 ]; + + te[ 0 ] = c * a11 + s * a21; + te[ 3 ] = c * a12 + s * a22; + te[ 6 ] = c * a13 + s * a23; + + te[ 1 ] = - s * a11 + c * a21; + te[ 4 ] = - s * a12 + c * a22; + te[ 7 ] = - s * a13 + c * a23; + + return this; + + }, + + translate: function ( tx, ty ) { + + var te = this.elements; + + 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; + + }, + + equals: function ( matrix ) { + + var te = this.elements; + var me = matrix.elements; + + for ( var i = 0; i < 9; i ++ ) { + + if ( te[ i ] !== me[ i ] ) return false; + + } + + return true; + + }, + + fromArray: function ( array, offset ) { + + if ( offset === undefined ) offset = 0; + + for ( var i = 0; i < 9; i ++ ) { + + this.elements[ i ] = array[ i + offset ]; + + } + + return this; + + }, + + toArray: function ( array, offset ) { + + if ( array === undefined ) array = []; + if ( offset === undefined ) offset = 0; + + var te = this.elements; + + array[ offset ] = te[ 0 ]; + array[ offset + 1 ] = te[ 1 ]; + array[ offset + 2 ] = te[ 2 ]; + + 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 ]; + + return array; + + } + +} ); + +/** + * @author mrdoob / http://mrdoob.com/ + * @author alteredq / http://alteredqualia.com/ + * @author szimek / https://github.com/szimek/ + */ + +var textureId = 0; + +function Texture( image, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ) { + + Object.defineProperty( this, 'id', { value: textureId ++ } ); + + this.uuid = _Math.generateUUID(); + + this.name = ''; + + this.image = image !== undefined ? image : Texture.DEFAULT_IMAGE; + this.mipmaps = []; + + this.mapping = mapping !== undefined ? mapping : Texture.DEFAULT_MAPPING; + + this.wrapS = wrapS !== undefined ? wrapS : ClampToEdgeWrapping; + this.wrapT = wrapT !== undefined ? wrapT : ClampToEdgeWrapping; + + this.magFilter = magFilter !== undefined ? magFilter : LinearFilter; + this.minFilter = minFilter !== undefined ? minFilter : LinearMipMapLinearFilter; + + this.anisotropy = anisotropy !== undefined ? anisotropy : 1; + + this.format = format !== undefined ? format : RGBAFormat; + this.type = type !== undefined ? type : UnsignedByteType; + + this.offset = new Vector2( 0, 0 ); + this.repeat = new Vector2( 1, 1 ); + this.rotation = 0; + + 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) + + // 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.version = 0; + this.onUpdate = null; + +} + +Texture.DEFAULT_IMAGE = undefined; +Texture.DEFAULT_MAPPING = UVMapping; + +Object.defineProperty( Texture.prototype, "needsUpdate", { + + set: function ( value ) { + + if ( value === true ) this.version ++; + + } + +} ); + +Object.assign( Texture.prototype, EventDispatcher.prototype, { + + constructor: Texture, + + isTexture: true, + + clone: function () { + + return new this.constructor().copy( this ); + + }, + + copy: function ( source ) { + + this.name = source.name; + + this.image = source.image; + this.mipmaps = source.mipmaps.slice( 0 ); + + this.mapping = source.mapping; + + this.wrapS = source.wrapS; + this.wrapT = source.wrapT; + + this.magFilter = source.magFilter; + this.minFilter = source.minFilter; + + this.anisotropy = source.anisotropy; + + this.format = source.format; + this.type = source.type; + + this.offset.copy( source.offset ); + this.repeat.copy( source.repeat ); + this.rotation = source.rotation; + + 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.encoding = source.encoding; + + return this; + + }, + + toJSON: function ( meta ) { + + if ( meta.textures[ this.uuid ] !== undefined ) { + + return meta.textures[ this.uuid ]; + + } + + function getDataURL( image ) { + + var canvas; + + if ( image instanceof HTMLCanvasElement ) { + + canvas = image; + + } else { + + canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' ); + canvas.width = image.width; + canvas.height = image.height; + + var context = canvas.getContext( '2d' ); + + if ( image instanceof ImageData ) { + + context.putImageData( image, 0, 0 ); + + } else { + + context.drawImage( image, 0, 0, image.width, image.height ); + + } } - z.normalize(); - x.crossVectors( up, z ); + if ( canvas.width > 2048 || canvas.height > 2048 ) { - if ( x.lengthSq() === 0 ) { + return canvas.toDataURL( 'image/jpeg', 0.6 ); - // eye and target are in the same vertical + } else { - z.z += 0.0001; - x.crossVectors( up, z ); + return canvas.toDataURL( 'image/png' ); } - x.normalize(); - y.crossVectors( z, x ); + } - 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; + var output = { + metadata: { + version: 4.5, + type: 'Texture', + generator: 'Texture.toJSON' + }, - return this; + uuid: this.uuid, + name: this.name, + mapping: this.mapping, + + repeat: [ this.repeat.x, this.repeat.y ], + offset: [ this.offset.x, this.offset.y ], + rotation: this.rotation, + + wrap: [ this.wrapS, this.wrapT ], + + minFilter: this.minFilter, + magFilter: this.magFilter, + anisotropy: this.anisotropy, + + flipY: this.flipY }; - }(), + if ( this.image !== undefined ) { - multiply: function ( m, n ) { + // TODO: Move to THREE.Image - if ( n !== undefined ) { + var image = this.image; - console.warn( 'THREE.Matrix4: .multiply() now only accepts one argument. Use .multiplyMatrices( a, b ) instead.' ); - return this.multiplyMatrices( m, n ); + if ( image.uuid === undefined ) { + + image.uuid = _Math.generateUUID(); // UGH + + } + + if ( meta.images[ image.uuid ] === undefined ) { + + meta.images[ image.uuid ] = { + uuid: image.uuid, + url: getDataURL( image ) + }; + + } + + output.image = image.uuid; } - return this.multiplyMatrices( this, m ); + meta.textures[ this.uuid ] = output; + + return output; }, - premultiply: function ( m ) { + dispose: function () { - return this.multiplyMatrices( m, this ); + this.dispatchEvent( { type: 'dispose' } ); }, - multiplyMatrices: function ( a, b ) { + transformUv: function ( uv ) { - var ae = a.elements; - var be = b.elements; - var te = this.elements; + if ( this.mapping !== UVMapping ) return; - 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 ]; + uv.applyMatrix3( this.matrix ); - 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 ]; + if ( uv.x < 0 || uv.x > 1 ) { - 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; + switch ( this.wrapS ) { - 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; + case RepeatWrapping: - 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; + uv.x = uv.x - Math.floor( uv.x ); + break; - 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; + case ClampToEdgeWrapping: + + uv.x = uv.x < 0 ? 0 : 1; + break; + + case MirroredRepeatWrapping: + + if ( Math.abs( Math.floor( uv.x ) % 2 ) === 1 ) { + + uv.x = Math.ceil( uv.x ) - uv.x; + + } else { + + uv.x = uv.x - Math.floor( uv.x ); + + } + break; + + } + + } + + if ( uv.y < 0 || uv.y > 1 ) { + + switch ( this.wrapT ) { + + case RepeatWrapping: + + uv.y = uv.y - Math.floor( uv.y ); + break; + + case ClampToEdgeWrapping: + + uv.y = uv.y < 0 ? 0 : 1; + break; + + case MirroredRepeatWrapping: + + if ( Math.abs( Math.floor( uv.y ) % 2 ) === 1 ) { + + uv.y = Math.ceil( uv.y ) - uv.y; + + } else { + + uv.y = uv.y - Math.floor( uv.y ); + + } + break; + + } + + } + + if ( this.flipY ) { + + uv.y = 1 - uv.y; + + } + + } + +} ); + +/** + * @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.assign( Vector4.prototype, { + + isVector4: true, + + set: function ( x, y, z, w ) { + + this.x = x; + this.y = y; + this.z = z; + this.w = w; return this; }, - multiplyScalar: function ( s ) { + setScalar: function ( scalar ) { - var te = this.elements; + this.x = scalar; + this.y = scalar; + this.z = scalar; + this.w = scalar; - 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; + + }, + + setX: function ( x ) { + + this.x = x; return this; }, - applyToBufferAttribute: function () { + setY: function ( y ) { - var v1 = new Vector3(); + this.y = y; - return function applyToBufferAttribute( attribute ) { + return this; - for ( var i = 0, l = attribute.count; i < l; i ++ ) { + }, - v1.x = attribute.getX( i ); - v1.y = attribute.getY( i ); - v1.z = attribute.getZ( i ); + setZ: function ( z ) { - v1.applyMatrix4( this ); + this.z = z; - attribute.setXYZ( i, v1.x, v1.y, v1.z ); + return this; + + }, + + setW: function ( w ) { + + this.w = w; + + return this; + + }, + + setComponent: function ( index, value ) { + + 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 ); + + } + + return this; + + }, + + getComponent: function ( index ) { + + switch ( index ) { + + 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 ); + + } + + }, + + clone: function () { + + return new this.constructor( this.x, this.y, this.z, this.w ); + + }, + + copy: function ( v ) { + + this.x = v.x; + this.y = v.y; + this.z = v.z; + this.w = ( v.w !== undefined ) ? v.w : 1; + + return this; + + }, + + add: function ( v, w ) { + + if ( w !== undefined ) { + + console.warn( 'THREE.Vector4: .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; + this.w += v.w; + + return this; + + }, + + addScalar: function ( s ) { + + this.x += s; + this.y += s; + this.z += s; + this.w += s; + + return this; + + }, + + addVectors: function ( a, b ) { + + 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; + + }, + + addScaledVector: function ( v, s ) { + + this.x += v.x * s; + this.y += v.y * s; + this.z += v.z * s; + this.w += v.w * s; + + return this; + + }, + + sub: function ( v, w ) { + + if ( w !== undefined ) { + + console.warn( 'THREE.Vector4: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' ); + return this.subVectors( v, w ); + + } + + this.x -= v.x; + this.y -= v.y; + this.z -= v.z; + this.w -= v.w; + + return this; + + }, + + subScalar: function ( s ) { + + this.x -= s; + this.y -= s; + this.z -= s; + this.w -= s; + + return this; + + }, + + subVectors: function ( a, b ) { + + 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; + + }, + + multiplyScalar: function ( scalar ) { + + this.x *= scalar; + this.y *= scalar; + this.z *= scalar; + this.w *= scalar; + + return this; + + }, + + applyMatrix4: function ( m ) { + + var x = this.x, y = this.y, z = this.z, w = this.w; + var e = m.elements; + + 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; + + }, + + divideScalar: function ( scalar ) { + + return this.multiplyScalar( 1 / scalar ); + + }, + + setAxisAngleFromQuaternion: function ( q ) { + + // http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm + + // q is assumed to be normalized + + this.w = 2 * Math.acos( q.w ); + + var s = Math.sqrt( 1 - q.w * q.w ); + + if ( s < 0.0001 ) { + + this.x = 1; + this.y = 0; + this.z = 0; + + } else { + + this.x = q.x / s; + this.y = q.y / s; + this.z = q.z / s; + + } + + return this; + + }, + + setAxisAngleFromRotationMatrix: function ( m ) { + + // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm + + // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) + + 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 + + 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 ]; + + if ( ( Math.abs( m12 - m21 ) < epsilon ) && + ( Math.abs( m13 - m31 ) < epsilon ) && + ( Math.abs( m23 - m32 ) < epsilon ) ) { + + // 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 ) ) { + + // this singularity is identity matrix so angle = 0 + + this.set( 1, 0, 0, 0 ); + + return this; // zero angle, arbitrary axis } - return attribute; + // otherwise this singularity is angle = 180 - }; + angle = Math.PI; - }(), + 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; - determinant: function () { + if ( ( xx > yy ) && ( xx > zz ) ) { - var te = this.elements; + // m11 is the largest diagonal term - 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 ]; + if ( xx < epsilon ) { - //TODO: make this more efficient - //( based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm ) + x = 0; + y = 0.707106781; + z = 0.707106781; - 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 - ) + } else { + + x = Math.sqrt( xx ); + y = xy / x; + z = xz / x; + + } + + } else if ( yy > zz ) { + + // m22 is the largest diagonal term + + if ( yy < epsilon ) { + + x = 0.707106781; + y = 0; + z = 0.707106781; + + } else { + + y = Math.sqrt( yy ); + x = xy / y; + z = yz / y; + + } + + } else { + + // m33 is the largest diagonal term so base result on this + + if ( zz < epsilon ) { + + x = 0.707106781; + y = 0.707106781; + z = 0; + + } else { + + z = Math.sqrt( zz ); + x = xz / z; + y = yz / z; + + } + + } + + this.set( x, y, z, angle ); + + return this; // return 180 deg rotation + + } + + // as we have reached here there are no singularities so we can handle normally + + var 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; - }, + // 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 - transpose: function () { + this.x = ( m32 - m23 ) / s; + this.y = ( m13 - m31 ) / s; + this.z = ( m21 - m12 ) / s; + this.w = Math.acos( ( m11 + m22 + m33 - 1 ) / 2 ); - var te = this.elements; - var tmp; + return this; - 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; + 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 ); + this.w = Math.min( this.w, v.w ); return this; }, - setPosition: function ( v ) { - - var te = this.elements; + max: function ( v ) { - te[ 12 ] = v.x; - te[ 13 ] = v.y; - te[ 14 ] = v.z; + 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 ); return this; }, - getInverse: function ( m, throwOnDegenerate ) { - - // based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm - var te = this.elements, - me = m.elements, + clamp: function ( min, max ) { - 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 ], + // assumes min < max, componentwise - 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; + 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 ) ); - var det = n11 * t11 + n21 * t12 + n31 * t13 + n41 * t14; + return this; - if ( det === 0 ) { + }, - var msg = "THREE.Matrix4.getInverse(): can't invert matrix, determinant is 0"; + clampScalar: function () { - if ( throwOnDegenerate === true ) { + var min, max; - throw new Error( msg ); + return function clampScalar( minVal, maxVal ) { - } else { + if ( min === undefined ) { - console.warn( msg ); + min = new Vector4(); + max = new Vector4(); } - return this.identity(); - - } + min.set( minVal, minVal, minVal, minVal ); + max.set( maxVal, maxVal, maxVal, maxVal ); - var detInv = 1 / det; + return this.clamp( min, max ); - 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; + }(), - 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; + clampLength: function ( min, max ) { - 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; + var length = this.length(); - return this; + return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) ); }, - scale: function ( v ) { - - var te = this.elements; - var x = v.x, y = v.y, z = v.z; + floor: function () { - 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; + 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; }, - getMaxScaleOnAxis: function () { - - var te = this.elements; + ceil: function () { - 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 ]; + 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 Math.sqrt( Math.max( scaleXSq, scaleYSq, scaleZSq ) ); + return this; }, - makeTranslation: function ( x, y, z ) { - - this.set( - - 1, 0, 0, x, - 0, 1, 0, y, - 0, 0, 1, z, - 0, 0, 0, 1 + 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 ); return this; }, - makeRotationX: function ( theta ) { - - var c = Math.cos( theta ), s = Math.sin( theta ); - - this.set( - - 1, 0, 0, 0, - 0, c, - s, 0, - 0, s, c, 0, - 0, 0, 0, 1 + 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 ); + 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 ); return this; }, - makeRotationY: function ( theta ) { - - var c = Math.cos( theta ), s = Math.sin( theta ); - - this.set( - - c, 0, s, 0, - 0, 1, 0, 0, - - s, 0, c, 0, - 0, 0, 0, 1 + negate: function () { - ); + this.x = - this.x; + this.y = - this.y; + this.z = - this.z; + this.w = - this.w; return this; }, - makeRotationZ: function ( theta ) { - - var c = Math.cos( theta ), s = Math.sin( theta ); + dot: function ( v ) { - this.set( + return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w; - c, - s, 0, 0, - s, c, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1 + }, - ); + lengthSq: function () { - return this; + return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w; }, - makeRotationAxis: function ( axis, angle ) { + length: function () { - // Based on http://www.gamedev.net/reference/articles/article1199.asp + return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w ); - 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; + }, - this.set( + lengthManhattan: function () { - 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 + return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ) + Math.abs( this.w ); - ); + }, - return this; + normalize: function () { + + return this.divideScalar( this.length() || 1 ); }, - makeScale: function ( x, y, z ) { + setLength: function ( length ) { - this.set( + return this.normalize().multiplyScalar( length ); - x, 0, 0, 0, - 0, y, 0, 0, - 0, 0, z, 0, - 0, 0, 0, 1 + }, - ); + lerp: function ( v, alpha ) { + + 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; }, - makeShear: function ( x, y, z ) { + lerpVectors: function ( v1, v2, alpha ) { - this.set( + return this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 ); - 1, y, z, 0, - x, 1, z, 0, - x, y, 1, 0, - 0, 0, 0, 1 + }, - ); + equals: function ( v ) { - return this; + return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) && ( v.w === this.w ) ); }, - compose: function ( position, quaternion, scale ) { + fromArray: function ( array, offset ) { - this.makeRotationFromQuaternion( quaternion ); - this.scale( scale ); - this.setPosition( position ); + if ( offset === undefined ) offset = 0; + + this.x = array[ offset ]; + this.y = array[ offset + 1 ]; + this.z = array[ offset + 2 ]; + this.w = array[ offset + 3 ]; return this; }, - decompose: function () { - - var vector = new Vector3(); - var matrix = new Matrix4(); - - return function decompose( position, quaternion, scale ) { - - var te = this.elements; + toArray: function ( array, offset ) { - var sx = vector.set( te[ 0 ], te[ 1 ], te[ 2 ] ).length(); - var sy = vector.set( te[ 4 ], te[ 5 ], te[ 6 ] ).length(); - var sz = vector.set( te[ 8 ], te[ 9 ], te[ 10 ] ).length(); + if ( array === undefined ) array = []; + if ( offset === undefined ) offset = 0; - // if determine is negative, we need to invert one scale - var det = this.determinant(); - if ( det < 0 ) sx = - sx; + array[ offset ] = this.x; + array[ offset + 1 ] = this.y; + array[ offset + 2 ] = this.z; + array[ offset + 3 ] = this.w; - position.x = te[ 12 ]; - position.y = te[ 13 ]; - position.z = te[ 14 ]; + return array; - // scale the rotation part - matrix.copy( this ); + }, - var invSX = 1 / sx; - var invSY = 1 / sy; - var invSZ = 1 / sz; + fromBufferAttribute: function ( attribute, index, offset ) { - matrix.elements[ 0 ] *= invSX; - matrix.elements[ 1 ] *= invSX; - matrix.elements[ 2 ] *= invSX; + if ( offset !== undefined ) { - matrix.elements[ 4 ] *= invSY; - matrix.elements[ 5 ] *= invSY; - matrix.elements[ 6 ] *= invSY; + console.warn( 'THREE.Vector4: offset has been removed from .fromBufferAttribute().' ); - matrix.elements[ 8 ] *= invSZ; - matrix.elements[ 9 ] *= invSZ; - matrix.elements[ 10 ] *= invSZ; + } - quaternion.setFromRotationMatrix( matrix ); + this.x = attribute.getX( index ); + this.y = attribute.getY( index ); + this.z = attribute.getZ( index ); + this.w = attribute.getW( index ); - scale.x = sx; - scale.y = sy; - scale.z = sz; + return this; - return this; + } - }; +} ); - }(), +/** + * @author szimek / https://github.com/szimek/ + * @author alteredq / http://alteredqualia.com/ + * @author Marius Kintel / https://github.com/kintel + */ - makePerspective: function ( left, right, top, bottom, near, far ) { +/* + 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 ) { - if ( far === undefined ) { + this.uuid = _Math.generateUUID(); - console.warn( 'THREE.Matrix4: .makePerspective() has been redefined and has a new signature. Please check the docs.' ); + this.width = width; + this.height = height; - } + this.scissor = new Vector4( 0, 0, width, height ); + this.scissorTest = false; - var te = this.elements; - var x = 2 * near / ( right - left ); - var y = 2 * near / ( top - bottom ); + this.viewport = new Vector4( 0, 0, width, height ); - 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 ); + options = options || {}; - 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; + if ( options.minFilter === undefined ) options.minFilter = LinearFilter; - return this; + this.texture = new Texture( undefined, undefined, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding ); - }, + this.depthBuffer = options.depthBuffer !== undefined ? options.depthBuffer : true; + this.stencilBuffer = options.stencilBuffer !== undefined ? options.stencilBuffer : true; + this.depthTexture = options.depthTexture !== undefined ? options.depthTexture : null; - makeOrthographic: function ( left, right, top, bottom, near, far ) { +} - var te = this.elements; - var w = 1.0 / ( right - left ); - var h = 1.0 / ( top - bottom ); - var p = 1.0 / ( far - near ); +Object.assign( WebGLRenderTarget.prototype, EventDispatcher.prototype, { - var x = ( right + left ) * w; - var y = ( top + bottom ) * h; - var z = ( far + near ) * p; + isWebGLRenderTarget: true, - 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; + setSize: function ( width, height ) { - return this; + if ( this.width !== width || this.height !== height ) { - }, + this.width = width; + this.height = height; - equals: function ( matrix ) { + this.dispose(); - var te = this.elements; - var me = matrix.elements; + } - for ( var i = 0; i < 16; i ++ ) { + this.viewport.set( 0, 0, width, height ); + this.scissor.set( 0, 0, width, height ); - if ( te[ i ] !== me[ i ] ) return false; + }, - } + clone: function () { - return true; + return new this.constructor().copy( this ); }, - fromArray: function ( array, offset ) { + copy: function ( source ) { - if ( offset === undefined ) offset = 0; + this.width = source.width; + this.height = source.height; - for ( var i = 0; i < 16; i ++ ) { + this.viewport.copy( source.viewport ); - this.elements[ i ] = array[ i + offset ]; + this.texture = source.texture.clone(); - } + this.depthBuffer = source.depthBuffer; + this.stencilBuffer = source.stencilBuffer; + this.depthTexture = source.depthTexture; return this; }, - toArray: function ( array, offset ) { + dispose: function () { - if ( array === undefined ) array = []; - if ( offset === undefined ) offset = 0; + this.dispatchEvent( { type: 'dispose' } ); - var te = this.elements; + } - array[ offset ] = te[ 0 ]; - array[ offset + 1 ] = te[ 1 ]; - array[ offset + 2 ] = te[ 2 ]; - 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 ]; +/** + * @author alteredq / http://alteredqualia.com + */ - array[ offset + 8 ] = te[ 8 ]; - array[ offset + 9 ] = te[ 9 ]; - array[ offset + 10 ] = te[ 10 ]; - array[ offset + 11 ] = te[ 11 ]; +function WebGLRenderTargetCube( width, height, options ) { - array[ offset + 12 ] = te[ 12 ]; - array[ offset + 13 ] = te[ 13 ]; - array[ offset + 14 ] = te[ 14 ]; - array[ offset + 15 ] = te[ 15 ]; + WebGLRenderTarget.call( this, width, height, options ); - return array; + this.activeCubeFace = 0; // PX 0, NX 1, PY 2, NY 3, PZ 4, NZ 5 + this.activeMipMapLevel = 0; - } +} -} ); +WebGLRenderTargetCube.prototype = Object.create( WebGLRenderTarget.prototype ); +WebGLRenderTargetCube.prototype.constructor = WebGLRenderTargetCube; + +WebGLRenderTargetCube.prototype.isWebGLRenderTargetCube = true; /** * @author alteredq / http://alteredqualia.com/ @@ -4508,7 +4946,7 @@ function getSingularSetter( type ) { case 0x8b5b: return setValue3fm; // _MAT3 case 0x8b5c: return setValue4fm; // _MAT4 - case 0x8b5e: return setValueT1; // SAMPLER_2D + case 0x8b5e: case 0x8d66: return setValueT1; // SAMPLER_2D, SAMPLER_EXTERNAL_OES case 0x8b60: return setValueT6; // SAMPLER_CUBE case 0x1404: case 0x8b56: return setValue1i; // INT, BOOL @@ -4840,7 +5278,7 @@ var ColorKeywords = { 'aliceblue': 0xF0F8FF, 'antiquewhite': 0xFAEBD7, 'aqua': 0 '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, 'red': 0xFF0000, 'rosybrown': 0xBC8F8F, + '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, @@ -5348,11 +5786,20 @@ var UniformsLib = { opacity: { value: 1.0 }, map: { value: null }, - offsetRepeat: { value: new Vector4( 0, 0, 1, 1 ) }, + uvTransform: { value: new Matrix3() }, - specularMap: { value: null }, alphaMap: { value: null }, + }, + + specularmap: { + + specularMap: { value: null }, + + }, + + envmap: { + envMap: { value: null }, flipEnvMap: { value: - 1 }, reflectivity: { value: 1.0 }, @@ -5473,7 +5920,9 @@ var UniformsLib = { shadow: {}, shadowBias: {}, shadowRadius: {}, - shadowMapSize: {} + shadowMapSize: {}, + shadowCameraNear: {}, + shadowCameraFar: {} } }, pointShadowMap: { value: [] }, @@ -5502,7 +5951,7 @@ var UniformsLib = { size: { value: 1.0 }, scale: { value: 1.0 }, map: { value: null }, - offsetRepeat: { value: new Vector4( 0, 0, 1, 1 ) } + uvTransform: { value: new Matrix3() } } @@ -5589,7 +6038,7 @@ var beginnormal_vertex = "\nvec3 objectNormal = vec3( normal );\n"; var bsdfs = "float punctualLightIntensityToIrradianceFactor( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\tif( decayExponent > 0.0 ) {\n#if defined ( PHYSICALLY_CORRECT_LIGHTS )\n\t\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\t\tfloat maxDistanceCutoffFactor = pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t\treturn distanceFalloff * maxDistanceCutoffFactor;\n#else\n\t\treturn pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );\n#endif\n\t}\n\treturn 1.0;\n}\nvec3 BRDF_Diffuse_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 specularColor, const in float dotLH ) {\n\tfloat fresnel = exp2( ( -5.55473 * dotLH - 6.98316 ) * dotLH );\n\treturn ( 1.0 - specularColor ) * fresnel + specularColor;\n}\nfloat G_GGX_Smith( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gl = dotNL + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\tfloat gv = dotNV + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\treturn 1.0 / ( gl * gv );\n}\nfloat G_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}\nvec3 BRDF_Specular_GGX( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNL = saturate( dot( geometry.normal, incidentLight.direction ) );\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\tfloat D = D_GGX( alpha, dotNH );\n\treturn F * ( G * 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 theta = acos( dot( N, V ) );\n\tvec2 uv = vec2(\n\t\tsqrt( saturate( roughness ) ),\n\t\tsaturate( theta / ( 0.5 * PI ) ) );\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.86267 + (0.49788 + 0.01436 * y ) * y;\n\tfloat b = 3.45068 + (4.18814 + y) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = (x > 0.0) ? v : 0.5 * inversesqrt( 1.0 - x * x ) - 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 * transpose( 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\tvec3 result = vec3( LTC_ClippedSphereFormFactor( vectorFormFactor ) );\n\treturn result;\n}\nvec3 BRDF_Specular_GGX_Environment( const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.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 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;\n\treturn specularColor * AB.x + AB.y;\n}\nfloat 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_Specular_BlinnPhong( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float shininess ) {\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n}\nfloat GGXRoughnessToBlinnExponent( const in float ggxRoughness ) {\n\treturn ( 2.0 / pow2( ggxRoughness + 0.0001 ) - 2.0 );\n}\nfloat BlinnExponentToGGXRoughness( const in float blinnExponent ) {\n\treturn sqrt( 2.0 / ( blinnExponent + 2.0 ) );\n}\n"; -var bumpmap_pars_fragment = "#ifdef USE_BUMPMAP\n\tuniform sampler2D bumpMap;\n\tuniform float bumpScale;\n\tvec2 dHdxy_fwd() {\n\t\tvec2 dSTdx = dFdx( vUv );\n\t\tvec2 dSTdy = dFdy( vUv );\n\t\tfloat Hll = bumpScale * texture2D( bumpMap, vUv ).x;\n\t\tfloat dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;\n\t\tfloat dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;\n\t\treturn vec2( dBx, dBy );\n\t}\n\tvec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy ) {\n\t\tvec3 vSigmaX = dFdx( surf_pos );\n\t\tvec3 vSigmaY = dFdy( surf_pos );\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 );\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\n"; +var bumpmap_pars_fragment = "#ifdef USE_BUMPMAP\n\tuniform sampler2D bumpMap;\n\tuniform float bumpScale;\n\tvec2 dHdxy_fwd() {\n\t\tvec2 dSTdx = dFdx( vUv );\n\t\tvec2 dSTdy = dFdy( vUv );\n\t\tfloat Hll = bumpScale * texture2D( bumpMap, vUv ).x;\n\t\tfloat dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;\n\t\tfloat dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;\n\t\treturn vec2( dBx, dBy );\n\t}\n\tvec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy ) {\n\t\tvec3 vSigmaX = vec3( dFdx( surf_pos.x ), dFdx( surf_pos.y ), dFdx( surf_pos.z ) );\n\t\tvec3 vSigmaY = vec3( dFdy( surf_pos.x ), dFdy( surf_pos.y ), dFdy( surf_pos.z ) );\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 );\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\n"; var clipping_planes_fragment = "#if NUM_CLIPPING_PLANES > 0\n\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; ++ i ) {\n\t\tvec4 plane = clippingPlanes[ i ];\n\t\tif ( dot( vViewPosition, plane.xyz ) > plane.w ) discard;\n\t}\n\t\t\n\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\tbool clipped = true;\n\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; ++ i ) {\n\t\t\tvec4 plane = clippingPlanes[ i ];\n\t\t\tclipped = ( dot( vViewPosition, plane.xyz ) > plane.w ) && clipped;\n\t\t}\n\t\tif ( clipped ) discard;\n\t\n\t#endif\n#endif\n"; @@ -5607,15 +6056,15 @@ var color_pars_vertex = "#ifdef USE_COLOR\n\tvarying vec3 vColor;\n#endif"; var color_vertex = "#ifdef USE_COLOR\n\tvColor.xyz = color.xyz;\n#endif"; -var common = "#define PI 3.14159265359\n#define PI2 6.28318530718\n#define PI_HALF 1.5707963267949\n#define RECIPROCAL_PI 0.31830988618\n#define RECIPROCAL_PI2 0.15915494\n#define LOG2 1.442695\n#define EPSILON 1e-6\n#define saturate(a) clamp( a, 0.0, 1.0 )\n#define whiteCompliment(a) ( 1.0 - saturate( a ) )\nfloat pow2( const in float 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 average( const in vec3 color ) { return dot( color, vec3( 0.3333 ) ); }\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}\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};\nstruct GeometricContext {\n\tvec3 position;\n\tvec3 normal;\n\tvec3 viewDir;\n};\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}\nvec3 projectOnPlane(in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\tfloat distance = dot( planeNormal, point - pointOnPlane );\n\treturn - distance * planeNormal + point;\n}\nfloat sideOfPlane( in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn sign( dot( point - pointOnPlane, planeNormal ) );\n}\nvec3 linePlaneIntersect( in vec3 pointOnLine, in vec3 lineDirection, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn lineDirection * ( dot( planeNormal, pointOnPlane - pointOnLine ) / dot( planeNormal, lineDirection ) ) + pointOnLine;\n}\nmat3 transpose( const in mat3 v ) {\n\tmat3 tmp;\n\ttmp[0] = vec3(v[0].x, v[1].x, v[2].x);\n\ttmp[1] = vec3(v[0].y, v[1].y, v[2].y);\n\ttmp[2] = vec3(v[0].z, v[1].z, v[2].z);\n\treturn tmp;\n}\n"; +var common = "#define PI 3.14159265359\n#define PI2 6.28318530718\n#define PI_HALF 1.5707963267949\n#define RECIPROCAL_PI 0.31830988618\n#define RECIPROCAL_PI2 0.15915494\n#define LOG2 1.442695\n#define EPSILON 1e-6\n#define saturate(a) clamp( a, 0.0, 1.0 )\n#define whiteCompliment(a) ( 1.0 - saturate( a ) )\nfloat pow2( const in float 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 average( const in vec3 color ) { return dot( color, vec3( 0.3333 ) ); }\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}\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};\nstruct GeometricContext {\n\tvec3 position;\n\tvec3 normal;\n\tvec3 viewDir;\n};\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}\nvec3 projectOnPlane(in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\tfloat distance = dot( planeNormal, point - pointOnPlane );\n\treturn - distance * planeNormal + point;\n}\nfloat sideOfPlane( in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn sign( dot( point - pointOnPlane, planeNormal ) );\n}\nvec3 linePlaneIntersect( in vec3 pointOnLine, in vec3 lineDirection, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn lineDirection * ( dot( planeNormal, pointOnPlane - pointOnLine ) / dot( planeNormal, lineDirection ) ) + pointOnLine;\n}\nmat3 transpose( const in mat3 v ) {\n\tmat3 tmp;\n\ttmp[0] = vec3(v[0].x, v[1].x, v[2].x);\n\ttmp[1] = vec3(v[0].y, v[1].y, v[2].y);\n\ttmp[2] = vec3(v[0].z, v[1].z, v[2].z);\n\treturn tmp;\n}\nfloat linearToRelativeLuminance( const in vec3 color ) {\n\tvec3 weights = vec3( 0.2126, 0.7152, 0.0722 );\n\treturn dot( weights, color.rgb );\n}\n"; var cube_uv_reflection_fragment = "#ifdef ENVMAP_TYPE_CUBE_UV\n#define cubeUV_textureSize (1024.0)\nint getFaceFromDirection(vec3 direction) {\n\tvec3 absDirection = abs(direction);\n\tint face = -1;\n\tif( absDirection.x > absDirection.z ) {\n\t\tif(absDirection.x > absDirection.y )\n\t\t\tface = direction.x > 0.0 ? 0 : 3;\n\t\telse\n\t\t\tface = direction.y > 0.0 ? 1 : 4;\n\t}\n\telse {\n\t\tif(absDirection.z > absDirection.y )\n\t\t\tface = direction.z > 0.0 ? 2 : 5;\n\t\telse\n\t\t\tface = direction.y > 0.0 ? 1 : 4;\n\t}\n\treturn face;\n}\n#define cubeUV_maxLods1 (log2(cubeUV_textureSize*0.25) - 1.0)\n#define cubeUV_rangeClamp (exp2((6.0 - 1.0) * 2.0))\nvec2 MipLevelInfo( vec3 vec, float roughnessLevel, float roughness ) {\n\tfloat scale = exp2(cubeUV_maxLods1 - roughnessLevel);\n\tfloat dxRoughness = dFdx(roughness);\n\tfloat dyRoughness = dFdy(roughness);\n\tvec3 dx = dFdx( vec * scale * dxRoughness );\n\tvec3 dy = dFdy( vec * scale * dyRoughness );\n\tfloat d = max( dot( dx, dx ), dot( dy, dy ) );\n\td = clamp(d, 1.0, cubeUV_rangeClamp);\n\tfloat mipLevel = 0.5 * log2(d);\n\treturn vec2(floor(mipLevel), fract(mipLevel));\n}\n#define cubeUV_maxLods2 (log2(cubeUV_textureSize*0.25) - 2.0)\n#define cubeUV_rcpTextureSize (1.0 / cubeUV_textureSize)\nvec2 getCubeUV(vec3 direction, float roughnessLevel, float mipLevel) {\n\tmipLevel = roughnessLevel > cubeUV_maxLods2 - 3.0 ? 0.0 : mipLevel;\n\tfloat a = 16.0 * cubeUV_rcpTextureSize;\n\tvec2 exp2_packed = exp2( vec2( roughnessLevel, mipLevel ) );\n\tvec2 rcp_exp2_packed = vec2( 1.0 ) / exp2_packed;\n\tfloat powScale = exp2_packed.x * exp2_packed.y;\n\tfloat scale = rcp_exp2_packed.x * rcp_exp2_packed.y * 0.25;\n\tfloat mipOffset = 0.75*(1.0 - rcp_exp2_packed.y) * rcp_exp2_packed.x;\n\tbool bRes = mipLevel == 0.0;\n\tscale = bRes && (scale < a) ? a : scale;\n\tvec3 r;\n\tvec2 offset;\n\tint face = getFaceFromDirection(direction);\n\tfloat rcpPowScale = 1.0 / powScale;\n\tif( face == 0) {\n\t\tr = vec3(direction.x, -direction.z, direction.y);\n\t\toffset = vec2(0.0+mipOffset,0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 1) {\n\t\tr = vec3(direction.y, direction.x, direction.z);\n\t\toffset = vec2(scale+mipOffset, 0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 2) {\n\t\tr = vec3(direction.z, direction.x, direction.y);\n\t\toffset = vec2(2.0*scale+mipOffset, 0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 3) {\n\t\tr = vec3(direction.x, direction.z, direction.y);\n\t\toffset = vec2(0.0+mipOffset,0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\telse if( face == 4) {\n\t\tr = vec3(direction.y, direction.x, -direction.z);\n\t\toffset = vec2(scale+mipOffset, 0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\telse {\n\t\tr = vec3(direction.z, -direction.x, direction.y);\n\t\toffset = vec2(2.0*scale+mipOffset, 0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\tr = normalize(r);\n\tfloat texelOffset = 0.5 * cubeUV_rcpTextureSize;\n\tvec2 s = ( r.yz / abs( r.x ) + vec2( 1.0 ) ) * 0.5;\n\tvec2 base = offset + vec2( texelOffset );\n\treturn base + s * ( scale - 2.0 * texelOffset );\n}\n#define cubeUV_maxLods3 (log2(cubeUV_textureSize*0.25) - 3.0)\nvec4 textureCubeUV(vec3 reflectedDirection, float roughness ) {\n\tfloat roughnessVal = roughness* cubeUV_maxLods3;\n\tfloat r1 = floor(roughnessVal);\n\tfloat r2 = r1 + 1.0;\n\tfloat t = fract(roughnessVal);\n\tvec2 mipInfo = MipLevelInfo(reflectedDirection, r1, roughness);\n\tfloat s = mipInfo.y;\n\tfloat level0 = mipInfo.x;\n\tfloat level1 = level0 + 1.0;\n\tlevel1 = level1 > 5.0 ? 5.0 : level1;\n\tlevel0 += min( floor( s + 0.5 ), 5.0 );\n\tvec2 uv_10 = getCubeUV(reflectedDirection, r1, level0);\n\tvec4 color10 = envMapTexelToLinear(texture2D(envMap, uv_10));\n\tvec2 uv_20 = getCubeUV(reflectedDirection, r2, level0);\n\tvec4 color20 = envMapTexelToLinear(texture2D(envMap, uv_20));\n\tvec4 result = mix(color10, color20, t);\n\treturn vec4(result.rgb, 1.0);\n}\n#endif\n"; -var defaultnormal_vertex = "#ifdef FLIP_SIDED\n\tobjectNormal = -objectNormal;\n#endif\nvec3 transformedNormal = normalMatrix * objectNormal;\n"; +var defaultnormal_vertex = "vec3 transformedNormal = normalMatrix * objectNormal;\n#ifdef FLIP_SIDED\n\ttransformedNormal = - transformedNormal;\n#endif\n"; var displacementmap_pars_vertex = "#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif\n"; -var displacementmap_vertex = "#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normal * ( texture2D( displacementMap, uv ).x * displacementScale + displacementBias );\n#endif\n"; +var displacementmap_vertex = "#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, uv ).x * displacementScale + displacementBias );\n#endif\n"; var emissivemap_fragment = "#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vUv );\n\temissiveColor.rgb = emissiveMapTexelToLinear( emissiveColor ).rgb;\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif\n"; @@ -5625,7 +6074,7 @@ var encodings_fragment = " gl_FragColor = linearToOutputTexel( gl_FragColor );\ var encodings_pars_fragment = "\nvec4 LinearToLinear( in vec4 value ) {\n\treturn value;\n}\nvec4 GammaToLinear( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.xyz, vec3( gammaFactor ) ), value.w );\n}\nvec4 LinearToGamma( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.xyz, vec3( 1.0 / gammaFactor ) ), value.w );\n}\nvec4 sRGBToLinear( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), value.rgb * 0.0773993808, vec3( lessThanEqual( value.rgb, vec3( 0.04045 ) ) ) ), value.w );\n}\nvec4 LinearTosRGB( 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.w );\n}\nvec4 RGBEToLinear( in vec4 value ) {\n\treturn vec4( value.rgb * exp2( value.a * 255.0 - 128.0 ), 1.0 );\n}\nvec4 LinearToRGBE( in vec4 value ) {\n\tfloat maxComponent = max( max( value.r, value.g ), value.b );\n\tfloat fExp = clamp( ceil( log2( maxComponent ) ), -128.0, 127.0 );\n\treturn vec4( value.rgb / exp2( fExp ), ( fExp + 128.0 ) / 255.0 );\n}\nvec4 RGBMToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.xyz * value.w * maxRange, 1.0 );\n}\nvec4 LinearToRGBM( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.x, max( value.g, value.b ) );\n\tfloat M = clamp( maxRGB / maxRange, 0.0, 1.0 );\n\tM = ceil( M * 255.0 ) / 255.0;\n\treturn vec4( value.rgb / ( M * maxRange ), M );\n}\nvec4 RGBDToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.rgb * ( ( maxRange / 255.0 ) / value.a ), 1.0 );\n}\nvec4 LinearToRGBD( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.x, max( value.g, value.b ) );\n\tfloat D = max( maxRange / maxRGB, 1.0 );\n\tD = min( floor( D ) / 255.0, 1.0 );\n\treturn vec4( value.rgb * ( D * ( 255.0 / maxRange ) ), D );\n}\nconst mat3 cLogLuvM = mat3( 0.2209, 0.3390, 0.4184, 0.1138, 0.6780, 0.7319, 0.0102, 0.1130, 0.2969 );\nvec4 LinearToLogLuv( in vec4 value ) {\n\tvec3 Xp_Y_XYZp = value.rgb * cLogLuvM;\n\tXp_Y_XYZp = max(Xp_Y_XYZp, vec3(1e-6, 1e-6, 1e-6));\n\tvec4 vResult;\n\tvResult.xy = Xp_Y_XYZp.xy / Xp_Y_XYZp.z;\n\tfloat Le = 2.0 * log2(Xp_Y_XYZp.y) + 127.0;\n\tvResult.w = fract(Le);\n\tvResult.z = (Le - (floor(vResult.w*255.0))/255.0)/255.0;\n\treturn vResult;\n}\nconst mat3 cLogLuvInverseM = mat3( 6.0014, -2.7008, -1.7996, -1.3320, 3.1029, -5.7721, 0.3008, -1.0882, 5.6268 );\nvec4 LogLuvToLinear( in vec4 value ) {\n\tfloat Le = value.z * 255.0 + value.w;\n\tvec3 Xp_Y_XYZp;\n\tXp_Y_XYZp.y = exp2((Le - 127.0) / 2.0);\n\tXp_Y_XYZp.z = Xp_Y_XYZp.y / value.y;\n\tXp_Y_XYZp.x = value.x * Xp_Y_XYZp.z;\n\tvec3 vRGB = Xp_Y_XYZp.rgb * cLogLuvInverseM;\n\treturn vec4( max(vRGB, 0.0), 1.0 );\n}\n"; -var envmap_fragment = "#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvec3 cameraToVertex = normalize( vWorldPosition - cameraPosition );\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToVertex, 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, flipNormal * vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\t#elif defined( ENVMAP_TYPE_EQUIREC )\n\t\tvec2 sampleUV;\n\t\tsampleUV.y = saturate( flipNormal * reflectVec.y * 0.5 + 0.5 );\n\t\tsampleUV.x = atan( flipNormal * reflectVec.z, flipNormal * reflectVec.x ) * RECIPROCAL_PI2 + 0.5;\n\t\tvec4 envColor = texture2D( envMap, sampleUV );\n\t#elif defined( ENVMAP_TYPE_SPHERE )\n\t\tvec3 reflectView = flipNormal * normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0, 0.0, 1.0 ) );\n\t\tvec4 envColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5 );\n\t#else\n\t\tvec4 envColor = vec4( 0.0 );\n\t#endif\n\tenvColor = envMapTexelToLinear( envColor );\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\n"; +var envmap_fragment = "#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvec3 cameraToVertex = normalize( vWorldPosition - cameraPosition );\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToVertex, 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#elif defined( ENVMAP_TYPE_EQUIREC )\n\t\tvec2 sampleUV;\n\t\treflectVec = normalize( reflectVec );\n\t\tsampleUV.y = asin( clamp( reflectVec.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\t\tsampleUV.x = atan( reflectVec.z, reflectVec.x ) * RECIPROCAL_PI2 + 0.5;\n\t\tvec4 envColor = texture2D( envMap, sampleUV );\n\t#elif defined( ENVMAP_TYPE_SPHERE )\n\t\treflectVec = normalize( reflectVec );\n\t\tvec3 reflectView = normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0, 0.0, 1.0 ) );\n\t\tvec4 envColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5 );\n\t#else\n\t\tvec4 envColor = vec4( 0.0 );\n\t#endif\n\tenvColor = envMapTexelToLinear( envColor );\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\n"; var envmap_pars_fragment = "#if defined( USE_ENVMAP ) || defined( PHYSICAL )\n\tuniform float reflectivity;\n\tuniform float envMapIntensity;\n#endif\n#ifdef USE_ENVMAP\n\t#if ! defined( PHYSICAL ) && ( defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) )\n\t\tvarying vec3 vWorldPosition;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tuniform samplerCube envMap;\n\t#else\n\t\tuniform sampler2D envMap;\n\t#endif\n\tuniform float flipEnvMap;\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( PHYSICAL )\n\t\tuniform float refractionRatio;\n\t#else\n\t\tvarying vec3 vReflect;\n\t#endif\n#endif\n"; @@ -5649,7 +6098,7 @@ var lightmap_pars_fragment = "#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap; var lights_lambert_vertex = "vec3 diffuse = vec3( 1.0 );\nGeometricContext geometry;\ngeometry.position = mvPosition.xyz;\ngeometry.normal = normalize( transformedNormal );\ngeometry.viewDir = normalize( -mvPosition.xyz );\nGeometricContext backGeometry;\nbackGeometry.position = geometry.position;\nbackGeometry.normal = -geometry.normal;\nbackGeometry.viewDir = geometry.viewDir;\nvLightFront = vec3( 0.0 );\n#ifdef DOUBLE_SIDED\n\tvLightBack = vec3( 0.0 );\n#endif\nIncidentLight directLight;\nfloat dotNL;\nvec3 directLightColor_Diffuse;\n#if NUM_POINT_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tgetPointDirectLightIrradiance( pointLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tgetSpotDirectLightIrradiance( spotLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_DIR_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tgetDirectionalDirectLightIrradiance( directionalLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\tvLightFront += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += getHemisphereLightIrradiance( hemisphereLights[ i ], backGeometry );\n\t\t#endif\n\t}\n#endif\n"; -var lights_pars = "uniform vec3 ambientLightColor;\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treturn irradiance;\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalDirectLightIrradiance( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tdirectLight.color = directionalLight.color;\n\t\tdirectLight.direction = directionalLight.direction;\n\t\tdirectLight.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\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointDirectLightIrradiance( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tvec3 lVector = pointLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tdirectLight.color = pointLight.color;\n\t\tdirectLight.color *= punctualLightIntensityToIrradianceFactor( lightDistance, pointLight.distance, pointLight.decay );\n\t\tdirectLight.visible = ( directLight.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\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\tvoid getSpotDirectLightIrradiance( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tvec3 lVector = spotLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tfloat angleCos = dot( directLight.direction, spotLight.direction );\n\t\tif ( angleCos > spotLight.coneCos ) {\n\t\t\tfloat spotEffect = smoothstep( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\t\tdirectLight.color = spotLight.color;\n\t\t\tdirectLight.color *= spotEffect * punctualLightIntensityToIrradianceFactor( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tdirectLight.visible = true;\n\t\t} else {\n\t\t\tdirectLight.color = vec3( 0.0 );\n\t\t\tdirectLight.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 ltcMat;\tuniform sampler2D ltcMag;\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 GeometricContext geometry ) {\n\t\tfloat dotNL = dot( geometry.normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tirradiance *= PI;\n\t\t#endif\n\t\treturn irradiance;\n\t}\n#endif\n#if defined( USE_ENVMAP ) && defined( PHYSICAL )\n\tvec3 getLightProbeIndirectIrradiance( const in GeometricContext geometry, const in int maxMIPLevel ) {\n\t\tvec3 worldNormal = inverseTransformDirection( geometry.normal, viewMatrix );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\tvec4 envMapColor = textureCubeUV( queryVec, 1.0 );\n\t\t#else\n\t\t\tvec4 envMapColor = vec4( 0.0 );\n\t\t#endif\n\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t}\n\tfloat getSpecularMIPLevel( const in float blinnShininessExponent, const in int maxMIPLevel ) {\n\t\tfloat maxMIPLevelScalar = float( maxMIPLevel );\n\t\tfloat desiredMIPLevel = maxMIPLevelScalar - 0.79248 - 0.5 * log2( pow2( blinnShininessExponent ) + 1.0 );\n\t\treturn clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );\n\t}\n\tvec3 getLightProbeIndirectRadiance( const in GeometricContext geometry, const in float blinnShininessExponent, const in int maxMIPLevel ) {\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( -geometry.viewDir, geometry.normal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( -geometry.viewDir, geometry.normal, refractionRatio );\n\t\t#endif\n\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\tfloat specularMIPLevel = getSpecularMIPLevel( blinnShininessExponent, maxMIPLevel );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\tvec4 envMapColor = textureCubeUV(queryReflectVec, BlinnExponentToGGXRoughness(blinnShininessExponent));\n\t\t#elif defined( ENVMAP_TYPE_EQUIREC )\n\t\t\tvec2 sampleUV;\n\t\t\tsampleUV.y = saturate( reflectVec.y * 0.5 + 0.5 );\n\t\t\tsampleUV.x = atan( reflectVec.z, reflectVec.x ) * RECIPROCAL_PI2 + 0.5;\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = texture2DLodEXT( envMap, sampleUV, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = texture2D( envMap, sampleUV, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_SPHERE )\n\t\t\tvec3 reflectView = normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0,0.0,1.0 ) );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = texture2DLodEXT( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#endif\n\t\treturn envMapColor.rgb * envMapIntensity;\n\t}\n#endif\n"; +var lights_pars = "uniform vec3 ambientLightColor;\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treturn irradiance;\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalDirectLightIrradiance( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tdirectLight.color = directionalLight.color;\n\t\tdirectLight.direction = directionalLight.direction;\n\t\tdirectLight.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\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t\tfloat shadowCameraNear;\n\t\tfloat shadowCameraFar;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointDirectLightIrradiance( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tvec3 lVector = pointLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tdirectLight.color = pointLight.color;\n\t\tdirectLight.color *= punctualLightIntensityToIrradianceFactor( lightDistance, pointLight.distance, pointLight.decay );\n\t\tdirectLight.visible = ( directLight.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\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\tvoid getSpotDirectLightIrradiance( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tvec3 lVector = spotLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tfloat angleCos = dot( directLight.direction, spotLight.direction );\n\t\tif ( angleCos > spotLight.coneCos ) {\n\t\t\tfloat spotEffect = smoothstep( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\t\tdirectLight.color = spotLight.color;\n\t\t\tdirectLight.color *= spotEffect * punctualLightIntensityToIrradianceFactor( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tdirectLight.visible = true;\n\t\t} else {\n\t\t\tdirectLight.color = vec3( 0.0 );\n\t\t\tdirectLight.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 ltcMat;\tuniform sampler2D ltcMag;\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 GeometricContext geometry ) {\n\t\tfloat dotNL = dot( geometry.normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tirradiance *= PI;\n\t\t#endif\n\t\treturn irradiance;\n\t}\n#endif\n#if defined( USE_ENVMAP ) && defined( PHYSICAL )\n\tvec3 getLightProbeIndirectIrradiance( const in GeometricContext geometry, const in int maxMIPLevel ) {\n\t\tvec3 worldNormal = inverseTransformDirection( geometry.normal, viewMatrix );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\tvec4 envMapColor = textureCubeUV( queryVec, 1.0 );\n\t\t#else\n\t\t\tvec4 envMapColor = vec4( 0.0 );\n\t\t#endif\n\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t}\n\tfloat getSpecularMIPLevel( const in float blinnShininessExponent, const in int maxMIPLevel ) {\n\t\tfloat maxMIPLevelScalar = float( maxMIPLevel );\n\t\tfloat desiredMIPLevel = maxMIPLevelScalar - 0.79248 - 0.5 * log2( pow2( blinnShininessExponent ) + 1.0 );\n\t\treturn clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );\n\t}\n\tvec3 getLightProbeIndirectRadiance( const in GeometricContext geometry, const in float blinnShininessExponent, const in int maxMIPLevel ) {\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( -geometry.viewDir, geometry.normal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( -geometry.viewDir, geometry.normal, refractionRatio );\n\t\t#endif\n\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\tfloat specularMIPLevel = getSpecularMIPLevel( blinnShininessExponent, maxMIPLevel );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\tvec4 envMapColor = textureCubeUV(queryReflectVec, BlinnExponentToGGXRoughness(blinnShininessExponent));\n\t\t#elif defined( ENVMAP_TYPE_EQUIREC )\n\t\t\tvec2 sampleUV;\n\t\t\tsampleUV.y = asin( clamp( reflectVec.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\t\t\tsampleUV.x = atan( reflectVec.z, reflectVec.x ) * RECIPROCAL_PI2 + 0.5;\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = texture2DLodEXT( envMap, sampleUV, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = texture2D( envMap, sampleUV, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_SPHERE )\n\t\t\tvec3 reflectView = normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0,0.0,1.0 ) );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = texture2DLodEXT( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#endif\n\t\treturn envMapColor.rgb * envMapIntensity;\n\t}\n#endif\n"; var lights_phong_fragment = "BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;\n"; @@ -5659,23 +6108,23 @@ var lights_physical_fragment = "PhysicalMaterial material;\nmaterial.diffuseColo var lights_physical_pars_fragment = "struct PhysicalMaterial {\n\tvec3\tdiffuseColor;\n\tfloat\tspecularRoughness;\n\tvec3\tspecularColor;\n\t#ifndef STANDARD\n\t\tfloat clearCoat;\n\t\tfloat clearCoatRoughness;\n\t#endif\n};\n#define MAXIMUM_SPECULAR_COEFFICIENT 0.16\n#define DEFAULT_SPECULAR_COEFFICIENT 0.04\nfloat clearCoatDHRApprox( const in float roughness, const in float dotNL ) {\n\treturn DEFAULT_SPECULAR_COEFFICIENT + ( 1.0 - DEFAULT_SPECULAR_COEFFICIENT ) * ( pow( 1.0 - dotNL, 5.0 ) * pow( 1.0 - roughness, 2.0 ) );\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometry.normal;\n\t\tvec3 viewDir = geometry.viewDir;\n\t\tvec3 position = geometry.position;\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.specularRoughness;\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\tfloat norm = texture2D( ltcMag, uv ).a;\n\t\tvec4 t = texture2D( ltcMat, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( 1, 0, t.y ),\n\t\t\tvec3( 0, t.z, 0 ),\n\t\t\tvec3( t.w, 0, t.x )\n\t\t);\n\t\treflectedLight.directSpecular += lightColor * material.specularColor * norm * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\t#ifndef STANDARD\n\t\tfloat clearCoatDHR = material.clearCoat * clearCoatDHRApprox( material.clearCoatRoughness, dotNL );\n\t#else\n\t\tfloat clearCoatDHR = 0.0;\n\t#endif\n\treflectedLight.directSpecular += ( 1.0 - clearCoatDHR ) * irradiance * BRDF_Specular_GGX( directLight, geometry, material.specularColor, material.specularRoughness );\n\treflectedLight.directDiffuse += ( 1.0 - clearCoatDHR ) * irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\t#ifndef STANDARD\n\t\treflectedLight.directSpecular += irradiance * material.clearCoat * BRDF_Specular_GGX( directLight, geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness );\n\t#endif\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 clearCoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t#ifndef STANDARD\n\t\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\t\tfloat dotNL = dotNV;\n\t\tfloat clearCoatDHR = material.clearCoat * clearCoatDHRApprox( material.clearCoatRoughness, dotNL );\n\t#else\n\t\tfloat clearCoatDHR = 0.0;\n\t#endif\n\treflectedLight.indirectSpecular += ( 1.0 - clearCoatDHR ) * radiance * BRDF_Specular_GGX_Environment( geometry, material.specularColor, material.specularRoughness );\n\t#ifndef STANDARD\n\t\treflectedLight.indirectSpecular += clearCoatRadiance * material.clearCoat * BRDF_Specular_GGX_Environment( geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness );\n\t#endif\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\n#define Material_BlinnShininessExponent( material ) GGXRoughnessToBlinnExponent( material.specularRoughness )\n#define Material_ClearCoat_BlinnShininessExponent( material ) GGXRoughnessToBlinnExponent( material.clearCoatRoughness )\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}\n"; -var lights_template = "\nGeometricContext geometry;\ngeometry.position = - vViewPosition;\ngeometry.normal = normal;\ngeometry.viewDir = normalize( vViewPosition );\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointDirectLightIrradiance( pointLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( pointLight.shadow, directLight.visible ) ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotDirectLightIrradiance( spotLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( spotLight.shadow, directLight.visible ) ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalDirectLightIrradiance( directionalLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( directionalLight.shadow, directLight.visible ) ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\t#ifdef USE_LIGHTMAP\n\t\tvec3 lightMapIrradiance = texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tlightMapIrradiance *= PI;\n\t\t#endif\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t}\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( PHYSICAL ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tirradiance += getLightProbeIndirectIrradiance( geometry, 8 );\n\t#endif\n\tRE_IndirectDiffuse( irradiance, geometry, material, reflectedLight );\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\tvec3 radiance = getLightProbeIndirectRadiance( geometry, Material_BlinnShininessExponent( material ), 8 );\n\t#ifndef STANDARD\n\t\tvec3 clearCoatRadiance = getLightProbeIndirectRadiance( geometry, Material_ClearCoat_BlinnShininessExponent( material ), 8 );\n\t#else\n\t\tvec3 clearCoatRadiance = vec3( 0.0 );\n\t#endif\n\tRE_IndirectSpecular( radiance, clearCoatRadiance, geometry, material, reflectedLight );\n#endif\n"; +var lights_template = "\nGeometricContext geometry;\ngeometry.position = - vViewPosition;\ngeometry.normal = normal;\ngeometry.viewDir = normalize( vViewPosition );\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointDirectLightIrradiance( pointLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( pointLight.shadow, directLight.visible ) ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotDirectLightIrradiance( spotLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( spotLight.shadow, directLight.visible ) ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalDirectLightIrradiance( directionalLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( directionalLight.shadow, directLight.visible ) ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\t#ifdef USE_LIGHTMAP\n\t\tvec3 lightMapIrradiance = texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tlightMapIrradiance *= PI;\n\t\t#endif\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t}\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( PHYSICAL ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tirradiance += getLightProbeIndirectIrradiance( geometry, 8 );\n\t#endif\n\tRE_IndirectDiffuse( irradiance, geometry, material, reflectedLight );\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\tvec3 radiance = getLightProbeIndirectRadiance( geometry, Material_BlinnShininessExponent( material ), 8 );\n\t#ifndef STANDARD\n\t\tvec3 clearCoatRadiance = getLightProbeIndirectRadiance( geometry, Material_ClearCoat_BlinnShininessExponent( material ), 8 );\n\t#else\n\t\tvec3 clearCoatRadiance = vec3( 0.0 );\n\t#endif\n\tRE_IndirectSpecular( radiance, clearCoatRadiance, geometry, material, reflectedLight );\n#endif\n"; -var logdepthbuf_fragment = "#if defined(USE_LOGDEPTHBUF) && defined(USE_LOGDEPTHBUF_EXT)\n\tgl_FragDepthEXT = log2(vFragDepth) * logDepthBufFC * 0.5;\n#endif"; +var logdepthbuf_fragment = "#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tgl_FragDepthEXT = log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif"; var logdepthbuf_pars_fragment = "#ifdef USE_LOGDEPTHBUF\n\tuniform float logDepthBufFC;\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t#endif\n#endif\n"; var logdepthbuf_pars_vertex = "#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t#endif\n\tuniform float logDepthBufFC;\n#endif"; -var logdepthbuf_vertex = "#ifdef USE_LOGDEPTHBUF\n\tgl_Position.z = log2(max( EPSILON, gl_Position.w + 1.0 )) * logDepthBufFC;\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvFragDepth = 1.0 + gl_Position.w;\n\t#else\n\t\tgl_Position.z = (gl_Position.z - 1.0) * gl_Position.w;\n\t#endif\n#endif\n"; +var logdepthbuf_vertex = "#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvFragDepth = 1.0 + gl_Position.w;\n\t#else\n\t\tgl_Position.z = log2( max( EPSILON, gl_Position.w + 1.0 ) ) * logDepthBufFC - 1.0;\n\t\tgl_Position.z *= gl_Position.w;\n\t#endif\n#endif\n"; var map_fragment = "#ifdef USE_MAP\n\tvec4 texelColor = texture2D( map, vUv );\n\ttexelColor = mapTexelToLinear( texelColor );\n\tdiffuseColor *= texelColor;\n#endif\n"; var map_pars_fragment = "#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif\n"; -var map_particle_fragment = "#ifdef USE_MAP\n\tvec4 mapTexel = texture2D( map, vec2( gl_PointCoord.x, 1.0 - gl_PointCoord.y ) * offsetRepeat.zw + offsetRepeat.xy );\n\tdiffuseColor *= mapTexelToLinear( mapTexel );\n#endif\n"; +var map_particle_fragment = "#ifdef USE_MAP\n\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n\tvec4 mapTexel = texture2D( map, uv );\n\tdiffuseColor *= mapTexelToLinear( mapTexel );\n#endif\n"; -var map_particle_pars_fragment = "#ifdef USE_MAP\n\tuniform vec4 offsetRepeat;\n\tuniform sampler2D map;\n#endif\n"; +var map_particle_pars_fragment = "#ifdef USE_MAP\n\tuniform mat3 uvTransform;\n\tuniform sampler2D map;\n#endif\n"; var metalnessmap_fragment = "float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif\n"; @@ -5687,17 +6136,15 @@ var morphtarget_pars_vertex = "#ifdef USE_MORPHTARGETS\n\t#ifndef USE_MORPHNORMA var morphtarget_vertex = "#ifdef USE_MORPHTARGETS\n\ttransformed += ( morphTarget0 - position ) * morphTargetInfluences[ 0 ];\n\ttransformed += ( morphTarget1 - position ) * morphTargetInfluences[ 1 ];\n\ttransformed += ( morphTarget2 - position ) * morphTargetInfluences[ 2 ];\n\ttransformed += ( morphTarget3 - position ) * morphTargetInfluences[ 3 ];\n\t#ifndef USE_MORPHNORMALS\n\ttransformed += ( morphTarget4 - position ) * morphTargetInfluences[ 4 ];\n\ttransformed += ( morphTarget5 - position ) * morphTargetInfluences[ 5 ];\n\ttransformed += ( morphTarget6 - position ) * morphTargetInfluences[ 6 ];\n\ttransformed += ( morphTarget7 - position ) * morphTargetInfluences[ 7 ];\n\t#endif\n#endif\n"; -var normal_flip = "#ifdef DOUBLE_SIDED\n\tfloat flipNormal = ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n#else\n\tfloat flipNormal = 1.0;\n#endif\n"; - -var normal_fragment = "#ifdef FLAT_SHADED\n\tvec3 fdx = vec3( dFdx( vViewPosition.x ), dFdx( vViewPosition.y ), dFdx( vViewPosition.z ) );\n\tvec3 fdy = vec3( dFdy( vViewPosition.x ), dFdy( vViewPosition.y ), dFdy( vViewPosition.z ) );\n\tvec3 normal = normalize( cross( fdx, fdy ) );\n#else\n\tvec3 normal = normalize( vNormal ) * flipNormal;\n#endif\n#ifdef USE_NORMALMAP\n\tnormal = perturbNormal2Arb( -vViewPosition, normal );\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );\n#endif\n"; +var normal_fragment = "#ifdef FLAT_SHADED\n\tvec3 fdx = vec3( dFdx( vViewPosition.x ), dFdx( vViewPosition.y ), dFdx( vViewPosition.z ) );\n\tvec3 fdy = vec3( dFdy( vViewPosition.x ), dFdy( vViewPosition.y ), dFdy( vViewPosition.z ) );\n\tvec3 normal = normalize( cross( fdx, fdy ) );\n#else\n\tvec3 normal = normalize( vNormal );\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t#endif\n#endif\n#ifdef USE_NORMALMAP\n\tnormal = perturbNormal2Arb( -vViewPosition, normal );\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );\n#endif\n"; -var normalmap_pars_fragment = "#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n\tvec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm ) {\n\t\tvec3 q0 = dFdx( eye_pos.xyz );\n\t\tvec3 q1 = dFdy( eye_pos.xyz );\n\t\tvec2 st0 = dFdx( vUv.st );\n\t\tvec2 st1 = dFdy( vUv.st );\n\t\tvec3 S = normalize( q0 * st1.t - q1 * st0.t );\n\t\tvec3 T = normalize( -q0 * st1.s + q1 * st0.s );\n\t\tvec3 N = normalize( surf_norm );\n\t\tvec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\t\tmapN.xy = normalScale * mapN.xy;\n\t\tmat3 tsn = mat3( S, T, N );\n\t\treturn normalize( tsn * mapN );\n\t}\n#endif\n"; +var normalmap_pars_fragment = "#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n\tvec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm ) {\n\t\tvec3 q0 = vec3( dFdx( eye_pos.x ), dFdx( eye_pos.y ), dFdx( eye_pos.z ) );\n\t\tvec3 q1 = vec3( dFdy( eye_pos.x ), dFdy( eye_pos.y ), dFdy( eye_pos.z ) );\n\t\tvec2 st0 = dFdx( vUv.st );\n\t\tvec2 st1 = dFdy( vUv.st );\n\t\tvec3 S = normalize( q0 * st1.t - q1 * st0.t );\n\t\tvec3 T = normalize( -q0 * st1.s + q1 * st0.s );\n\t\tvec3 N = normalize( surf_norm );\n\t\tvec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\t\tmapN.xy = normalScale * mapN.xy;\n\t\tmat3 tsn = mat3( S, T, N );\n\t\treturn normalize( tsn * mapN );\n\t}\n#endif\n"; 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 1.0 - 2.0 * rgb.xyz;\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}\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 linearClipZ, const in float near, const in float far ) {\n\treturn linearClipZ * ( 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 invClipZ, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * invClipZ - far );\n}\n"; var premultiplied_alpha_fragment = "#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif\n"; -var project_vertex = "#ifdef USE_SKINNING\n\tvec4 mvPosition = modelViewMatrix * skinned;\n#else\n\tvec4 mvPosition = modelViewMatrix * vec4( transformed, 1.0 );\n#endif\ngl_Position = projectionMatrix * mvPosition;\n"; +var project_vertex = "vec4 mvPosition = modelViewMatrix * vec4( transformed, 1.0 );\ngl_Position = projectionMatrix * mvPosition;\n"; var dithering_fragment = "#if defined( DITHERING )\n gl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif\n"; @@ -5707,19 +6154,19 @@ var roughnessmap_fragment = "float roughnessFactor = roughness;\n#ifdef USE_ROUG var roughnessmap_pars_fragment = "#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif"; -var shadowmap_pars_fragment = "#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHTS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHTS ];\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHTS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHTS ];\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHTS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHTS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tfloat texture2DShadowLerp( sampler2D depths, vec2 size, vec2 uv, float compare ) {\n\t\tconst vec2 offset = vec2( 0.0, 1.0 );\n\t\tvec2 texelSize = vec2( 1.0 ) / size;\n\t\tvec2 centroidUV = floor( uv * size + 0.5 ) / size;\n\t\tfloat lb = texture2DCompare( depths, centroidUV + texelSize * offset.xx, compare );\n\t\tfloat lt = texture2DCompare( depths, centroidUV + texelSize * offset.xy, compare );\n\t\tfloat rb = texture2DCompare( depths, centroidUV + texelSize * offset.yx, compare );\n\t\tfloat rt = texture2DCompare( depths, centroidUV + texelSize * offset.yy, compare );\n\t\tvec2 f = fract( uv * size + 0.5 );\n\t\tfloat a = mix( lb, lt, f.y );\n\t\tfloat b = mix( rb, rt, f.y );\n\t\tfloat c = mix( a, b, f.x );\n\t\treturn c;\n\t}\n\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\tshadowCoord.z += shadowBias;\n\t\tbvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );\n\t\tbool inFrustum = all( inFrustumVec );\n\t\tbvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );\n\t\tbool frustumTest = all( frustumTestVec );\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\treturn (\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( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, 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( 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 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\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\treturn (\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\treturn texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#endif\n\t\t}\n\t\treturn 1.0;\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 ) {\n\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\tvec3 bd3D = normalize( lightToPosition );\n\t\tfloat dp = ( length( lightToPosition ) - shadowBias ) / 1000.0;\n\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT )\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\n"; +var shadowmap_pars_fragment = "#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHTS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHTS ];\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHTS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHTS ];\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHTS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHTS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tfloat texture2DShadowLerp( sampler2D depths, vec2 size, vec2 uv, float compare ) {\n\t\tconst vec2 offset = vec2( 0.0, 1.0 );\n\t\tvec2 texelSize = vec2( 1.0 ) / size;\n\t\tvec2 centroidUV = floor( uv * size + 0.5 ) / size;\n\t\tfloat lb = texture2DCompare( depths, centroidUV + texelSize * offset.xx, compare );\n\t\tfloat lt = texture2DCompare( depths, centroidUV + texelSize * offset.xy, compare );\n\t\tfloat rb = texture2DCompare( depths, centroidUV + texelSize * offset.yx, compare );\n\t\tfloat rt = texture2DCompare( depths, centroidUV + texelSize * offset.yy, compare );\n\t\tvec2 f = fract( uv * size + 0.5 );\n\t\tfloat a = mix( lb, lt, f.y );\n\t\tfloat b = mix( rb, rt, f.y );\n\t\tfloat c = mix( a, b, f.x );\n\t\treturn c;\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\tbvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );\n\t\tbool inFrustum = all( inFrustumVec );\n\t\tbvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );\n\t\tbool frustumTest = all( frustumTestVec );\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\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( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, 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( 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 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\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\tshadow = (\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 9.0 );\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 )\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\n"; var shadowmap_pars_vertex = "#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHTS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHTS ];\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\t\tuniform mat4 spotShadowMatrix[ NUM_SPOT_LIGHTS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHTS ];\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHTS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHTS ];\n\t#endif\n#endif\n"; var shadowmap_vertex = "#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tvSpotShadowCoord[ i ] = spotShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n#endif\n"; -var shadowmask_pars_fragment = "float getShadowMask() {\n\tfloat shadow = 1.0;\n\t#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\tDirectionalLight directionalLight;\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tshadow *= bool( directionalLight.shadow ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t}\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\tSpotLight spotLight;\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tshadow *= bool( spotLight.shadow ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t}\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\tPointLight pointLight;\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tshadow *= bool( pointLight.shadow ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ] ) : 1.0;\n\t}\n\t#endif\n\t#endif\n\treturn shadow;\n}\n"; +var shadowmask_pars_fragment = "float getShadowMask() {\n\tfloat shadow = 1.0;\n\t#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\tDirectionalLight directionalLight;\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tshadow *= bool( directionalLight.shadow ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t}\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\tSpotLight spotLight;\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tshadow *= bool( spotLight.shadow ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t}\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\tPointLight pointLight;\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tshadow *= bool( pointLight.shadow ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t}\n\t#endif\n\t#endif\n\treturn shadow;\n}\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"; var skinning_pars_vertex = "#ifdef USE_SKINNING\n\tuniform mat4 bindMatrix;\n\tuniform mat4 bindMatrixInverse;\n\t#ifdef BONE_TEXTURE\n\t\tuniform sampler2D boneTexture;\n\t\tuniform int boneTextureSize;\n\t\tmat4 getBoneMatrix( const in float i ) {\n\t\t\tfloat j = i * 4.0;\n\t\t\tfloat x = mod( j, float( boneTextureSize ) );\n\t\t\tfloat y = floor( j / float( boneTextureSize ) );\n\t\t\tfloat dx = 1.0 / float( boneTextureSize );\n\t\t\tfloat dy = 1.0 / float( boneTextureSize );\n\t\t\ty = dy * ( y + 0.5 );\n\t\t\tvec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );\n\t\t\tvec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );\n\t\t\tvec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );\n\t\t\tvec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );\n\t\t\tmat4 bone = mat4( v1, v2, v3, v4 );\n\t\t\treturn bone;\n\t\t}\n\t#else\n\t\tuniform mat4 boneMatrices[ MAX_BONES ];\n\t\tmat4 getBoneMatrix( const in float i ) {\n\t\t\tmat4 bone = boneMatrices[ int(i) ];\n\t\t\treturn bone;\n\t\t}\n\t#endif\n#endif\n"; -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\tskinned = bindMatrixInverse * skinned;\n#endif\n"; +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\n"; 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#endif\n"; @@ -5733,9 +6180,9 @@ var tonemapping_pars_fragment = "#define saturate(a) clamp( a, 0.0, 1.0 )\nunifo var uv_pars_fragment = "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvarying vec2 vUv;\n#endif"; -var uv_pars_vertex = "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvarying vec2 vUv;\n\tuniform vec4 offsetRepeat;\n#endif\n"; +var uv_pars_vertex = "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvarying vec2 vUv;\n\tuniform mat3 uvTransform;\n#endif\n"; -var uv_vertex = "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvUv = uv * offsetRepeat.zw + offsetRepeat.xy;\n#endif"; +var uv_vertex = "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n#endif"; var uv2_pars_fragment = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvarying vec2 vUv2;\n#endif"; @@ -5743,21 +6190,21 @@ var uv2_pars_vertex = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tat var uv2_vertex = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvUv2 = uv2;\n#endif"; -var worldpos_vertex = "#if defined( USE_ENVMAP ) || defined( PHONG ) || defined( PHYSICAL ) || defined( LAMBERT ) || defined ( USE_SHADOWMAP )\n\t#ifdef USE_SKINNING\n\t\tvec4 worldPosition = modelMatrix * skinned;\n\t#else\n\t\tvec4 worldPosition = modelMatrix * vec4( transformed, 1.0 );\n\t#endif\n#endif\n"; +var worldpos_vertex = "#if defined( USE_ENVMAP ) || defined( PHONG ) || defined( PHYSICAL ) || defined( LAMBERT ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP )\n\tvec4 worldPosition = modelMatrix * vec4( transformed, 1.0 );\n#endif\n"; -var cube_frag = "uniform samplerCube tCube;\nuniform float tFlip;\nuniform float opacity;\nvarying vec3 vWorldPosition;\n#include \nvoid main() {\n\tgl_FragColor = textureCube( tCube, vec3( tFlip * vWorldPosition.x, vWorldPosition.yz ) );\n\tgl_FragColor.a *= opacity;\n}\n"; +var cube_frag = "uniform samplerCube tCube;\nuniform float tFlip;\nuniform float opacity;\nvarying vec3 vWorldPosition;\nvoid main() {\n\tgl_FragColor = textureCube( tCube, vec3( tFlip * vWorldPosition.x, vWorldPosition.yz ) );\n\tgl_FragColor.a *= opacity;\n}\n"; var cube_vert = "varying vec3 vWorldPosition;\n#include \nvoid main() {\n\tvWorldPosition = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n}\n"; var depth_frag = "#if DEPTH_PACKING == 3200\n\tuniform float opacity;\n#endif\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#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#if DEPTH_PACKING == 3200\n\t\tgl_FragColor = vec4( vec3( gl_FragCoord.z ), opacity );\n\t#elif DEPTH_PACKING == 3201\n\t\tgl_FragColor = packDepthToRGBA( gl_FragCoord.z );\n\t#endif\n}\n"; -var depth_vert = "#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}\n"; +var depth_vert = "#include \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}\n"; -var distanceRGBA_frag = "uniform vec3 lightPos;\nvarying vec4 vWorldPosition;\n#include \n#include \n#include \nvoid main () {\n\t#include \n\tgl_FragColor = packDepthToRGBA( length( vWorldPosition.xyz - lightPos.xyz ) / 1000.0 );\n}\n"; +var distanceRGBA_frag = "#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 \nvoid main () {\n\t#include \n\tvec4 diffuseColor = vec4( 1.0 );\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}\n"; -var distanceRGBA_vert = "varying vec4 vWorldPosition;\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\tvWorldPosition = worldPosition;\n}\n"; +var distanceRGBA_vert = "#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}\n"; -var equirect_frag = "uniform sampler2D tEquirect;\nuniform float tFlip;\nvarying vec3 vWorldPosition;\n#include \nvoid main() {\n\tvec3 direction = normalize( vWorldPosition );\n\tvec2 sampleUV;\n\tsampleUV.y = saturate( tFlip * direction.y * -0.5 + 0.5 );\n\tsampleUV.x = atan( direction.z, direction.x ) * RECIPROCAL_PI2 + 0.5;\n\tgl_FragColor = texture2D( tEquirect, sampleUV );\n}\n"; +var equirect_frag = "uniform sampler2D tEquirect;\nvarying vec3 vWorldPosition;\n#include \nvoid main() {\n\tvec3 direction = normalize( vWorldPosition );\n\tvec2 sampleUV;\n\tsampleUV.y = asin( clamp( direction.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\tsampleUV.x = atan( direction.z, direction.x ) * RECIPROCAL_PI2 + 0.5;\n\tgl_FragColor = texture2D( tEquirect, sampleUV );\n}\n"; var equirect_vert = "varying vec3 vWorldPosition;\n#include \nvoid main() {\n\tvWorldPosition = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n}\n"; @@ -5765,33 +6212,33 @@ var linedashed_frag = "uniform vec3 diffuse;\nuniform float opacity;\nuniform fl var linedashed_vert = "uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvLineDistance = scale * lineDistance;\n\tvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\n\tgl_Position = projectionMatrix * mvPosition;\n\t#include \n\t#include \n\t#include \n}\n"; -var meshbasic_frag = "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 \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\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\treflectedLight.indirectDiffuse += texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\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\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; +var meshbasic_frag = "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 \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\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\treflectedLight.indirectDiffuse += texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\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\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; var meshbasic_vert = "#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#ifdef USE_ENVMAP\n\t#include \n\t#include \n\t#include \n\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}\n"; -var meshlambert_frag = "uniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\nvarying vec3 vLightFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\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 \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\treflectedLight.indirectDiffuse = getAmbientLightIrradiance( ambientLightColor );\n\t#include \n\treflectedLight.indirectDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb );\n\t#ifdef DOUBLE_SIDED\n\t\treflectedLight.directDiffuse = ( gl_FrontFacing ) ? vLightFront : vLightBack;\n\t#else\n\t\treflectedLight.directDiffuse = vLightFront;\n\t#endif\n\treflectedLight.directDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb ) * getShadowMask();\n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\t#include \n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; +var meshlambert_frag = "uniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\nvarying vec3 vLightFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\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 \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\treflectedLight.indirectDiffuse = getAmbientLightIrradiance( ambientLightColor );\n\t#include \n\treflectedLight.indirectDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb );\n\t#ifdef DOUBLE_SIDED\n\t\treflectedLight.directDiffuse = ( gl_FrontFacing ) ? vLightFront : vLightBack;\n\t#else\n\t\treflectedLight.directDiffuse = vLightFront;\n\t#endif\n\treflectedLight.directDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb ) * getShadowMask();\n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; var meshlambert_vert = "#define LAMBERT\nvarying vec3 vLightFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\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 \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\t#include \n\t#include \n\t#include \n}\n"; -var meshphong_frag = "#define PHONG\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;\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 \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\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\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\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include \n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; +var meshphong_frag = "#define PHONG\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;\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 \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\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\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\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include \n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; -var meshphong_vert = "#define PHONG\nvarying vec3 vViewPosition;\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 \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#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\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}\n"; +var meshphong_vert = "#define PHONG\nvarying vec3 vViewPosition;\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 \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#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\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}\n"; -var meshphysical_frag = "#define PHYSICAL\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifndef STANDARD\n\tuniform float clearCoat;\n\tuniform float clearCoatRoughness;\n#endif\nvarying vec3 vViewPosition;\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 \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\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\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\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; +var meshphysical_frag = "#define PHYSICAL\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifndef STANDARD\n\tuniform float clearCoat;\n\tuniform float clearCoatRoughness;\n#endif\nvarying vec3 vViewPosition;\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 \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\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\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\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; -var meshphysical_vert = "#define PHYSICAL\nvarying vec3 vViewPosition;\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 \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#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\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}\n"; +var meshphysical_vert = "#define PHYSICAL\nvarying vec3 vViewPosition;\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 \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#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\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}\n"; -var normal_frag = "#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\tgl_FragColor = vec4( packNormalToRGB( normal ), opacity );\n}\n"; +var normal_frag = "#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\tgl_FragColor = vec4( packNormalToRGB( normal ), opacity );\n}\n"; -var normal_vert = "#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\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#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}\n"; +var normal_vert = "#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\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#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}\n"; var points_frag = "uniform vec3 diffuse;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; var points_vert = "uniform float size;\nuniform float scale;\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#ifdef USE_SIZEATTENUATION\n\t\tgl_PointSize = size * ( scale / - mvPosition.z );\n\t#else\n\t\tgl_PointSize = size;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; -var shadow_frag = "uniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tgl_FragColor = vec4( 0.0, 0.0, 0.0, opacity * ( 1.0 - getShadowMask() ) );\n}\n"; +var shadow_frag = "uniform vec3 color;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tgl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\n\t#include \n}\n"; -var shadow_vert = "#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; +var shadow_vert = "#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; var ShaderChunk = { alphamap_fragment: alphamap_fragment, @@ -5851,7 +6298,6 @@ var ShaderChunk = { morphnormal_vertex: morphnormal_vertex, morphtarget_pars_vertex: morphtarget_pars_vertex, morphtarget_vertex: morphtarget_vertex, - normal_flip: normal_flip, normal_fragment: normal_fragment, normalmap_pars_fragment: normalmap_pars_fragment, packing: packing, @@ -5919,6 +6365,8 @@ var ShaderLib = { uniforms: UniformsUtils.merge( [ UniformsLib.common, + UniformsLib.specularmap, + UniformsLib.envmap, UniformsLib.aomap, UniformsLib.lightmap, UniformsLib.fog @@ -5933,6 +6381,8 @@ var ShaderLib = { uniforms: UniformsUtils.merge( [ UniformsLib.common, + UniformsLib.specularmap, + UniformsLib.envmap, UniformsLib.aomap, UniformsLib.lightmap, UniformsLib.emissivemap, @@ -5952,6 +6402,8 @@ var ShaderLib = { uniforms: UniformsUtils.merge( [ UniformsLib.common, + UniformsLib.specularmap, + UniformsLib.envmap, UniformsLib.aomap, UniformsLib.lightmap, UniformsLib.emissivemap, @@ -5977,6 +6429,7 @@ var ShaderLib = { uniforms: UniformsUtils.merge( [ UniformsLib.common, + UniformsLib.envmap, UniformsLib.aomap, UniformsLib.lightmap, UniformsLib.emissivemap, @@ -6075,15 +6528,10 @@ var ShaderLib = { }, - /* ------------------------------------------------------------------------- - // Cube map shader - ------------------------------------------------------------------------- */ - equirect: { uniforms: { tEquirect: { value: null }, - tFlip: { value: - 1 } }, vertexShader: ShaderChunk.equirect_vert, @@ -6093,13 +6541,35 @@ var ShaderLib = { distanceRGBA: { - uniforms: { - lightPos: { value: new Vector3() } - }, + uniforms: UniformsUtils.merge( [ + UniformsLib.common, + UniformsLib.displacementmap, + { + referencePosition: { value: new Vector3() }, + nearDistance: { value: 1 }, + farDistance: { value: 1000 } + } + ] ), vertexShader: ShaderChunk.distanceRGBA_vert, fragmentShader: ShaderChunk.distanceRGBA_frag + }, + + shadow: { + + uniforms: UniformsUtils.merge( [ + UniformsLib.lights, + UniformsLib.fog, + { + color: { value: new Color( 0x00000 ) }, + opacity: { value: 1.0 } + }, + ] ), + + vertexShader: ShaderChunk.shadow_vert, + fragmentShader: ShaderChunk.shadow_frag + } }; @@ -6341,10 +6811,7 @@ Object.assign( Box2.prototype, { * @author alteredq / http://alteredqualia.com/ */ -function LensFlarePlugin( renderer, flares ) { - - var gl = renderer.context; - var state = renderer.state; +function WebGLFlareRenderer( renderer, gl, state, textures, capabilities ) { var vertexBuffer, elementBuffer; var shader, program, attributes, uniforms; @@ -6515,7 +6982,7 @@ function LensFlarePlugin( renderer, flares ) { * reads these back and calculates occlusion. */ - this.render = function ( scene, camera, viewport ) { + this.render = function ( flares, scene, camera, viewport ) { if ( flares.length === 0 ) return; @@ -6542,7 +7009,7 @@ function LensFlarePlugin( renderer, flares ) { } - gl.useProgram( program ); + state.useProgram( program ); state.initAttributes(); state.enableAttribute( attributes.vertex ); @@ -6671,7 +7138,8 @@ function LensFlarePlugin( renderer, flares ) { gl.uniform3f( uniforms.color, sprite.color.r, sprite.color.g, sprite.color.b ); state.setBlending( sprite.blending, sprite.blendEquation, sprite.blendSrc, sprite.blendDst ); - renderer.setTexture2D( sprite.texture, 1 ); + + textures.setTexture2D( sprite.texture, 1 ); gl.drawElements( gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 ); @@ -6689,7 +7157,7 @@ function LensFlarePlugin( renderer, flares ) { state.enable( gl.DEPTH_TEST ); state.buffers.depth.setMask( true ); - renderer.resetGLState(); + state.reset(); }; @@ -6700,7 +7168,7 @@ function LensFlarePlugin( renderer, flares ) { var fragmentShader = gl.createShader( gl.FRAGMENT_SHADER ); var vertexShader = gl.createShader( gl.VERTEX_SHADER ); - var prefix = "precision " + renderer.getPrecision() + " float;\n"; + var prefix = "precision " + capabilities.precision + " float;\n"; gl.shaderSource( fragmentShader, prefix + shader.fragmentShader ); gl.shaderSource( vertexShader, prefix + shader.vertexShader ); @@ -6719,15 +7187,27 @@ function LensFlarePlugin( renderer, flares ) { } +/** + * @author mrdoob / http://mrdoob.com/ + */ + +function CanvasTexture( canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) { + + Texture.call( this, canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ); + + this.needsUpdate = true; + +} + +CanvasTexture.prototype = Object.create( Texture.prototype ); +CanvasTexture.prototype.constructor = CanvasTexture; + /** * @author mikael emtinger / http://gomo.se/ * @author alteredq / http://alteredqualia.com/ */ -function SpritePlugin( renderer, sprites ) { - - var gl = renderer.context; - var state = renderer.state; +function WebGLSpriteRenderer( renderer, gl, state, textures, capabilities ) { var vertexBuffer, elementBuffer; var program, attributes, uniforms; @@ -6789,6 +7269,7 @@ function SpritePlugin( renderer, sprites ) { fogNear: gl.getUniformLocation( program, 'fogNear' ), fogFar: gl.getUniformLocation( program, 'fogFar' ), fogColor: gl.getUniformLocation( program, 'fogColor' ), + fogDepth: gl.getUniformLocation( program, 'fogDepth' ), alphaTest: gl.getUniformLocation( program, 'alphaTest' ) }; @@ -6801,12 +7282,11 @@ function SpritePlugin( renderer, sprites ) { context.fillStyle = 'white'; context.fillRect( 0, 0, 8, 8 ); - texture = new Texture( canvas ); - texture.needsUpdate = true; + texture = new CanvasTexture( canvas ); } - this.render = function ( scene, camera ) { + this.render = function ( sprites, scene, camera ) { if ( sprites.length === 0 ) return; @@ -6818,7 +7298,7 @@ function SpritePlugin( renderer, sprites ) { } - gl.useProgram( program ); + state.useProgram( program ); state.initAttributes(); state.enableAttribute( attributes.position ); @@ -6899,6 +7379,8 @@ function SpritePlugin( renderer, sprites ) { if ( material.visible === false ) continue; + sprite.onBeforeRender( renderer, scene, camera, undefined, material, undefined ); + gl.uniform1f( uniforms.alphaTest, material.alphaTest ); gl.uniformMatrix4fv( uniforms.modelViewMatrix, false, sprite.modelViewMatrix.elements ); @@ -6944,25 +7426,19 @@ function SpritePlugin( renderer, sprites ) { state.buffers.depth.setTest( material.depthTest ); state.buffers.depth.setMask( material.depthWrite ); - if ( material.map ) { - - renderer.setTexture2D( material.map, 0 ); - - } else { - - renderer.setTexture2D( texture, 0 ); - - } + textures.setTexture2D( material.map || texture, 0 ); gl.drawElements( gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 ); + sprite.onAfterRender( renderer, scene, camera, undefined, material, undefined ); + } // restore gl state.enable( gl.CULL_FACE ); - renderer.resetGLState(); + state.reset(); }; @@ -6975,7 +7451,9 @@ function SpritePlugin( renderer, sprites ) { gl.shaderSource( vertexShader, [ - 'precision ' + renderer.getPrecision() + ' float;', + 'precision ' + capabilities.precision + ' float;', + + '#define SHADER_NAME ' + 'SpriteMaterial', 'uniform mat4 modelViewMatrix;', 'uniform mat4 projectionMatrix;', @@ -6988,6 +7466,7 @@ function SpritePlugin( renderer, sprites ) { 'attribute vec2 uv;', 'varying vec2 vUV;', + 'varying float fogDepth;', 'void main() {', @@ -6999,13 +7478,14 @@ function SpritePlugin( renderer, sprites ) { 'rotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;', 'rotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;', - 'vec4 finalPosition;', + 'vec4 mvPosition;', + + 'mvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );', + 'mvPosition.xy += rotatedPosition;', - 'finalPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );', - 'finalPosition.xy += rotatedPosition;', - 'finalPosition = projectionMatrix * finalPosition;', + 'gl_Position = projectionMatrix * mvPosition;', - 'gl_Position = finalPosition;', + 'fogDepth = - mvPosition.z;', '}' @@ -7013,7 +7493,9 @@ function SpritePlugin( renderer, sprites ) { gl.shaderSource( fragmentShader, [ - 'precision ' + renderer.getPrecision() + ' float;', + 'precision ' + capabilities.precision + ' float;', + + '#define SHADER_NAME ' + 'SpriteMaterial', 'uniform vec3 color;', 'uniform sampler2D map;', @@ -7027,33 +7509,33 @@ function SpritePlugin( renderer, sprites ) { 'uniform float alphaTest;', 'varying vec2 vUV;', + 'varying float fogDepth;', 'void main() {', 'vec4 texture = texture2D( map, vUV );', - 'if ( texture.a < alphaTest ) discard;', - 'gl_FragColor = vec4( color * texture.xyz, texture.a * opacity );', + 'if ( gl_FragColor.a < alphaTest ) discard;', + 'if ( fogType > 0 ) {', - 'float depth = gl_FragCoord.z / gl_FragCoord.w;', 'float fogFactor = 0.0;', 'if ( fogType == 1 ) {', - 'fogFactor = smoothstep( fogNear, fogFar, depth );', + 'fogFactor = smoothstep( fogNear, fogFar, fogDepth );', '} else {', 'const float LOG2 = 1.442695;', - 'fogFactor = exp2( - fogDensity * fogDensity * depth * depth * LOG2 );', + 'fogFactor = exp2( - fogDensity * fogDensity * fogDepth * fogDepth * LOG2 );', 'fogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 );', '}', - 'gl_FragColor = mix( gl_FragColor, vec4( fogColor, gl_FragColor.w ), fogFactor );', + 'gl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );', '}', @@ -7114,7 +7596,7 @@ function Material() { this.blending = NormalBlending; this.side = FrontSide; - this.shading = SmoothShading; // THREE.FlatShading, THREE.SmoothShading + this.flatShading = false; this.vertexColors = NoColors; // THREE.NoColors, THREE.VertexColors, THREE.FaceColors this.opacity = 1; @@ -7152,6 +7634,8 @@ function Material() { this.visible = true; + this.userData = {}; + this.needsUpdate = true; } @@ -7160,6 +7644,8 @@ Object.assign( Material.prototype, EventDispatcher.prototype, { isMaterial: true, + onBeforeCompile: function () {}, + setValues: function ( values ) { if ( values === undefined ) return; @@ -7175,6 +7661,15 @@ Object.assign( Material.prototype, EventDispatcher.prototype, { } + // for backward compatability if shading is set in the constructor + if ( key === 'shading' ) { + + console.warn( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' ); + this.flatShading = ( newValue === FlatShading ) ? true : false; + continue; + + } + var currentValue = this[ key ]; if ( currentValue === undefined ) { @@ -7290,7 +7785,7 @@ Object.assign( Material.prototype, EventDispatcher.prototype, { if ( this.sizeAttenuation !== undefined ) data.sizeAttenuation = this.sizeAttenuation; if ( this.blending !== NormalBlending ) data.blending = this.blending; - if ( this.shading !== SmoothShading ) data.shading = this.shading; + if ( this.flatShading === true ) data.flatShading = this.flatShading; if ( this.side !== FrontSide ) data.side = this.side; if ( this.vertexColors !== NoColors ) data.vertexColors = this.vertexColors; @@ -7301,17 +7796,21 @@ Object.assign( Material.prototype, EventDispatcher.prototype, { data.depthTest = this.depthTest; data.depthWrite = this.depthWrite; + 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.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.skinning = this.skinning; - data.morphTargets = this.morphTargets; + if ( this.morphTargets === true ) data.morphTargets = true; + if ( this.skinning === true ) data.skinning = true; - data.dithering = this.dithering; + if ( this.visible === false ) data.visible = false; + if ( JSON.stringify( this.userData ) !== '{}' ) data.userData = this.userData; // TODO: Copied from Object3D.toJSON @@ -7360,7 +7859,7 @@ Object.assign( Material.prototype, EventDispatcher.prototype, { this.blending = source.blending; this.side = source.side; - this.shading = source.shading; + this.flatShading = source.flatShading; this.vertexColors = source.vertexColors; this.opacity = source.opacity; @@ -7388,12 +7887,13 @@ Object.assign( Material.prototype, EventDispatcher.prototype, { this.dithering = source.dithering; this.alphaTest = source.alphaTest; - this.premultipliedAlpha = source.premultipliedAlpha; this.overdraw = source.overdraw; this.visible = source.visible; + this.userData = JSON.parse( JSON.stringify( source.userData ) ); + this.clipShadows = source.clipShadows; this.clipIntersection = source.clipIntersection; @@ -7627,6 +8127,85 @@ MeshDepthMaterial.prototype.copy = function ( source ) { }; +/** + * @author WestLangley / http://github.com/WestLangley + * + * parameters = { + * + * referencePosition: , + * nearDistance: , + * farDistance: , + * + * skinning: , + * morphTargets: , + * + * map: new THREE.Texture( ), + * + * alphaMap: new THREE.Texture( ), + * + * displacementMap: new THREE.Texture( ), + * displacementScale: , + * displacementBias: + * + * } + */ + +function MeshDistanceMaterial( parameters ) { + + Material.call( this ); + + this.type = 'MeshDistanceMaterial'; + + this.referencePosition = new Vector3(); + this.nearDistance = 1; + this.farDistance = 1000; + + this.skinning = false; + this.morphTargets = false; + + this.map = null; + + this.alphaMap = null; + + this.displacementMap = null; + this.displacementScale = 1; + this.displacementBias = 0; + + this.fog = false; + this.lights = false; + + this.setValues( parameters ); + +} + +MeshDistanceMaterial.prototype = Object.create( Material.prototype ); +MeshDistanceMaterial.prototype.constructor = MeshDistanceMaterial; + +MeshDistanceMaterial.prototype.isMeshDistanceMaterial = true; + +MeshDistanceMaterial.prototype.copy = function ( source ) { + + Material.prototype.copy.call( this, source ); + + this.referencePosition.copy( source.referencePosition ); + this.nearDistance = source.nearDistance; + this.farDistance = source.farDistance; + + this.skinning = source.skinning; + this.morphTargets = source.morphTargets; + + this.map = source.map; + + this.alphaMap = source.alphaMap; + + this.displacementMap = source.displacementMap; + this.displacementScale = source.displacementScale; + this.displacementBias = source.displacementBias; + + return this; + +}; + /** * @author bhouston / http://clara.io * @author WestLangley / http://github.com/WestLangley @@ -8175,433 +8754,98 @@ Object.assign( Sphere.prototype, { this.center.copy( sphere.center ); this.radius = sphere.radius; - return this; - - }, - - empty: function () { - - return ( this.radius <= 0 ); - - }, - - containsPoint: function ( point ) { - - return ( point.distanceToSquared( this.center ) <= ( this.radius * this.radius ) ); - - }, - - distanceToPoint: function ( point ) { - - return ( point.distanceTo( this.center ) - this.radius ); - - }, - - intersectsSphere: function ( sphere ) { - - var radiusSum = this.radius + sphere.radius; - - return sphere.center.distanceToSquared( this.center ) <= ( radiusSum * radiusSum ); - - }, - - intersectsBox: function ( box ) { - - return box.intersectsSphere( this ); - - }, - - intersectsPlane: function ( plane ) { - - // We use the following equation to compute the signed distance from - // the center of the sphere to the plane. - // - // distance = q * n - d - // - // If this distance is greater than the radius of the sphere, - // then there is no intersection. - - return Math.abs( this.center.dot( plane.normal ) - plane.constant ) <= this.radius; - - }, - - clampPoint: function ( point, optionalTarget ) { - - var deltaLengthSq = this.center.distanceToSquared( point ); - - var result = optionalTarget || new Vector3(); - - result.copy( point ); - - if ( deltaLengthSq > ( this.radius * this.radius ) ) { - - result.sub( this.center ).normalize(); - result.multiplyScalar( this.radius ).add( this.center ); - - } - - return result; - - }, - - getBoundingBox: function ( optionalTarget ) { - - var box = optionalTarget || new Box3(); - - box.set( this.center, this.center ); - box.expandByScalar( this.radius ); - - return box; - - }, - - applyMatrix4: function ( matrix ) { - - this.center.applyMatrix4( matrix ); - this.radius = this.radius * matrix.getMaxScaleOnAxis(); - - return this; - - }, - - translate: function ( offset ) { - - this.center.add( offset ); - - return this; - - }, - - equals: function ( sphere ) { - - return sphere.center.equals( this.center ) && ( sphere.radius === this.radius ); - - } - -} ); - -/** - * @author alteredq / http://alteredqualia.com/ - * @author WestLangley / http://github.com/WestLangley - * @author bhouston / http://clara.io - * @author tschw - */ - -function Matrix3() { - - this.elements = [ - - 1, 0, 0, - 0, 1, 0, - 0, 0, 1 - - ]; - - if ( arguments.length > 0 ) { - - console.error( 'THREE.Matrix3: the constructor no longer reads arguments. use .set() instead.' ); - - } - -} - -Object.assign( Matrix3.prototype, { - - isMatrix3: true, - - set: function ( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) { - - 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; - - return this; - - }, - - identity: function () { - - this.set( - - 1, 0, 0, - 0, 1, 0, - 0, 0, 1 - - ); - - return this; - - }, - - clone: function () { - - return new this.constructor().fromArray( this.elements ); - - }, - - copy: function ( m ) { - - var te = this.elements; - var me = m.elements; - - 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; - - }, - - setFromMatrix4: function ( m ) { - - var me = m.elements; - - this.set( - - me[ 0 ], me[ 4 ], me[ 8 ], - me[ 1 ], me[ 5 ], me[ 9 ], - me[ 2 ], me[ 6 ], me[ 10 ] - - ); - - return this; - - }, - - applyToBufferAttribute: function () { - - var v1 = new Vector3(); - - return function applyToBufferAttribute( attribute ) { - - for ( var i = 0, l = attribute.count; i < l; i ++ ) { - - v1.x = attribute.getX( i ); - v1.y = attribute.getY( i ); - v1.z = attribute.getZ( i ); - - v1.applyMatrix3( this ); - - attribute.setXYZ( i, v1.x, v1.y, v1.z ); - - } - - return attribute; - - }; - - }(), - - multiply: function ( m ) { - - return this.multiplyMatrices( this, m ); - - }, - - premultiply: function ( m ) { - - return this.multiplyMatrices( m, this ); - - }, - - multiplyMatrices: function ( a, b ) { - - var ae = a.elements; - var be = b.elements; - var te = this.elements; - - 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 ]; - - 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 ]; - - te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31; - te[ 3 ] = a11 * b12 + a12 * b22 + a13 * b32; - te[ 6 ] = a11 * b13 + a12 * b23 + a13 * b33; - - te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31; - te[ 4 ] = a21 * b12 + a22 * b22 + a23 * b32; - te[ 7 ] = a21 * b13 + a22 * b23 + a23 * b33; - - 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; - - }, - - multiplyScalar: function ( s ) { - - var te = this.elements; - - 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; - - return this; - - }, - - determinant: function () { - - var te = this.elements; - - 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 ]; - - return a * e * i - a * f * h - b * d * i + b * f * g + c * d * h - c * e * g; - - }, - - getInverse: function ( matrix, throwOnDegenerate ) { - - if ( matrix && matrix.isMatrix4 ) { - - console.error( "THREE.Matrix3.getInverse no longer takes a Matrix4 argument." ); - - } - - 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 ], - - t11 = n33 * n22 - n32 * n23, - t12 = n32 * n13 - n33 * n12, - t13 = n23 * n12 - n22 * n13, - - det = n11 * t11 + n21 * t12 + n31 * t13; - - if ( det === 0 ) { - - var msg = "THREE.Matrix3.getInverse(): can't invert matrix, determinant is 0"; - - if ( throwOnDegenerate === true ) { - - throw new Error( msg ); - - } else { + return this; - console.warn( msg ); + }, - } + empty: function () { - return this.identity(); + return ( this.radius <= 0 ); - } + }, - var detInv = 1 / det; + containsPoint: function ( point ) { - te[ 0 ] = t11 * detInv; - te[ 1 ] = ( n31 * n23 - n33 * n21 ) * detInv; - te[ 2 ] = ( n32 * n21 - n31 * n22 ) * detInv; + return ( point.distanceToSquared( this.center ) <= ( this.radius * this.radius ) ); - te[ 3 ] = t12 * detInv; - te[ 4 ] = ( n33 * n11 - n31 * n13 ) * detInv; - te[ 5 ] = ( n31 * n12 - n32 * n11 ) * detInv; + }, - te[ 6 ] = t13 * detInv; - te[ 7 ] = ( n21 * n13 - n23 * n11 ) * detInv; - te[ 8 ] = ( n22 * n11 - n21 * n12 ) * detInv; + distanceToPoint: function ( point ) { - return this; + return ( point.distanceTo( this.center ) - this.radius ); }, - transpose: function () { - - var tmp, m = this.elements; + intersectsSphere: function ( sphere ) { - 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; + var radiusSum = this.radius + sphere.radius; - return this; + return sphere.center.distanceToSquared( this.center ) <= ( radiusSum * radiusSum ); }, - getNormalMatrix: function ( matrix4 ) { + intersectsBox: function ( box ) { - return this.setFromMatrix4( matrix4 ).getInverse( this ).transpose(); + return box.intersectsSphere( this ); }, - transposeIntoArray: function ( r ) { + intersectsPlane: function ( plane ) { - var m = this.elements; + return Math.abs( plane.distanceToPoint( this.center ) ) <= this.radius; - 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 ]; + }, - return this; + clampPoint: function ( point, optionalTarget ) { - }, + var deltaLengthSq = this.center.distanceToSquared( point ); - equals: function ( matrix ) { + var result = optionalTarget || new Vector3(); - var te = this.elements; - var me = matrix.elements; + result.copy( point ); - for ( var i = 0; i < 9; i ++ ) { + if ( deltaLengthSq > ( this.radius * this.radius ) ) { - if ( te[ i ] !== me[ i ] ) return false; + result.sub( this.center ).normalize(); + result.multiplyScalar( this.radius ).add( this.center ); } - return true; + return result; }, - fromArray: function ( array, offset ) { + getBoundingBox: function ( optionalTarget ) { - if ( offset === undefined ) offset = 0; + var box = optionalTarget || new Box3(); - for ( var i = 0; i < 9; i ++ ) { + box.set( this.center, this.center ); + box.expandByScalar( this.radius ); - this.elements[ i ] = array[ i + offset ]; + return box; - } + }, + + applyMatrix4: function ( matrix ) { + + this.center.applyMatrix4( matrix ); + this.radius = this.radius * matrix.getMaxScaleOnAxis(); return this; }, - toArray: function ( array, offset ) { - - if ( array === undefined ) array = []; - if ( offset === undefined ) offset = 0; + translate: function ( offset ) { - var te = this.elements; + this.center.add( offset ); - 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 ]; + equals: function ( sphere ) { - return array; + return sphere.center.equals( this.center ) && ( sphere.radius === this.radius ); } @@ -8613,6 +8857,8 @@ Object.assign( Matrix3.prototype, { function Plane( normal, constant ) { + // normal is assumed to be normalized + this.normal = ( normal !== undefined ) ? normal : new Vector3( 1, 0, 0 ); this.constant = ( constant !== undefined ) ? constant : 0; @@ -8641,7 +8887,7 @@ Object.assign( Plane.prototype, { setFromNormalAndCoplanarPoint: function ( normal, point ) { this.normal.copy( normal ); - this.constant = - point.dot( this.normal ); // must be this.normal, not normal, as this.normal is normalized + this.constant = - point.dot( this.normal ); return this; @@ -8716,16 +8962,9 @@ Object.assign( Plane.prototype, { projectPoint: function ( point, optionalTarget ) { - return this.orthoPoint( point, optionalTarget ).sub( point ).negate(); - - }, - - orthoPoint: function ( point, optionalTarget ) { - - var perpendicularMagnitude = this.distanceToPoint( point ); - var result = optionalTarget || new Vector3(); - return result.copy( this.normal ).multiplyScalar( perpendicularMagnitude ); + + return result.copy( this.normal ).multiplyScalar( - this.distanceToPoint( point ) ).add( point ); }, @@ -8795,6 +9034,7 @@ Object.assign( Plane.prototype, { coplanarPoint: function ( optionalTarget ) { var result = optionalTarget || new Vector3(); + return result.copy( this.normal ).multiplyScalar( - this.constant ); }, @@ -8806,14 +9046,12 @@ Object.assign( Plane.prototype, { return function applyMatrix4( matrix, optionalNormalMatrix ) { + var normalMatrix = optionalNormalMatrix || m1.getNormalMatrix( matrix ); + var referencePoint = this.coplanarPoint( v1 ).applyMatrix4( matrix ); - // transform normal based on theory here: - // http://www.songho.ca/opengl/gl_normaltransform.html - var normalMatrix = optionalNormalMatrix || m1.getNormalMatrix( matrix ); var normal = this.normal.applyMatrix3( normalMatrix ).normalize(); - // recalculate constant (like in setFromNormalAndCoplanarPoint) this.constant = - referencePoint.dot( normal ); return this; @@ -8824,7 +9062,7 @@ Object.assign( Plane.prototype, { translate: function ( offset ) { - this.constant = this.constant - offset.dot( this.normal ); + this.constant -= offset.dot( this.normal ); return this; @@ -9038,17 +9276,13 @@ Object.assign( Frustum.prototype, { * @author mrdoob / http://mrdoob.com/ */ -function WebGLShadowMap( _renderer, _lights, _objects, capabilities ) { +function WebGLShadowMap( _renderer, _objects, maxTextureSize ) { - var _gl = _renderer.context, - _state = _renderer.state, - _frustum = new Frustum(), + var _frustum = new Frustum(), _projScreenMatrix = new Matrix4(), - _lightShadows = _lights.shadows, - _shadowMapSize = new Vector2(), - _maxShadowMapSize = new Vector2( capabilities.maxTextureSize, capabilities.maxTextureSize ), + _maxShadowMapSize = new Vector2( maxTextureSize, maxTextureSize ), _lookTarget = new Vector3(), _lightPositionWorld = new Vector3(), @@ -9080,34 +9314,29 @@ function WebGLShadowMap( _renderer, _lights, _objects, capabilities ) { // init - var depthMaterialTemplate = new MeshDepthMaterial(); - depthMaterialTemplate.depthPacking = RGBADepthPacking; - depthMaterialTemplate.clipping = true; - - var distanceShader = ShaderLib[ "distanceRGBA" ]; - var distanceUniforms = UniformsUtils.clone( distanceShader.uniforms ); - for ( var i = 0; i !== _NumberOfMaterialVariants; ++ i ) { var useMorphing = ( i & _MorphingFlag ) !== 0; var useSkinning = ( i & _SkinningFlag ) !== 0; - var depthMaterial = depthMaterialTemplate.clone(); - depthMaterial.morphTargets = useMorphing; - depthMaterial.skinning = useSkinning; + var depthMaterial = new MeshDepthMaterial( { + + depthPacking: RGBADepthPacking, + + morphTargets: useMorphing, + skinning: useSkinning + + } ); _depthMaterials[ i ] = depthMaterial; - var distanceMaterial = new ShaderMaterial( { - defines: { - 'USE_SHADOWMAP': '' - }, - uniforms: distanceUniforms, - vertexShader: distanceShader.vertexShader, - fragmentShader: distanceShader.fragmentShader, + // + + var distanceMaterial = new MeshDistanceMaterial( { + morphTargets: useMorphing, - skinning: useSkinning, - clipping: true + skinning: useSkinning + } ); _distanceMaterials[ i ] = distanceMaterial; @@ -9128,12 +9357,16 @@ function WebGLShadowMap( _renderer, _lights, _objects, capabilities ) { this.renderReverseSided = true; this.renderSingleSided = true; - this.render = function ( scene, camera ) { + this.render = function ( lights, scene, camera ) { if ( scope.enabled === false ) return; if ( scope.autoUpdate === false && scope.needsUpdate === false ) return; - if ( _lightShadows.length === 0 ) return; + if ( lights.length === 0 ) return; + + // TODO Clean up (needed in case of contextlost) + var _gl = _renderer.context; + var _state = _renderer.state; // Set GL state for depth map. _state.disable( _gl.BLEND ); @@ -9145,9 +9378,9 @@ function WebGLShadowMap( _renderer, _lights, _objects, capabilities ) { var faceCount; - for ( var i = 0, il = _lightShadows.length; i < il; i ++ ) { + for ( var i = 0, il = lights.length; i < il; i ++ ) { - var light = _lightShadows[ i ]; + var light = lights[ i ]; var shadow = light.shadow; var isPointLight = light && light.isPointLight; @@ -9163,850 +9396,467 @@ function WebGLShadowMap( _renderer, _lights, _objects, capabilities ) { _shadowMapSize.copy( shadow.mapSize ); _shadowMapSize.min( _maxShadowMapSize ); - if ( isPointLight ) { - - var vpWidth = _shadowMapSize.x; - var vpHeight = _shadowMapSize.y; - - // These viewports map a cube-map onto a 2D texture with the - // following orientation: - // - // xzXZ - // y Y - // - // X - Positive x direction - // x - Negative x direction - // Y - Positive y direction - // y - Negative y direction - // Z - Positive z direction - // z - Negative z direction - - // positive X - cube2DViewPorts[ 0 ].set( vpWidth * 2, vpHeight, vpWidth, vpHeight ); - // negative X - cube2DViewPorts[ 1 ].set( 0, vpHeight, vpWidth, vpHeight ); - // positive Z - cube2DViewPorts[ 2 ].set( vpWidth * 3, vpHeight, vpWidth, vpHeight ); - // negative Z - cube2DViewPorts[ 3 ].set( vpWidth, vpHeight, vpWidth, vpHeight ); - // positive Y - cube2DViewPorts[ 4 ].set( vpWidth * 3, 0, vpWidth, vpHeight ); - // negative Y - cube2DViewPorts[ 5 ].set( vpWidth, 0, vpWidth, vpHeight ); - - _shadowMapSize.x *= 4.0; - _shadowMapSize.y *= 2.0; - - } - - if ( shadow.map === null ) { - - var pars = { minFilter: NearestFilter, magFilter: NearestFilter, format: RGBAFormat }; - - shadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars ); - shadow.map.texture.name = light.name + ".shadowMap"; - - shadowCamera.updateProjectionMatrix(); - - } - - if ( shadow.isSpotLightShadow ) { - - shadow.update( light ); - - } - - var shadowMap = shadow.map; - var shadowMatrix = shadow.matrix; - - _lightPositionWorld.setFromMatrixPosition( light.matrixWorld ); - shadowCamera.position.copy( _lightPositionWorld ); - - if ( isPointLight ) { - - faceCount = 6; - - // for point lights we set the shadow matrix to be a translation-only matrix - // equal to inverse of the light's position - - shadowMatrix.makeTranslation( - _lightPositionWorld.x, - _lightPositionWorld.y, - _lightPositionWorld.z ); - - } else { - - faceCount = 1; - - _lookTarget.setFromMatrixPosition( light.target.matrixWorld ); - shadowCamera.lookAt( _lookTarget ); - shadowCamera.updateMatrixWorld(); - shadowCamera.matrixWorldInverse.getInverse( shadowCamera.matrixWorld ); - - // compute shadow matrix - - shadowMatrix.set( - 0.5, 0.0, 0.0, 0.5, - 0.0, 0.5, 0.0, 0.5, - 0.0, 0.0, 0.5, 0.5, - 0.0, 0.0, 0.0, 1.0 - ); - - shadowMatrix.multiply( shadowCamera.projectionMatrix ); - shadowMatrix.multiply( shadowCamera.matrixWorldInverse ); - - } - - _renderer.setRenderTarget( shadowMap ); - _renderer.clear(); - - // render shadow map for each cube face (if omni-directional) or - // run a single pass if not - - for ( var face = 0; face < faceCount; face ++ ) { - - if ( isPointLight ) { - - _lookTarget.copy( shadowCamera.position ); - _lookTarget.add( cubeDirections[ face ] ); - shadowCamera.up.copy( cubeUps[ face ] ); - shadowCamera.lookAt( _lookTarget ); - shadowCamera.updateMatrixWorld(); - shadowCamera.matrixWorldInverse.getInverse( shadowCamera.matrixWorld ); - - var vpDimensions = cube2DViewPorts[ face ]; - _state.viewport( vpDimensions ); - - } - - // update camera matrices and frustum - - _projScreenMatrix.multiplyMatrices( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse ); - _frustum.setFromMatrix( _projScreenMatrix ); - - // set object matrices & frustum culling - - renderObject( scene, camera, shadowCamera, isPointLight ); - - } - - } - - // Restore GL state. - var clearColor = _renderer.getClearColor(); - var clearAlpha = _renderer.getClearAlpha(); - _renderer.setClearColor( clearColor, clearAlpha ); - - scope.needsUpdate = false; - - }; - - function getDepthMaterial( object, material, isPointLight, lightPositionWorld ) { - - var geometry = object.geometry; - - var result = null; - - var materialVariants = _depthMaterials; - var customMaterial = object.customDepthMaterial; - - if ( isPointLight ) { - - materialVariants = _distanceMaterials; - customMaterial = object.customDistanceMaterial; - - } - - if ( ! customMaterial ) { - - var useMorphing = false; - - if ( material.morphTargets ) { - - if ( geometry && geometry.isBufferGeometry ) { - - useMorphing = geometry.morphAttributes && geometry.morphAttributes.position && geometry.morphAttributes.position.length > 0; - - } else if ( geometry && geometry.isGeometry ) { - - useMorphing = geometry.morphTargets && geometry.morphTargets.length > 0; - - } - - } - - if ( object.isSkinnedMesh && material.skinning === false ) { - - console.warn( 'THREE.WebGLShadowMap: THREE.SkinnedMesh with material.skinning set to false:', object ); - - } - - var useSkinning = object.isSkinnedMesh && material.skinning; - - var variantIndex = 0; - - if ( useMorphing ) variantIndex |= _MorphingFlag; - if ( useSkinning ) variantIndex |= _SkinningFlag; - - result = materialVariants[ variantIndex ]; - - } else { - - result = customMaterial; - - } - - if ( _renderer.localClippingEnabled && - material.clipShadows === true && - material.clippingPlanes.length !== 0 ) { - - // in this case we need a unique material instance reflecting the - // appropriate state - - var keyA = result.uuid, keyB = material.uuid; - - var materialsForVariant = _materialCache[ keyA ]; - - if ( materialsForVariant === undefined ) { - - materialsForVariant = {}; - _materialCache[ keyA ] = materialsForVariant; - - } - - var cachedMaterial = materialsForVariant[ keyB ]; - - if ( cachedMaterial === undefined ) { - - cachedMaterial = result.clone(); - materialsForVariant[ keyB ] = cachedMaterial; - - } - - result = cachedMaterial; - - } - - result.visible = material.visible; - result.wireframe = material.wireframe; - - var side = material.side; - - if ( scope.renderSingleSided && side == DoubleSide ) { - - side = FrontSide; - - } - - if ( scope.renderReverseSided ) { - - if ( side === FrontSide ) side = BackSide; - else if ( side === BackSide ) side = FrontSide; - - } - - result.side = side; - - result.clipShadows = material.clipShadows; - result.clippingPlanes = material.clippingPlanes; - - result.wireframeLinewidth = material.wireframeLinewidth; - result.linewidth = material.linewidth; - - if ( isPointLight && result.uniforms.lightPos !== undefined ) { - - result.uniforms.lightPos.value.copy( lightPositionWorld ); - - } - - return result; - - } - - function renderObject( object, camera, shadowCamera, isPointLight ) { - - if ( object.visible === false ) return; - - var visible = object.layers.test( camera.layers ); - - if ( visible && ( object.isMesh || object.isLine || object.isPoints ) ) { - - if ( object.castShadow && ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) ) { - - object.modelViewMatrix.multiplyMatrices( shadowCamera.matrixWorldInverse, object.matrixWorld ); - - var geometry = _objects.update( object ); - var material = object.material; - - if ( Array.isArray( material ) ) { - - var groups = geometry.groups; - - for ( var k = 0, kl = groups.length; k < kl; k ++ ) { - - var group = groups[ k ]; - var groupMaterial = material[ group.materialIndex ]; - - if ( groupMaterial && groupMaterial.visible ) { - - var depthMaterial = getDepthMaterial( object, groupMaterial, isPointLight, _lightPositionWorld ); - _renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, group ); - - } - - } - - } else if ( material.visible ) { - - var depthMaterial = getDepthMaterial( object, material, isPointLight, _lightPositionWorld ); - _renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, null ); - - } - - } - - } - - var children = object.children; - - for ( var i = 0, l = children.length; i < l; i ++ ) { - - renderObject( children[ i ], camera, shadowCamera, isPointLight ); - - } - - } - -} - -/** - * @author bhouston / http://clara.io - */ - -function Ray( origin, direction ) { - - this.origin = ( origin !== undefined ) ? origin : new Vector3(); - this.direction = ( direction !== undefined ) ? direction : new Vector3(); - -} - -Object.assign( Ray.prototype, { - - set: function ( origin, direction ) { - - this.origin.copy( origin ); - this.direction.copy( direction ); - - return this; - - }, - - clone: function () { - - return new this.constructor().copy( this ); - - }, - - copy: function ( ray ) { - - this.origin.copy( ray.origin ); - this.direction.copy( ray.direction ); - - return this; - - }, - - at: function ( t, optionalTarget ) { - - var result = optionalTarget || new Vector3(); - - return result.copy( this.direction ).multiplyScalar( t ).add( this.origin ); - - }, - - lookAt: function ( v ) { - - this.direction.copy( v ).sub( this.origin ).normalize(); - - return this; - - }, - - recast: function () { - - var v1 = new Vector3(); - - return function recast( t ) { - - this.origin.copy( this.at( t, v1 ) ); - - return this; - - }; - - }(), - - closestPointToPoint: function ( point, optionalTarget ) { - - var result = optionalTarget || new Vector3(); - result.subVectors( point, this.origin ); - var directionDistance = result.dot( this.direction ); - - if ( directionDistance < 0 ) { - - return result.copy( this.origin ); - - } + if ( isPointLight ) { - return result.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin ); + var vpWidth = _shadowMapSize.x; + var vpHeight = _shadowMapSize.y; - }, + // These viewports map a cube-map onto a 2D texture with the + // following orientation: + // + // xzXZ + // y Y + // + // X - Positive x direction + // x - Negative x direction + // Y - Positive y direction + // y - Negative y direction + // Z - Positive z direction + // z - Negative z direction - distanceToPoint: function ( point ) { + // positive X + cube2DViewPorts[ 0 ].set( vpWidth * 2, vpHeight, vpWidth, vpHeight ); + // negative X + cube2DViewPorts[ 1 ].set( 0, vpHeight, vpWidth, vpHeight ); + // positive Z + cube2DViewPorts[ 2 ].set( vpWidth * 3, vpHeight, vpWidth, vpHeight ); + // negative Z + cube2DViewPorts[ 3 ].set( vpWidth, vpHeight, vpWidth, vpHeight ); + // positive Y + cube2DViewPorts[ 4 ].set( vpWidth * 3, 0, vpWidth, vpHeight ); + // negative Y + cube2DViewPorts[ 5 ].set( vpWidth, 0, vpWidth, vpHeight ); - return Math.sqrt( this.distanceSqToPoint( point ) ); + _shadowMapSize.x *= 4.0; + _shadowMapSize.y *= 2.0; - }, + } - distanceSqToPoint: function () { + if ( shadow.map === null ) { - var v1 = new Vector3(); + var pars = { minFilter: NearestFilter, magFilter: NearestFilter, format: RGBAFormat }; - return function distanceSqToPoint( point ) { + shadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars ); + shadow.map.texture.name = light.name + ".shadowMap"; - var directionDistance = v1.subVectors( point, this.origin ).dot( this.direction ); + shadowCamera.updateProjectionMatrix(); - // point behind the ray + } - if ( directionDistance < 0 ) { + if ( shadow.isSpotLightShadow ) { - return this.origin.distanceToSquared( point ); + shadow.update( light ); } - v1.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin ); - - return v1.distanceToSquared( point ); + var shadowMap = shadow.map; + var shadowMatrix = shadow.matrix; - }; + _lightPositionWorld.setFromMatrixPosition( light.matrixWorld ); + shadowCamera.position.copy( _lightPositionWorld ); - }(), + if ( isPointLight ) { - distanceSqToSegment: function () { + faceCount = 6; - var segCenter = new Vector3(); - var segDir = new Vector3(); - var diff = new Vector3(); + // for point lights we set the shadow matrix to be a translation-only matrix + // equal to inverse of the light's position - return function distanceSqToSegment( v0, v1, optionalPointOnRay, optionalPointOnSegment ) { + shadowMatrix.makeTranslation( - _lightPositionWorld.x, - _lightPositionWorld.y, - _lightPositionWorld.z ); - // 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 + } else { - segCenter.copy( v0 ).add( v1 ).multiplyScalar( 0.5 ); - segDir.copy( v1 ).sub( v0 ).normalize(); - diff.copy( this.origin ).sub( segCenter ); + faceCount = 1; - 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; + _lookTarget.setFromMatrixPosition( light.target.matrixWorld ); + shadowCamera.lookAt( _lookTarget ); + shadowCamera.updateMatrixWorld(); - if ( det > 0 ) { + // compute shadow matrix - // The ray and segment are not parallel. + shadowMatrix.set( + 0.5, 0.0, 0.0, 0.5, + 0.0, 0.5, 0.0, 0.5, + 0.0, 0.0, 0.5, 0.5, + 0.0, 0.0, 0.0, 1.0 + ); - s0 = a01 * b1 - b0; - s1 = a01 * b0 - b1; - extDet = segExtent * det; + shadowMatrix.multiply( shadowCamera.projectionMatrix ); + shadowMatrix.multiply( shadowCamera.matrixWorldInverse ); - if ( s0 >= 0 ) { + } - if ( s1 >= - extDet ) { + _renderer.setRenderTarget( shadowMap ); + _renderer.clear(); - if ( s1 <= extDet ) { + // render shadow map for each cube face (if omni-directional) or + // run a single pass if not - // region 0 - // Minimum at interior points of ray and segment. + for ( var face = 0; face < faceCount; face ++ ) { - var invDet = 1 / det; - s0 *= invDet; - s1 *= invDet; - sqrDist = s0 * ( s0 + a01 * s1 + 2 * b0 ) + s1 * ( a01 * s0 + s1 + 2 * b1 ) + c; + if ( isPointLight ) { - } else { + _lookTarget.copy( shadowCamera.position ); + _lookTarget.add( cubeDirections[ face ] ); + shadowCamera.up.copy( cubeUps[ face ] ); + shadowCamera.lookAt( _lookTarget ); + shadowCamera.updateMatrixWorld(); - // region 1 + var vpDimensions = cube2DViewPorts[ face ]; + _state.viewport( vpDimensions ); - s1 = segExtent; - s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); - sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; + } - } + // update camera matrices and frustum - } else { + _projScreenMatrix.multiplyMatrices( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse ); + _frustum.setFromMatrix( _projScreenMatrix ); - // region 5 + // set object matrices & frustum culling - s1 = - segExtent; - s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); - sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; + renderObject( scene, camera, shadowCamera, isPointLight ); - } + } - } else { + } - if ( s1 <= - extDet ) { + scope.needsUpdate = false; - // region 4 + }; - 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; + function getDepthMaterial( object, material, isPointLight, lightPositionWorld, shadowCameraNear, shadowCameraFar ) { - } else if ( s1 <= extDet ) { + var geometry = object.geometry; - // region 3 + var result = null; - s0 = 0; - s1 = Math.min( Math.max( - segExtent, - b1 ), segExtent ); - sqrDist = s1 * ( s1 + 2 * b1 ) + c; + var materialVariants = _depthMaterials; + var customMaterial = object.customDepthMaterial; - } else { + if ( isPointLight ) { - // region 2 + materialVariants = _distanceMaterials; + customMaterial = object.customDistanceMaterial; - 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; + } - } + if ( ! customMaterial ) { - } + var useMorphing = false; - } else { + if ( material.morphTargets ) { - // Ray and segment are parallel. + if ( geometry && geometry.isBufferGeometry ) { - s1 = ( a01 > 0 ) ? - segExtent : segExtent; - s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); - sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; + useMorphing = geometry.morphAttributes && geometry.morphAttributes.position && geometry.morphAttributes.position.length > 0; - } + } else if ( geometry && geometry.isGeometry ) { - if ( optionalPointOnRay ) { + useMorphing = geometry.morphTargets && geometry.morphTargets.length > 0; - optionalPointOnRay.copy( this.direction ).multiplyScalar( s0 ).add( this.origin ); + } } - if ( optionalPointOnSegment ) { + if ( object.isSkinnedMesh && material.skinning === false ) { - optionalPointOnSegment.copy( segDir ).multiplyScalar( s1 ).add( segCenter ); + console.warn( 'THREE.WebGLShadowMap: THREE.SkinnedMesh with material.skinning set to false:', object ); } - return sqrDist; + var useSkinning = object.isSkinnedMesh && material.skinning; - }; + var variantIndex = 0; - }(), + if ( useMorphing ) variantIndex |= _MorphingFlag; + if ( useSkinning ) variantIndex |= _SkinningFlag; - intersectSphere: function () { + result = materialVariants[ variantIndex ]; - var v1 = new Vector3(); + } else { - return function intersectSphere( sphere, optionalTarget ) { + result = customMaterial; - v1.subVectors( sphere.center, this.origin ); - var tca = v1.dot( this.direction ); - var d2 = v1.dot( v1 ) - tca * tca; - var radius2 = sphere.radius * sphere.radius; + } - if ( d2 > radius2 ) return null; + if ( _renderer.localClippingEnabled && + material.clipShadows === true && + material.clippingPlanes.length !== 0 ) { - var thc = Math.sqrt( radius2 - d2 ); + // in this case we need a unique material instance reflecting the + // appropriate state - // t0 = first intersect point - entrance on front of sphere - var t0 = tca - thc; + var keyA = result.uuid, keyB = material.uuid; - // t1 = second intersect point - exit point on back of sphere - var t1 = tca + thc; + var materialsForVariant = _materialCache[ keyA ]; - // test to see if both t0 and t1 are behind the ray - if so, return null - if ( t0 < 0 && t1 < 0 ) return null; + if ( materialsForVariant === undefined ) { - // 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, optionalTarget ); + materialsForVariant = {}; + _materialCache[ keyA ] = materialsForVariant; - // else t0 is in front of the ray, so return the first collision point scaled by t0 - return this.at( t0, optionalTarget ); + } - }; + var cachedMaterial = materialsForVariant[ keyB ]; - }(), + if ( cachedMaterial === undefined ) { - intersectsSphere: function ( sphere ) { + cachedMaterial = result.clone(); + materialsForVariant[ keyB ] = cachedMaterial; - return this.distanceToPoint( sphere.center ) <= sphere.radius; + } - }, + result = cachedMaterial; - distanceToPlane: function ( plane ) { + } - var denominator = plane.normal.dot( this.direction ); + result.visible = material.visible; + result.wireframe = material.wireframe; - if ( denominator === 0 ) { + var side = material.side; - // line is coplanar, return origin - if ( plane.distanceToPoint( this.origin ) === 0 ) { + if ( scope.renderSingleSided && side == DoubleSide ) { - return 0; + side = FrontSide; - } + } - // Null is preferable to undefined since undefined means.... it is undefined + if ( scope.renderReverseSided ) { - return null; + if ( side === FrontSide ) side = BackSide; + else if ( side === BackSide ) side = FrontSide; } - var t = - ( this.origin.dot( plane.normal ) + plane.constant ) / denominator; - - // Return if the ray never intersects the plane + result.side = side; - return t >= 0 ? t : null; + result.clipShadows = material.clipShadows; + result.clippingPlanes = material.clippingPlanes; + result.clipIntersection = material.clipIntersection; - }, + result.wireframeLinewidth = material.wireframeLinewidth; + result.linewidth = material.linewidth; - intersectPlane: function ( plane, optionalTarget ) { + if ( isPointLight && result.isMeshDistanceMaterial ) { - var t = this.distanceToPlane( plane ); + result.referencePosition.copy( lightPositionWorld ); + result.nearDistance = shadowCameraNear; + result.farDistance = shadowCameraFar; - if ( t === null ) { + } - return null; + return result; - } + } - return this.at( t, optionalTarget ); + function renderObject( object, camera, shadowCamera, isPointLight ) { - }, + if ( object.visible === false ) return; - intersectsPlane: function ( plane ) { + var visible = object.layers.test( camera.layers ); - // check if the ray lies on the plane first + if ( visible && ( object.isMesh || object.isLine || object.isPoints ) ) { - var distToPoint = plane.distanceToPoint( this.origin ); + if ( object.castShadow && ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) ) { - if ( distToPoint === 0 ) { + object.modelViewMatrix.multiplyMatrices( shadowCamera.matrixWorldInverse, object.matrixWorld ); - return true; + var geometry = _objects.update( object ); + var material = object.material; - } + if ( Array.isArray( material ) ) { - var denominator = plane.normal.dot( this.direction ); + var groups = geometry.groups; - if ( denominator * distToPoint < 0 ) { + for ( var k = 0, kl = groups.length; k < kl; k ++ ) { - return true; + var group = groups[ k ]; + var groupMaterial = material[ group.materialIndex ]; - } + if ( groupMaterial && groupMaterial.visible ) { - // ray origin is behind the plane (and is pointing behind it) + var depthMaterial = getDepthMaterial( object, groupMaterial, isPointLight, _lightPositionWorld, shadowCamera.near, shadowCamera.far ); + _renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, group ); - return false; + } - }, + } - intersectBox: function ( box, optionalTarget ) { + } else if ( material.visible ) { - var tmin, tmax, tymin, tymax, tzmin, tzmax; + var depthMaterial = getDepthMaterial( object, material, isPointLight, _lightPositionWorld, shadowCamera.near, shadowCamera.far ); + _renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, null ); - var invdirx = 1 / this.direction.x, - invdiry = 1 / this.direction.y, - invdirz = 1 / this.direction.z; + } - var origin = this.origin; + } - if ( invdirx >= 0 ) { + } - tmin = ( box.min.x - origin.x ) * invdirx; - tmax = ( box.max.x - origin.x ) * invdirx; + var children = object.children; - } else { + for ( var i = 0, l = children.length; i < l; i ++ ) { - tmin = ( box.max.x - origin.x ) * invdirx; - tmax = ( box.min.x - origin.x ) * invdirx; + renderObject( children[ i ], camera, shadowCamera, isPointLight ); } - if ( invdiry >= 0 ) { + } - tymin = ( box.min.y - origin.y ) * invdiry; - tymax = ( box.max.y - origin.y ) * invdiry; +} - } else { +/** + * @author mrdoob / http://mrdoob.com/ + */ - tymin = ( box.max.y - origin.y ) * invdiry; - tymax = ( box.min.y - origin.y ) * invdiry; +function WebGLAttributes( gl ) { - } + var buffers = {}; - if ( ( tmin > tymax ) || ( tymin > tmax ) ) return null; + function createBuffer( attribute, bufferType ) { - // These lines also handle the case where tmin or tmax is NaN - // (result of 0 * Infinity). x !== x returns true if x is NaN + var array = attribute.array; + var usage = attribute.dynamic ? gl.DYNAMIC_DRAW : gl.STATIC_DRAW; - if ( tymin > tmin || tmin !== tmin ) tmin = tymin; + var buffer = gl.createBuffer(); - if ( tymax < tmax || tmax !== tmax ) tmax = tymax; + gl.bindBuffer( bufferType, buffer ); + gl.bufferData( bufferType, array, usage ); - if ( invdirz >= 0 ) { + attribute.onUploadCallback(); - tzmin = ( box.min.z - origin.z ) * invdirz; - tzmax = ( box.max.z - origin.z ) * invdirz; + var type = gl.FLOAT; - } else { + if ( array instanceof Float32Array ) { - tzmin = ( box.max.z - origin.z ) * invdirz; - tzmax = ( box.min.z - origin.z ) * invdirz; + type = gl.FLOAT; - } + } else if ( array instanceof Float64Array ) { - if ( ( tmin > tzmax ) || ( tzmin > tmax ) ) return null; + console.warn( 'THREE.WebGLAttributes: Unsupported data buffer format: Float64Array.' ); - if ( tzmin > tmin || tmin !== tmin ) tmin = tzmin; + } else if ( array instanceof Uint16Array ) { - if ( tzmax < tmax || tmax !== tmax ) tmax = tzmax; + type = gl.UNSIGNED_SHORT; - //return point closest to the ray (positive side) + } else if ( array instanceof Int16Array ) { - if ( tmax < 0 ) return null; + type = gl.SHORT; - return this.at( tmin >= 0 ? tmin : tmax, optionalTarget ); + } else if ( array instanceof Uint32Array ) { - }, + type = gl.UNSIGNED_INT; - intersectsBox: ( function () { + } else if ( array instanceof Int32Array ) { - var v = new Vector3(); + type = gl.INT; - return function intersectsBox( box ) { + } else if ( array instanceof Int8Array ) { - return this.intersectBox( box, v ) !== null; + type = gl.BYTE; + + } else if ( array instanceof Uint8Array ) { + + type = gl.UNSIGNED_BYTE; + + } + return { + buffer: buffer, + type: type, + bytesPerElement: array.BYTES_PER_ELEMENT, + version: attribute.version }; - } )(), + } - intersectTriangle: function () { + function updateBuffer( buffer, attribute, bufferType ) { - // Compute the offset origin, edges, and normal. - var diff = new Vector3(); - var edge1 = new Vector3(); - var edge2 = new Vector3(); - var normal = new Vector3(); + var array = attribute.array; + var updateRange = attribute.updateRange; - return function intersectTriangle( a, b, c, backfaceCulling, optionalTarget ) { + gl.bindBuffer( bufferType, buffer ); - // from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteIntrRay3Triangle3.h + if ( attribute.dynamic === false ) { - edge1.subVectors( b, a ); - edge2.subVectors( c, a ); - normal.crossVectors( edge1, edge2 ); + gl.bufferData( bufferType, array, gl.STATIC_DRAW ); - // 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; + } else if ( updateRange.count === - 1 ) { - if ( DdN > 0 ) { + // Not using update ranges - if ( backfaceCulling ) return null; - sign = 1; + gl.bufferSubData( bufferType, 0, array ); - } else if ( DdN < 0 ) { + } else if ( updateRange.count === 0 ) { - sign = - 1; - DdN = - DdN; + console.error( 'THREE.WebGLObjects.updateBuffer: dynamic THREE.BufferAttribute marked as needsUpdate but updateRange.count is 0, ensure you are using set methods or updating manually.' ); - } else { + } else { - return null; + gl.bufferSubData( bufferType, updateRange.offset * array.BYTES_PER_ELEMENT, + array.subarray( updateRange.offset, updateRange.offset + updateRange.count ) ); - } + updateRange.count = -1; // reset range - diff.subVectors( this.origin, a ); - var DdQxE2 = sign * this.direction.dot( edge2.crossVectors( diff, edge2 ) ); + } - // b1 < 0, no intersection - if ( DdQxE2 < 0 ) { + } - return null; + // - } + function get( attribute ) { - var DdE1xQ = sign * this.direction.dot( edge1.cross( diff ) ); + if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data; - // b2 < 0, no intersection - if ( DdE1xQ < 0 ) { + return buffers[ attribute.uuid ]; - return null; + } - } + function remove( attribute ) { - // b1+b2 > 1, no intersection - if ( DdQxE2 + DdE1xQ > DdN ) { + if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data; + + var data = buffers[ attribute.uuid ]; - return null; + if ( data ) { - } + gl.deleteBuffer( data.buffer ); - // Line intersects triangle, check if ray does. - var QdN = - sign * diff.dot( normal ); + delete buffers[ attribute.uuid ]; - // t < 0, no intersection - if ( QdN < 0 ) { + } - return null; + } - } + function update( attribute, bufferType ) { - // Ray intersects triangle. - return this.at( QdN / DdN, optionalTarget ); + if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data; - }; + var data = buffers[ attribute.uuid ]; - }(), + if ( data === undefined ) { - applyMatrix4: function ( matrix4 ) { + buffers[ attribute.uuid ] = createBuffer( attribute, bufferType ); - this.direction.add( this.origin ).applyMatrix4( matrix4 ); - this.origin.applyMatrix4( matrix4 ); - this.direction.sub( this.origin ); - this.direction.normalize(); + } else if ( data.version < attribute.version ) { - return this; + updateBuffer( data.buffer, attribute, bufferType ); - }, + data.version = attribute.version; - equals: function ( ray ) { + } - return ray.origin.equals( this.origin ) && ray.direction.equals( this.direction ); + } + + return { + + get: get, + remove: remove, + update: update - } + }; -} ); +} /** * @author mrdoob / http://mrdoob.com/ @@ -10673,8 +10523,19 @@ Object.assign( Object3D.prototype, EventDispatcher.prototype, { // This method does not support objects with rotated and/or translated parent(s) var m1 = new Matrix4(); + var vector = new Vector3(); - return function lookAt( vector ) { + return function lookAt( x, y, z ) { + + if ( x.isVector3 ) { + + vector.copy( x ); + + } else { + + vector.set( x, y, z ); + + } if ( this.isCamera ) { @@ -10698,3286 +10559,3852 @@ Object.assign( Object3D.prototype, EventDispatcher.prototype, { for ( var i = 0; i < arguments.length; i ++ ) { - this.add( arguments[ i ] ); + this.add( arguments[ i ] ); + + } + + return this; + + } + + if ( object === this ) { + + console.error( "THREE.Object3D.add: object can't be added as a child of itself.", object ); + return this; + + } + + if ( ( object && object.isObject3D ) ) { + + if ( object.parent !== null ) { + + object.parent.remove( object ); + + } + + object.parent = this; + object.dispatchEvent( { type: 'added' } ); + + this.children.push( object ); + + } else { + + console.error( "THREE.Object3D.add: object not an instance of THREE.Object3D.", object ); + + } + + return this; + + }, + + remove: function ( object ) { + + if ( arguments.length > 1 ) { + + for ( var i = 0; i < arguments.length; i ++ ) { + + this.remove( arguments[ i ] ); + + } + + return this; + + } + + var index = this.children.indexOf( object ); + + if ( index !== - 1 ) { + + object.parent = null; + + object.dispatchEvent( { type: 'removed' } ); + + this.children.splice( index, 1 ); + + } + + return this; + + }, + + getObjectById: function ( id ) { + + return this.getObjectByProperty( 'id', id ); + + }, + + getObjectByName: function ( name ) { + + return this.getObjectByProperty( 'name', name ); + + }, + + getObjectByProperty: function ( name, value ) { + + if ( this[ name ] === value ) return this; + + for ( var i = 0, l = this.children.length; i < l; i ++ ) { + + var child = this.children[ i ]; + var object = child.getObjectByProperty( name, value ); + + if ( object !== undefined ) { + + return object; + + } + + } + + return undefined; + + }, + + getWorldPosition: function ( optionalTarget ) { + + var result = optionalTarget || new Vector3(); + + this.updateMatrixWorld( true ); + + return result.setFromMatrixPosition( this.matrixWorld ); + + }, + + getWorldQuaternion: function () { + + var position = new Vector3(); + var scale = new Vector3(); + + return function getWorldQuaternion( optionalTarget ) { + + var result = optionalTarget || new Quaternion(); + + this.updateMatrixWorld( true ); + + this.matrixWorld.decompose( position, result, scale ); + + return result; + + }; + + }(), + + getWorldRotation: function () { + + var quaternion = new Quaternion(); + + return function getWorldRotation( optionalTarget ) { + + var result = optionalTarget || new Euler(); + + this.getWorldQuaternion( quaternion ); + + return result.setFromQuaternion( quaternion, this.rotation.order, false ); + + }; + + }(), + + getWorldScale: function () { + + var position = new Vector3(); + var quaternion = new Quaternion(); + + return function getWorldScale( optionalTarget ) { + + var result = optionalTarget || new Vector3(); + + this.updateMatrixWorld( true ); + + this.matrixWorld.decompose( position, quaternion, result ); + + return result; + + }; + + }(), + + getWorldDirection: function () { + + var quaternion = new Quaternion(); + + return function getWorldDirection( optionalTarget ) { + + var result = optionalTarget || new Vector3(); + + this.getWorldQuaternion( quaternion ); + + return result.set( 0, 0, 1 ).applyQuaternion( quaternion ); + + }; + + }(), + + raycast: function () {}, + + traverse: function ( callback ) { + + callback( this ); + + var children = this.children; + + for ( var i = 0, l = children.length; i < l; i ++ ) { + + children[ i ].traverse( callback ); + + } + + }, + + traverseVisible: function ( callback ) { + + if ( this.visible === false ) return; + + callback( this ); + + var children = this.children; + + for ( var i = 0, l = children.length; i < l; i ++ ) { + + children[ i ].traverseVisible( callback ); + + } + + }, + + traverseAncestors: function ( callback ) { + + var parent = this.parent; + + if ( parent !== null ) { + + callback( parent ); + + parent.traverseAncestors( callback ); + + } + + }, + + updateMatrix: function () { + + this.matrix.compose( this.position, this.quaternion, this.scale ); + + this.matrixWorldNeedsUpdate = true; + + }, + + updateMatrixWorld: function ( force ) { + + if ( this.matrixAutoUpdate ) this.updateMatrix(); + + if ( this.matrixWorldNeedsUpdate || force ) { + + if ( this.parent === null ) { + + this.matrixWorld.copy( this.matrix ); + + } else { + + this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix ); + + } + + this.matrixWorldNeedsUpdate = false; + + force = true; + + } + + // update children + + var children = this.children; + + for ( var i = 0, l = children.length; i < l; i ++ ) { + + children[ i ].updateMatrixWorld( force ); + + } + + }, + + toJSON: function ( meta ) { + + // meta is '' when called from JSON.stringify + var isRootObject = ( meta === undefined || meta === '' ); + + var output = {}; + + // meta is a hash used to collect geometries, materials. + // not providing it implies that this is the root object + // being serialized. + if ( isRootObject ) { + + // initialize meta obj + meta = { + geometries: {}, + materials: {}, + textures: {}, + images: {} + }; + + output.metadata = { + version: 4.5, + type: 'Object', + generator: 'Object3D.toJSON' + }; + + } + + // standard Object3D serialization + + var object = {}; + + object.uuid = this.uuid; + object.type = this.type; + + 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 ( JSON.stringify( this.userData ) !== '{}' ) object.userData = this.userData; + + object.matrix = this.matrix.toArray(); + + // + + function serialize( library, element ) { + + if ( library[ element.uuid ] === undefined ) { + + library[ element.uuid ] = element.toJSON( meta ); + + } + + return element.uuid; + + } + + if ( this.geometry !== undefined ) { + + object.geometry = serialize( meta.geometries, this.geometry ); + + } + + if ( this.material !== undefined ) { + + if ( Array.isArray( this.material ) ) { + + var uuids = []; + + for ( var i = 0, l = this.material.length; i < l; i ++ ) { + + uuids.push( serialize( meta.materials, this.material[ i ] ) ); + + } + + object.material = uuids; + + } else { + + object.material = serialize( meta.materials, this.material ); + + } + + } + + // + + if ( this.children.length > 0 ) { + + object.children = []; + + for ( var i = 0; i < this.children.length; i ++ ) { + + object.children.push( this.children[ i ].toJSON( meta ).object ); + + } + + } + + if ( isRootObject ) { + + var geometries = extractFromCache( meta.geometries ); + var materials = extractFromCache( meta.materials ); + var textures = extractFromCache( meta.textures ); + var images = extractFromCache( meta.images ); + + 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; + + } + + output.object = object; + + return output; + + // extract data from the cache hash + // remove metadata on each item + // and return as array + function extractFromCache( cache ) { + + var values = []; + for ( var key in cache ) { + + var data = cache[ key ]; + delete data.metadata; + values.push( data ); + + } + return values; + + } + + }, + + clone: function ( recursive ) { + + return new this.constructor().copy( this, recursive ); + + }, + + copy: function ( source, recursive ) { + + if ( recursive === undefined ) recursive = true; + + this.name = source.name; + + this.up.copy( source.up ); + + this.position.copy( source.position ); + 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.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; + + this.userData = JSON.parse( JSON.stringify( source.userData ) ); + + if ( recursive === true ) { + + for ( var i = 0; i < source.children.length; i ++ ) { + + var child = source.children[ i ]; + this.add( child.clone() ); + + } + + } + + return this; + + } + +} ); + +/** + * @author mrdoob / http://mrdoob.com/ + * @author mikael emtinger / http://gomo.se/ + * @author WestLangley / http://github.com/WestLangley +*/ + +function Camera() { + + Object3D.call( this ); + + this.type = 'Camera'; + + this.matrixWorldInverse = new Matrix4(); + this.projectionMatrix = new Matrix4(); + +} + +Camera.prototype = Object.assign( Object.create( Object3D.prototype ), { + + constructor: Camera, + + isCamera: true, + + copy: function ( source, recursive ) { + + Object3D.prototype.copy.call( this, source, recursive ); + + this.matrixWorldInverse.copy( source.matrixWorldInverse ); + this.projectionMatrix.copy( source.projectionMatrix ); + + return this; + + }, + + getWorldDirection: function () { + + var quaternion = new Quaternion(); + + return function getWorldDirection( optionalTarget ) { + + var result = optionalTarget || new Vector3(); - } + this.getWorldQuaternion( quaternion ); - return this; + return result.set( 0, 0, - 1 ).applyQuaternion( quaternion ); - } + }; - if ( object === this ) { + }(), - console.error( "THREE.Object3D.add: object can't be added as a child of itself.", object ); - return this; + updateMatrixWorld: function ( force ) { - } + Object3D.prototype.updateMatrixWorld.call( this, force ); - if ( ( object && object.isObject3D ) ) { + this.matrixWorldInverse.getInverse( this.matrixWorld ); - if ( object.parent !== null ) { + }, - object.parent.remove( object ); + clone: function () { - } + return new this.constructor().copy( this ); - object.parent = this; - object.dispatchEvent( { type: 'added' } ); + } - this.children.push( object ); +} ); - } else { +/** + * @author alteredq / http://alteredqualia.com/ + * @author arose / http://github.com/arose + */ - console.error( "THREE.Object3D.add: object not an instance of THREE.Object3D.", object ); +function OrthographicCamera( left, right, top, bottom, near, far ) { - } + Camera.call( this ); - return this; + this.type = 'OrthographicCamera'; - }, + this.zoom = 1; + this.view = null; - remove: function ( object ) { + this.left = left; + this.right = right; + this.top = top; + this.bottom = bottom; - if ( arguments.length > 1 ) { + this.near = ( near !== undefined ) ? near : 0.1; + this.far = ( far !== undefined ) ? far : 2000; - for ( var i = 0; i < arguments.length; i ++ ) { + this.updateProjectionMatrix(); - this.remove( arguments[ i ] ); +} - } +OrthographicCamera.prototype = Object.assign( Object.create( Camera.prototype ), { - } + constructor: OrthographicCamera, - var index = this.children.indexOf( object ); + isOrthographicCamera: true, - if ( index !== - 1 ) { + copy: function ( source, recursive ) { - object.parent = null; + Camera.prototype.copy.call( this, source, recursive ); - object.dispatchEvent( { type: 'removed' } ); + this.left = source.left; + this.right = source.right; + this.top = source.top; + this.bottom = source.bottom; + this.near = source.near; + this.far = source.far; - this.children.splice( index, 1 ); + this.zoom = source.zoom; + this.view = source.view === null ? null : Object.assign( {}, source.view ); - } + return this; }, - getObjectById: function ( id ) { + setViewOffset: function( fullWidth, fullHeight, x, y, width, height ) { - return this.getObjectByProperty( 'id', id ); + this.view = { + fullWidth: fullWidth, + fullHeight: fullHeight, + offsetX: x, + offsetY: y, + width: width, + height: height + }; + + this.updateProjectionMatrix(); }, - getObjectByName: function ( name ) { + clearViewOffset: function() { - return this.getObjectByProperty( 'name', name ); + this.view = null; + this.updateProjectionMatrix(); }, - getObjectByProperty: function ( name, value ) { - - if ( this[ name ] === value ) return this; + updateProjectionMatrix: function () { - for ( var i = 0, l = this.children.length; i < l; i ++ ) { + var dx = ( this.right - this.left ) / ( 2 * this.zoom ); + var dy = ( this.top - this.bottom ) / ( 2 * this.zoom ); + var cx = ( this.right + this.left ) / 2; + var cy = ( this.top + this.bottom ) / 2; - var child = this.children[ i ]; - var object = child.getObjectByProperty( name, value ); + var left = cx - dx; + var right = cx + dx; + var top = cy + dy; + var bottom = cy - dy; - if ( object !== undefined ) { + if ( this.view !== null ) { - return object; + var zoomW = this.zoom / ( this.view.width / this.view.fullWidth ); + var zoomH = this.zoom / ( this.view.height / this.view.fullHeight ); + var scaleW = ( this.right - this.left ) / this.view.width; + var scaleH = ( this.top - this.bottom ) / this.view.height; - } + left += scaleW * ( this.view.offsetX / zoomW ); + right = left + scaleW * ( this.view.width / zoomW ); + top -= scaleH * ( this.view.offsetY / zoomH ); + bottom = top - scaleH * ( this.view.height / zoomH ); } - return undefined; + this.projectionMatrix.makeOrthographic( left, right, top, bottom, this.near, this.far ); }, - getWorldPosition: function ( optionalTarget ) { - - var result = optionalTarget || new Vector3(); - - this.updateMatrixWorld( true ); + toJSON: function ( meta ) { - return result.setFromMatrixPosition( this.matrixWorld ); + var data = Object3D.prototype.toJSON.call( this, meta ); - }, + data.object.zoom = this.zoom; + data.object.left = this.left; + data.object.right = this.right; + data.object.top = this.top; + data.object.bottom = this.bottom; + data.object.near = this.near; + data.object.far = this.far; - getWorldQuaternion: function () { + if ( this.view !== null ) data.object.view = Object.assign( {}, this.view ); - var position = new Vector3(); - var scale = new Vector3(); + return data; - return function getWorldQuaternion( optionalTarget ) { + } - var result = optionalTarget || new Quaternion(); +} ); - this.updateMatrixWorld( true ); +/** + * @author mrdoob / http://mrdoob.com/ + * @author greggman / http://games.greggman.com/ + * @author zz85 / http://www.lab4games.net/zz85/blog + * @author tschw + */ - this.matrixWorld.decompose( position, result, scale ); +function PerspectiveCamera( fov, aspect, near, far ) { - return result; + Camera.call( this ); - }; + this.type = 'PerspectiveCamera'; - }(), + this.fov = fov !== undefined ? fov : 50; + this.zoom = 1; - getWorldRotation: function () { + this.near = near !== undefined ? near : 0.1; + this.far = far !== undefined ? far : 2000; + this.focus = 10; - var quaternion = new Quaternion(); + this.aspect = aspect !== undefined ? aspect : 1; + this.view = null; - return function getWorldRotation( optionalTarget ) { + this.filmGauge = 35; // width of the film (default in millimeters) + this.filmOffset = 0; // horizontal film offset (same unit as gauge) - var result = optionalTarget || new Euler(); + this.updateProjectionMatrix(); - this.getWorldQuaternion( quaternion ); +} - return result.setFromQuaternion( quaternion, this.rotation.order, false ); +PerspectiveCamera.prototype = Object.assign( Object.create( Camera.prototype ), { - }; + constructor: PerspectiveCamera, - }(), + isPerspectiveCamera: true, - getWorldScale: function () { + copy: function ( source, recursive ) { - var position = new Vector3(); - var quaternion = new Quaternion(); + Camera.prototype.copy.call( this, source, recursive ); - return function getWorldScale( optionalTarget ) { + this.fov = source.fov; + this.zoom = source.zoom; - var result = optionalTarget || new Vector3(); + this.near = source.near; + this.far = source.far; + this.focus = source.focus; - this.updateMatrixWorld( true ); + this.aspect = source.aspect; + this.view = source.view === null ? null : Object.assign( {}, source.view ); - this.matrixWorld.decompose( position, quaternion, result ); + this.filmGauge = source.filmGauge; + this.filmOffset = source.filmOffset; - return result; + return this; - }; + }, - }(), + /** + * 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 ) { - getWorldDirection: function () { + // see http://www.bobatkins.com/photography/technical/field_of_view.html + var vExtentSlope = 0.5 * this.getFilmHeight() / focalLength; - var quaternion = new Quaternion(); + this.fov = _Math.RAD2DEG * 2 * Math.atan( vExtentSlope ); + this.updateProjectionMatrix(); - return function getWorldDirection( optionalTarget ) { + }, - var result = optionalTarget || new Vector3(); + /** + * Calculates the focal length from the current .fov and .filmGauge. + */ + getFocalLength: function () { - this.getWorldQuaternion( quaternion ); + var vExtentSlope = Math.tan( _Math.DEG2RAD * 0.5 * this.fov ); - return result.set( 0, 0, 1 ).applyQuaternion( quaternion ); + return 0.5 * this.getFilmHeight() / vExtentSlope; - }; + }, - }(), + getEffectiveFOV: function () { - raycast: function () {}, + return _Math.RAD2DEG * 2 * Math.atan( + Math.tan( _Math.DEG2RAD * 0.5 * this.fov ) / this.zoom ); - traverse: function ( callback ) { + }, - callback( this ); + getFilmWidth: function () { - var children = this.children; + // film not completely covered in portrait format (aspect < 1) + return this.filmGauge * Math.min( this.aspect, 1 ); - for ( var i = 0, l = children.length; i < l; i ++ ) { + }, - children[ i ].traverse( callback ); + getFilmHeight: function () { - } + // film not completely covered in landscape format (aspect > 1) + return this.filmGauge / Math.max( this.aspect, 1 ); }, - traverseVisible: function ( callback ) { + /** + * 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.setOffset( fullWidth, fullHeight, w * 0, h * 0, w, h ); + * --B-- + * camera.setOffset( fullWidth, fullHeight, w * 1, h * 0, w, h ); + * --C-- + * camera.setOffset( fullWidth, fullHeight, w * 2, h * 0, w, h ); + * --D-- + * camera.setOffset( fullWidth, fullHeight, w * 0, h * 1, w, h ); + * --E-- + * camera.setOffset( fullWidth, fullHeight, w * 1, h * 1, w, h ); + * --F-- + * camera.setOffset( 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 ) { - if ( this.visible === false ) return; + this.aspect = fullWidth / fullHeight; - callback( this ); + this.view = { + fullWidth: fullWidth, + fullHeight: fullHeight, + offsetX: x, + offsetY: y, + width: width, + height: height + }; - var children = this.children; + this.updateProjectionMatrix(); - for ( var i = 0, l = children.length; i < l; i ++ ) { + }, - children[ i ].traverseVisible( callback ); + clearViewOffset: function () { - } + this.view = null; + this.updateProjectionMatrix(); }, - traverseAncestors: function ( callback ) { + updateProjectionMatrix: function () { - var parent = this.parent; + 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; - if ( parent !== null ) { + if ( view !== null ) { - callback( parent ); + var fullWidth = view.fullWidth, + fullHeight = view.fullHeight; - parent.traverseAncestors( callback ); + left += view.offsetX * width / fullWidth; + top -= view.offsetY * height / fullHeight; + width *= view.width / fullWidth; + height *= view.height / fullHeight; } + var skew = this.filmOffset; + if ( skew !== 0 ) left += near * skew / this.getFilmWidth(); + + this.projectionMatrix.makePerspective( left, left + width, top, top - height, near, this.far ); + }, - updateMatrix: function () { + toJSON: function ( meta ) { - this.matrix.compose( this.position, this.quaternion, this.scale ); + var data = Object3D.prototype.toJSON.call( this, meta ); - this.matrixWorldNeedsUpdate = true; + data.object.fov = this.fov; + data.object.zoom = this.zoom; - }, + data.object.near = this.near; + data.object.far = this.far; + data.object.focus = this.focus; - updateMatrixWorld: function ( force ) { + data.object.aspect = this.aspect; - if ( this.matrixAutoUpdate ) this.updateMatrix(); + if ( this.view !== null ) data.object.view = Object.assign( {}, this.view ); - if ( this.matrixWorldNeedsUpdate || force ) { + data.object.filmGauge = this.filmGauge; + data.object.filmOffset = this.filmOffset; - if ( this.parent === null ) { + return data; - this.matrixWorld.copy( this.matrix ); + } - } else { +} ); - this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix ); +/** + * @author mrdoob / http://mrdoob.com/ + * @author alteredq / http://alteredqualia.com/ + */ - } +function Face3( a, b, c, normal, color, materialIndex ) { - this.matrixWorldNeedsUpdate = false; + this.a = a; + this.b = b; + this.c = c; - force = true; + 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 : []; - // update children + this.materialIndex = materialIndex !== undefined ? materialIndex : 0; - var children = this.children; +} - for ( var i = 0, l = children.length; i < l; i ++ ) { +Object.assign( Face3.prototype, { - children[ i ].updateMatrixWorld( force ); + clone: function () { - } + return new this.constructor().copy( this ); }, - toJSON: function ( meta ) { + copy: function ( source ) { - // meta is '' when called from JSON.stringify - var isRootObject = ( meta === undefined || meta === '' ); + this.a = source.a; + this.b = source.b; + this.c = source.c; - var output = {}; + this.normal.copy( source.normal ); + this.color.copy( source.color ); - // meta is a hash used to collect geometries, materials. - // not providing it implies that this is the root object - // being serialized. - if ( isRootObject ) { + this.materialIndex = source.materialIndex; - // initialize meta obj - meta = { - geometries: {}, - materials: {}, - textures: {}, - images: {} - }; + for ( var i = 0, il = source.vertexNormals.length; i < il; i ++ ) { - output.metadata = { - version: 4.5, - type: 'Object', - generator: 'Object3D.toJSON' - }; + this.vertexNormals[ i ] = source.vertexNormals[ i ].clone(); } - // standard Object3D serialization + for ( var i = 0, il = source.vertexColors.length; i < il; i ++ ) { - var object = {}; + this.vertexColors[ i ] = source.vertexColors[ i ].clone(); - object.uuid = this.uuid; - object.type = this.type; + } - if ( this.name !== '' ) object.name = this.name; - if ( JSON.stringify( this.userData ) !== '{}' ) object.userData = this.userData; - if ( this.castShadow === true ) object.castShadow = true; - if ( this.receiveShadow === true ) object.receiveShadow = true; - if ( this.visible === false ) object.visible = false; + return this; - object.matrix = this.matrix.toArray(); + } - // +} ); - function serialize( library, element ) { +/** + * @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 + */ - if ( library[ element.uuid ] === undefined ) { +var count = 0; +function GeometryIdCount() { return count++; } - library[ element.uuid ] = element.toJSON( meta ); +function Geometry() { - } + Object.defineProperty( this, 'id', { value: GeometryIdCount() } ); - return element.uuid; + this.uuid = _Math.generateUUID(); - } + this.name = ''; + this.type = 'Geometry'; - if ( this.geometry !== undefined ) { + this.vertices = []; + this.colors = []; + this.faces = []; + this.faceVertexUvs = [[]]; - object.geometry = serialize( meta.geometries, this.geometry ); + this.morphTargets = []; + this.morphNormals = []; - } + this.skinWeights = []; + this.skinIndices = []; - if ( this.material !== undefined ) { + this.lineDistances = []; - if ( Array.isArray( this.material ) ) { + this.boundingBox = null; + this.boundingSphere = null; - var uuids = []; + // update flags - for ( var i = 0, l = this.material.length; i < l; i ++ ) { + this.elementsNeedUpdate = false; + this.verticesNeedUpdate = false; + this.uvsNeedUpdate = false; + this.normalsNeedUpdate = false; + this.colorsNeedUpdate = false; + this.lineDistancesNeedUpdate = false; + this.groupsNeedUpdate = false; - uuids.push( serialize( meta.materials, this.material[ i ] ) ); +} - } +Object.assign( Geometry.prototype, EventDispatcher.prototype, { - object.material = uuids; + isGeometry: true, - } else { + applyMatrix: function ( matrix ) { - object.material = serialize( meta.materials, this.material ); + var normalMatrix = new Matrix3().getNormalMatrix( matrix ); - } + for ( var i = 0, il = this.vertices.length; i < il; i ++ ) { + + var vertex = this.vertices[ i ]; + vertex.applyMatrix4( matrix ); } - // + for ( var i = 0, il = this.faces.length; i < il; i ++ ) { - if ( this.children.length > 0 ) { + var face = this.faces[ i ]; + face.normal.applyMatrix3( normalMatrix ).normalize(); - object.children = []; + for ( var j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) { - for ( var i = 0; i < this.children.length; i ++ ) { + face.vertexNormals[ j ].applyMatrix3( normalMatrix ).normalize(); - object.children.push( this.children[ i ].toJSON( meta ).object ); + } + + } + + if ( this.boundingBox !== null ) { + + this.computeBoundingBox(); + + } + + if ( this.boundingSphere !== null ) { - } + this.computeBoundingSphere(); } - if ( isRootObject ) { + this.verticesNeedUpdate = true; + this.normalsNeedUpdate = true; - var geometries = extractFromCache( meta.geometries ); - var materials = extractFromCache( meta.materials ); - var textures = extractFromCache( meta.textures ); - var images = extractFromCache( meta.images ); + return this; - 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; + }, - } + rotateX: function () { - output.object = object; + // rotate geometry around world x-axis - return output; + var m1 = new Matrix4(); - // extract data from the cache hash - // remove metadata on each item - // and return as array - function extractFromCache( cache ) { + return function rotateX( angle ) { - var values = []; - for ( var key in cache ) { + m1.makeRotationX( angle ); - var data = cache[ key ]; - delete data.metadata; - values.push( data ); + this.applyMatrix( m1 ); - } - return values; + return this; - } + }; - }, + }(), - clone: function ( recursive ) { + rotateY: function () { - return new this.constructor().copy( this, recursive ); + // rotate geometry around world y-axis - }, + var m1 = new Matrix4(); - copy: function ( source, recursive ) { + return function rotateY( angle ) { - if ( recursive === undefined ) recursive = true; + m1.makeRotationY( angle ); - this.name = source.name; + this.applyMatrix( m1 ); - this.up.copy( source.up ); + return this; - this.position.copy( source.position ); - 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; + rotateZ: function () { - this.layers.mask = source.layers.mask; - this.visible = source.visible; + // rotate geometry around world z-axis - this.castShadow = source.castShadow; - this.receiveShadow = source.receiveShadow; + var m1 = new Matrix4(); - this.frustumCulled = source.frustumCulled; - this.renderOrder = source.renderOrder; + return function rotateZ( angle ) { - this.userData = JSON.parse( JSON.stringify( source.userData ) ); + m1.makeRotationZ( angle ); - if ( recursive === true ) { + this.applyMatrix( m1 ); - for ( var i = 0; i < source.children.length; i ++ ) { + return this; - var child = source.children[ i ]; - this.add( child.clone() ); + }; - } + }(), - } + translate: function () { - return this; + // translate geometry - } + var m1 = new Matrix4(); -} ); + return function translate( x, y, z ) { -/** - * @author bhouston / http://clara.io - */ + m1.makeTranslation( x, y, z ); -function Line3( start, end ) { + this.applyMatrix( m1 ); - this.start = ( start !== undefined ) ? start : new Vector3(); - this.end = ( end !== undefined ) ? end : new Vector3(); + return this; -} + }; -Object.assign( Line3.prototype, { + }(), - set: function ( start, end ) { + scale: function () { - this.start.copy( start ); - this.end.copy( end ); + // scale geometry - return this; + var m1 = new Matrix4(); - }, + return function scale( x, y, z ) { - clone: function () { + m1.makeScale( x, y, z ); - return new this.constructor().copy( this ); + this.applyMatrix( m1 ); - }, + return this; - copy: function ( line ) { + }; - this.start.copy( line.start ); - this.end.copy( line.end ); + }(), - return this; + lookAt: function () { - }, + var obj = new Object3D(); - getCenter: function ( optionalTarget ) { + return function lookAt( vector ) { - var result = optionalTarget || new Vector3(); - return result.addVectors( this.start, this.end ).multiplyScalar( 0.5 ); + obj.lookAt( vector ); - }, + obj.updateMatrix(); - delta: function ( optionalTarget ) { + this.applyMatrix( obj.matrix ); - var result = optionalTarget || new Vector3(); - return result.subVectors( this.end, this.start ); + }; - }, + }(), - distanceSq: function () { + fromBufferGeometry: function ( geometry ) { - return this.start.distanceToSquared( this.end ); + var scope = this; - }, + var indices = geometry.index !== null ? geometry.index.array : undefined; + var attributes = geometry.attributes; - distance: function () { + 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; - return this.start.distanceTo( this.end ); + if ( uvs2 !== undefined ) this.faceVertexUvs[ 1 ] = []; - }, + var tempNormals = []; + var tempUVs = []; + var tempUVs2 = []; - at: function ( t, optionalTarget ) { + for ( var i = 0, j = 0; i < positions.length; i += 3, j += 2 ) { - var result = optionalTarget || new Vector3(); + scope.vertices.push( new Vector3( positions[ i ], positions[ i + 1 ], positions[ i + 2 ] ) ); - return this.delta( result ).multiplyScalar( t ).add( this.start ); + if ( normals !== undefined ) { - }, + tempNormals.push( new Vector3( normals[ i ], normals[ i + 1 ], normals[ i + 2 ] ) ); - closestPointToPointParameter: function () { + } - var startP = new Vector3(); - var startEnd = new Vector3(); + if ( colors !== undefined ) { - return function closestPointToPointParameter( point, clampToLine ) { + scope.colors.push( new Color( colors[ i ], colors[ i + 1 ], colors[ i + 2 ] ) ); - startP.subVectors( point, this.start ); - startEnd.subVectors( this.end, this.start ); + } - var startEnd2 = startEnd.dot( startEnd ); - var startEnd_startP = startEnd.dot( startP ); + if ( uvs !== undefined ) { - var t = startEnd_startP / startEnd2; + tempUVs.push( new Vector2( uvs[ j ], uvs[ j + 1 ] ) ); - if ( clampToLine ) { + } - t = _Math.clamp( t, 0, 1 ); + if ( uvs2 !== undefined ) { + + tempUVs2.push( new Vector2( uvs2[ j ], uvs2[ j + 1 ] ) ); } - return t; + } - }; + function addFace( a, b, c, materialIndex ) { - }(), + var vertexNormals = normals !== undefined ? [ tempNormals[ a ].clone(), tempNormals[ b ].clone(), tempNormals[ c ].clone() ] : []; + var vertexColors = colors !== undefined ? [ scope.colors[ a ].clone(), scope.colors[ b ].clone(), scope.colors[ c ].clone() ] : []; - closestPointToPoint: function ( point, clampToLine, optionalTarget ) { + var face = new Face3( a, b, c, vertexNormals, vertexColors, materialIndex ); - var t = this.closestPointToPointParameter( point, clampToLine ); + scope.faces.push( face ); - var result = optionalTarget || new Vector3(); + if ( uvs !== undefined ) { - return this.delta( result ).multiplyScalar( t ).add( this.start ); + scope.faceVertexUvs[ 0 ].push( [ tempUVs[ a ].clone(), tempUVs[ b ].clone(), tempUVs[ c ].clone() ] ); - }, + } - applyMatrix4: function ( matrix ) { + if ( uvs2 !== undefined ) { - this.start.applyMatrix4( matrix ); - this.end.applyMatrix4( matrix ); + scope.faceVertexUvs[ 1 ].push( [ tempUVs2[ a ].clone(), tempUVs2[ b ].clone(), tempUVs2[ c ].clone() ] ); - return this; + } - }, + } - equals: function ( line ) { + var groups = geometry.groups; - return line.start.equals( this.start ) && line.end.equals( this.end ); + if ( groups.length > 0 ) { - } + for ( var i = 0; i < groups.length; i ++ ) { -} ); + var group = groups[ i ]; -/** - * @author bhouston / http://clara.io - * @author mrdoob / http://mrdoob.com/ - */ + var start = group.start; + var count = group.count; -function Triangle( a, b, c ) { + for ( var j = start, jl = start + count; j < jl; j += 3 ) { - this.a = ( a !== undefined ) ? a : new Vector3(); - this.b = ( b !== undefined ) ? b : new Vector3(); - this.c = ( c !== undefined ) ? c : new Vector3(); + if ( indices !== undefined ) { -} + addFace( indices[ j ], indices[ j + 1 ], indices[ j + 2 ], group.materialIndex ); -Object.assign( Triangle, { + } else { - normal: function () { + addFace( j, j + 1, j + 2, group.materialIndex ); - var v0 = new Vector3(); + } - return function normal( a, b, c, optionalTarget ) { + } - var result = optionalTarget || new Vector3(); + } - result.subVectors( c, b ); - v0.subVectors( a, b ); - result.cross( v0 ); + } else { - var resultLengthSq = result.lengthSq(); - if ( resultLengthSq > 0 ) { + if ( indices !== undefined ) { - return result.multiplyScalar( 1 / Math.sqrt( resultLengthSq ) ); + for ( var i = 0; i < indices.length; i += 3 ) { - } + addFace( indices[ i ], indices[ i + 1 ], indices[ i + 2 ] ); - return result.set( 0, 0, 0 ); + } - }; + } else { - }(), + for ( var i = 0; i < positions.length / 3; i += 3 ) { - // static/instance method to calculate barycentric coordinates - // based on: http://www.blackpawn.com/texts/pointinpoly/default.html - barycoordFromPoint: function () { + addFace( i, i + 1, i + 2 ); - var v0 = new Vector3(); - var v1 = new Vector3(); - var v2 = new Vector3(); + } - return function barycoordFromPoint( point, a, b, c, optionalTarget ) { + } - v0.subVectors( c, a ); - v1.subVectors( b, a ); - v2.subVectors( point, a ); + } - var dot00 = v0.dot( v0 ); - var dot01 = v0.dot( v1 ); - var dot02 = v0.dot( v2 ); - var dot11 = v1.dot( v1 ); - var dot12 = v1.dot( v2 ); + this.computeFaceNormals(); - var denom = ( dot00 * dot11 - dot01 * dot01 ); + if ( geometry.boundingBox !== null ) { - var result = optionalTarget || new Vector3(); + this.boundingBox = geometry.boundingBox.clone(); - // 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 result.set( - 2, - 1, - 1 ); + if ( geometry.boundingSphere !== null ) { - } + this.boundingSphere = geometry.boundingSphere.clone(); - var invDenom = 1 / denom; - var u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom; - var v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom; + } - // barycentric coordinates must always sum to 1 - return result.set( 1 - u - v, v, u ); + return this; - }; + }, - }(), + center: function () { - containsPoint: function () { + this.computeBoundingBox(); - var v1 = new Vector3(); + var offset = this.boundingBox.getCenter().negate(); - return function containsPoint( point, a, b, c ) { + this.translate( offset.x, offset.y, offset.z ); - var result = Triangle.barycoordFromPoint( point, a, b, c, v1 ); + return offset; - return ( result.x >= 0 ) && ( result.y >= 0 ) && ( ( result.x + result.y ) <= 1 ); + }, - }; + normalize: function () { - }() + this.computeBoundingSphere(); -} ); + var center = this.boundingSphere.center; + var radius = this.boundingSphere.radius; -Object.assign( Triangle.prototype, { + var s = radius === 0 ? 1 : 1.0 / radius; - set: function ( a, b, c ) { + var matrix = new Matrix4(); + matrix.set( + s, 0, 0, - s * center.x, + 0, s, 0, - s * center.y, + 0, 0, s, - s * center.z, + 0, 0, 0, 1 + ); - this.a.copy( a ); - this.b.copy( b ); - this.c.copy( c ); + this.applyMatrix( matrix ); return this; }, - setFromPointsAndIndices: function ( points, i0, i1, i2 ) { + computeFaceNormals: function () { - this.a.copy( points[ i0 ] ); - this.b.copy( points[ i1 ] ); - this.c.copy( points[ i2 ] ); + var cb = new Vector3(), ab = new Vector3(); - return this; + for ( var f = 0, fl = this.faces.length; f < fl; f ++ ) { - }, + var face = this.faces[ f ]; - clone: function () { + var vA = this.vertices[ face.a ]; + var vB = this.vertices[ face.b ]; + var vC = this.vertices[ face.c ]; - return new this.constructor().copy( this ); + cb.subVectors( vC, vB ); + ab.subVectors( vA, vB ); + cb.cross( ab ); + + cb.normalize(); + + face.normal.copy( cb ); + + } }, - copy: function ( triangle ) { + computeVertexNormals: function ( areaWeighted ) { - this.a.copy( triangle.a ); - this.b.copy( triangle.b ); - this.c.copy( triangle.c ); + if ( areaWeighted === undefined ) areaWeighted = true; - return this; + var v, vl, f, fl, face, vertices; - }, + vertices = new Array( this.vertices.length ); - area: function () { + for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) { - var v0 = new Vector3(); - var v1 = new Vector3(); + vertices[ v ] = new Vector3(); - return function area() { + } - v0.subVectors( this.c, this.b ); - v1.subVectors( this.a, this.b ); + if ( areaWeighted ) { - return v0.cross( v1 ).length() * 0.5; + // 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 ++ ) { - midpoint: function ( optionalTarget ) { + face = this.faces[ f ]; - var result = optionalTarget || new Vector3(); - return result.addVectors( this.a, this.b ).add( this.c ).multiplyScalar( 1 / 3 ); + vA = this.vertices[ face.a ]; + vB = this.vertices[ face.b ]; + vC = this.vertices[ face.c ]; - }, + cb.subVectors( vC, vB ); + ab.subVectors( vA, vB ); + cb.cross( ab ); - normal: function ( optionalTarget ) { + vertices[ face.a ].add( cb ); + vertices[ face.b ].add( cb ); + vertices[ face.c ].add( cb ); - return Triangle.normal( this.a, this.b, this.c, optionalTarget ); + } - }, + } else { - plane: function ( optionalTarget ) { + this.computeFaceNormals(); - var result = optionalTarget || new Plane(); + for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { - return result.setFromCoplanarPoints( this.a, this.b, this.c ); + face = this.faces[ f ]; - }, + vertices[ face.a ].add( face.normal ); + vertices[ face.b ].add( face.normal ); + vertices[ face.c ].add( face.normal ); - barycoordFromPoint: function ( point, optionalTarget ) { + } - return Triangle.barycoordFromPoint( point, this.a, this.b, this.c, optionalTarget ); + } - }, + for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) { - containsPoint: function ( point ) { + vertices[ v ].normalize(); - return Triangle.containsPoint( point, this.a, this.b, this.c ); + } - }, + for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { - closestPointToPoint: function () { + face = this.faces[ f ]; - var plane = new Plane(); - var edgeList = [ new Line3(), new Line3(), new Line3() ]; - var projectedPoint = new Vector3(); - var closestPoint = new Vector3(); + var vertexNormals = face.vertexNormals; - return function closestPointToPoint( point, optionalTarget ) { + if ( vertexNormals.length === 3 ) { - var result = optionalTarget || new Vector3(); - var minDistance = Infinity; + vertexNormals[ 0 ].copy( vertices[ face.a ] ); + vertexNormals[ 1 ].copy( vertices[ face.b ] ); + vertexNormals[ 2 ].copy( vertices[ face.c ] ); - // project the point onto the plane of the triangle + } else { - plane.setFromCoplanarPoints( this.a, this.b, this.c ); - plane.projectPoint( point, projectedPoint ); + vertexNormals[ 0 ] = vertices[ face.a ].clone(); + vertexNormals[ 1 ] = vertices[ face.b ].clone(); + vertexNormals[ 2 ] = vertices[ face.c ].clone(); - // check if the projection lies within the triangle + } - if( this.containsPoint( projectedPoint ) === true ) { + } - // if so, this is the closest point + if ( this.faces.length > 0 ) { - result.copy( projectedPoint ); + this.normalsNeedUpdate = true; - } else { + } - // if not, the point falls outside the triangle. the result is the closest point to the triangle's edges or vertices + }, - edgeList[ 0 ].set( this.a, this.b ); - edgeList[ 1 ].set( this.b, this.c ); - edgeList[ 2 ].set( this.c, this.a ); + computeFlatVertexNormals: function () { - for( var i = 0; i < edgeList.length; i ++ ) { + var f, fl, face; - edgeList[ i ].closestPointToPoint( projectedPoint, true, closestPoint ); + this.computeFaceNormals(); - var distance = projectedPoint.distanceToSquared( closestPoint ); + for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { - if( distance < minDistance ) { + face = this.faces[ f ]; - minDistance = distance; + var vertexNormals = face.vertexNormals; - result.copy( closestPoint ); + if ( vertexNormals.length === 3 ) { - } + vertexNormals[ 0 ].copy( face.normal ); + vertexNormals[ 1 ].copy( face.normal ); + vertexNormals[ 2 ].copy( face.normal ); - } + } else { + + vertexNormals[ 0 ] = face.normal.clone(); + vertexNormals[ 1 ] = face.normal.clone(); + vertexNormals[ 2 ] = face.normal.clone(); } - return result; + } - }; + if ( this.faces.length > 0 ) { - }(), + this.normalsNeedUpdate = true; - equals: function ( triangle ) { + } - return triangle.a.equals( this.a ) && triangle.b.equals( this.b ) && triangle.c.equals( this.c ); + }, - } + computeMorphNormals: function () { + + var i, il, f, fl, face; + + // save original normals + // - create temp variables on first access + // otherwise just copy (for faster repeated calls) + + for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { -} ); + face = this.faces[ f ]; -/** - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - */ + if ( ! face.__originalFaceNormal ) { -function Face3( a, b, c, normal, color, materialIndex ) { + face.__originalFaceNormal = face.normal.clone(); - this.a = a; - this.b = b; - this.c = c; + } else { - this.normal = ( normal && normal.isVector3 ) ? normal : new Vector3(); - this.vertexNormals = Array.isArray( normal ) ? normal : []; + face.__originalFaceNormal.copy( face.normal ); - this.color = ( color && color.isColor ) ? color : new Color(); - this.vertexColors = Array.isArray( color ) ? color : []; + } - this.materialIndex = materialIndex !== undefined ? materialIndex : 0; + if ( ! face.__originalVertexNormals ) face.__originalVertexNormals = []; -} + for ( i = 0, il = face.vertexNormals.length; i < il; i ++ ) { -Object.assign( Face3.prototype, { + if ( ! face.__originalVertexNormals[ i ] ) { - clone: function () { + face.__originalVertexNormals[ i ] = face.vertexNormals[ i ].clone(); - return new this.constructor().copy( this ); + } else { - }, + face.__originalVertexNormals[ i ].copy( face.vertexNormals[ i ] ); - copy: function ( source ) { + } - this.a = source.a; - this.b = source.b; - this.c = source.c; + } - this.normal.copy( source.normal ); - this.color.copy( source.color ); + } - this.materialIndex = source.materialIndex; + // use temp geometry to compute face and vertex normals for each morph - for ( var i = 0, il = source.vertexNormals.length; i < il; i ++ ) { + var tmpGeo = new Geometry(); + tmpGeo.faces = this.faces; - this.vertexNormals[ i ] = source.vertexNormals[ i ].clone(); + for ( i = 0, il = this.morphTargets.length; i < il; i ++ ) { - } + // create on first access - for ( var i = 0, il = source.vertexColors.length; i < il; i ++ ) { + if ( ! this.morphNormals[ i ] ) { - this.vertexColors[ i ] = source.vertexColors[ i ].clone(); + this.morphNormals[ i ] = {}; + this.morphNormals[ i ].faceNormals = []; + this.morphNormals[ i ].vertexNormals = []; - } + var dstNormalsFace = this.morphNormals[ i ].faceNormals; + var dstNormalsVertex = this.morphNormals[ i ].vertexNormals; - return this; + var faceNormal, vertexNormals; - } + for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { -} ); + faceNormal = new Vector3(); + vertexNormals = { a: new Vector3(), b: new Vector3(), c: new Vector3() }; -/** - * @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.TextureCube( [posx, negx, posy, negy, posz, negz] ), - * combine: THREE.Multiply, - * reflectivity: , - * refractionRatio: , - * - * shading: THREE.SmoothShading, - * depthTest: , - * depthWrite: , - * - * wireframe: , - * wireframeLinewidth: , - * - * skinning: , - * morphTargets: - * } - */ + dstNormalsFace.push( faceNormal ); + dstNormalsVertex.push( vertexNormals ); -function MeshBasicMaterial( parameters ) { + } - Material.call( this ); + } - this.type = 'MeshBasicMaterial'; + var morphNormals = this.morphNormals[ i ]; - this.color = new Color( 0xffffff ); // emissive + // set vertices to morph target - this.map = null; + tmpGeo.vertices = this.morphTargets[ i ].vertices; - this.lightMap = null; - this.lightMapIntensity = 1.0; + // compute morph normals - this.aoMap = null; - this.aoMapIntensity = 1.0; + tmpGeo.computeFaceNormals(); + tmpGeo.computeVertexNormals(); - this.specularMap = null; + // store morph normals - this.alphaMap = null; + var faceNormal, vertexNormals; - this.envMap = null; - this.combine = MultiplyOperation; - this.reflectivity = 1; - this.refractionRatio = 0.98; + for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { - this.wireframe = false; - this.wireframeLinewidth = 1; - this.wireframeLinecap = 'round'; - this.wireframeLinejoin = 'round'; + face = this.faces[ f ]; - this.skinning = false; - this.morphTargets = false; + faceNormal = morphNormals.faceNormals[ f ]; + vertexNormals = morphNormals.vertexNormals[ f ]; - this.lights = false; + faceNormal.copy( face.normal ); - this.setValues( parameters ); + vertexNormals.a.copy( face.vertexNormals[ 0 ] ); + vertexNormals.b.copy( face.vertexNormals[ 1 ] ); + vertexNormals.c.copy( face.vertexNormals[ 2 ] ); -} + } -MeshBasicMaterial.prototype = Object.create( Material.prototype ); -MeshBasicMaterial.prototype.constructor = MeshBasicMaterial; + } -MeshBasicMaterial.prototype.isMeshBasicMaterial = true; + // restore original normals -MeshBasicMaterial.prototype.copy = function ( source ) { + for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { - Material.prototype.copy.call( this, source ); + face = this.faces[ f ]; - this.color.copy( source.color ); + face.normal = face.__originalFaceNormal; + face.vertexNormals = face.__originalVertexNormals; - this.map = source.map; + } - this.lightMap = source.lightMap; - this.lightMapIntensity = source.lightMapIntensity; + }, - this.aoMap = source.aoMap; - this.aoMapIntensity = source.aoMapIntensity; + computeLineDistances: function () { - this.specularMap = source.specularMap; + var d = 0; + var vertices = this.vertices; - this.alphaMap = source.alphaMap; + for ( var i = 0, il = vertices.length; i < il; i ++ ) { - this.envMap = source.envMap; - this.combine = source.combine; - this.reflectivity = source.reflectivity; - this.refractionRatio = source.refractionRatio; + if ( i > 0 ) { - this.wireframe = source.wireframe; - this.wireframeLinewidth = source.wireframeLinewidth; - this.wireframeLinecap = source.wireframeLinecap; - this.wireframeLinejoin = source.wireframeLinejoin; + d += vertices[ i ].distanceTo( vertices[ i - 1 ] ); - this.skinning = source.skinning; - this.morphTargets = source.morphTargets; + } - return this; + this.lineDistances[ i ] = d; -}; + } -/** - * @author mrdoob / http://mrdoob.com/ - */ + }, -function BufferAttribute( array, itemSize, normalized ) { + computeBoundingBox: function () { - if ( Array.isArray( array ) ) { + if ( this.boundingBox === null ) { - throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' ); + this.boundingBox = new Box3(); - } + } - this.uuid = _Math.generateUUID(); - this.name = ''; + this.boundingBox.setFromPoints( this.vertices ); - 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 }; + computeBoundingSphere: function () { - this.onUploadCallback = function () {}; + if ( this.boundingSphere === null ) { - this.version = 0; + this.boundingSphere = new Sphere(); -} + } -Object.defineProperty( BufferAttribute.prototype, 'needsUpdate', { + this.boundingSphere.setFromPoints( this.vertices ); - set: function ( value ) { + }, - if ( value === true ) this.version ++; + merge: function ( geometry, matrix, materialIndexOffset ) { - } + if ( ! ( geometry && geometry.isGeometry ) ) { -} ); + console.error( 'THREE.Geometry.merge(): geometry not an instance of THREE.Geometry.', geometry ); + return; -Object.assign( BufferAttribute.prototype, { + } - isBufferAttribute: true, + var normalMatrix, + vertexOffset = this.vertices.length, + vertices1 = this.vertices, + vertices2 = geometry.vertices, + faces1 = this.faces, + faces2 = geometry.faces, + uvs1 = this.faceVertexUvs[ 0 ], + uvs2 = geometry.faceVertexUvs[ 0 ], + colors1 = this.colors, + colors2 = geometry.colors; - setArray: function ( array ) { + if ( materialIndexOffset === undefined ) materialIndexOffset = 0; - if ( Array.isArray( array ) ) { + if ( matrix !== undefined ) { - throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' ); + normalMatrix = new Matrix3().getNormalMatrix( matrix ); } - this.count = array !== undefined ? array.length / this.itemSize : 0; - this.array = array; + // vertices - }, + for ( var i = 0, il = vertices2.length; i < il; i ++ ) { - setDynamic: function ( value ) { + var vertex = vertices2[ i ]; - this.dynamic = value; + var vertexCopy = vertex.clone(); - return this; + if ( matrix !== undefined ) vertexCopy.applyMatrix4( matrix ); - }, + vertices1.push( vertexCopy ); - copy: function ( source ) { + } - this.array = new source.array.constructor( source.array ); - this.itemSize = source.itemSize; - this.count = source.count; - this.normalized = source.normalized; + // colors - this.dynamic = source.dynamic; + for ( var i = 0, il = colors2.length; i < il; i ++ ) { - return this; + colors1.push( colors2[ i ].clone() ); - }, + } - copyAt: function ( index1, attribute, index2 ) { + // faces - index1 *= this.itemSize; - index2 *= attribute.itemSize; + for ( i = 0, il = faces2.length; i < il; i ++ ) { - for ( var i = 0, l = this.itemSize; i < l; i ++ ) { + var face = faces2[ i ], faceCopy, normal, color, + faceVertexNormals = face.vertexNormals, + faceVertexColors = face.vertexColors; - this.array[ index1 + i ] = attribute.array[ index2 + i ]; + faceCopy = new Face3( face.a + vertexOffset, face.b + vertexOffset, face.c + vertexOffset ); + faceCopy.normal.copy( face.normal ); - } + if ( normalMatrix !== undefined ) { - return this; + faceCopy.normal.applyMatrix3( normalMatrix ).normalize(); - }, + } - copyArray: function ( array ) { + for ( var j = 0, jl = faceVertexNormals.length; j < jl; j ++ ) { - this.array.set( array ); + normal = faceVertexNormals[ j ].clone(); - return this; + if ( normalMatrix !== undefined ) { - }, + normal.applyMatrix3( normalMatrix ).normalize(); - copyColorsArray: function ( colors ) { + } - var array = this.array, offset = 0; + faceCopy.vertexNormals.push( normal ); - for ( var i = 0, l = colors.length; i < l; i ++ ) { + } - var color = colors[ i ]; + faceCopy.color.copy( face.color ); - if ( color === undefined ) { + for ( var j = 0, jl = faceVertexColors.length; j < jl; j ++ ) { - console.warn( 'THREE.BufferAttribute.copyColorsArray(): color is undefined', i ); - color = new Color(); + color = faceVertexColors[ j ]; + faceCopy.vertexColors.push( color.clone() ); } - array[ offset ++ ] = color.r; - array[ offset ++ ] = color.g; - array[ offset ++ ] = color.b; + faceCopy.materialIndex = face.materialIndex + materialIndexOffset; + + faces1.push( faceCopy ); } - return this; + // uvs - }, + for ( i = 0, il = uvs2.length; i < il; i ++ ) { - copyIndicesArray: function ( indices ) { + var uv = uvs2[ i ], uvCopy = []; - var array = this.array, offset = 0; + if ( uv === undefined ) { - for ( var i = 0, l = indices.length; i < l; i ++ ) { + continue; - var index = indices[ i ]; + } - array[ offset ++ ] = index.a; - array[ offset ++ ] = index.b; - array[ offset ++ ] = index.c; + for ( var j = 0, jl = uv.length; j < jl; j ++ ) { - } + uvCopy.push( uv[ j ].clone() ); - return this; + } + + uvs1.push( uvCopy ); + + } }, - copyVector2sArray: function ( vectors ) { + mergeMesh: function ( mesh ) { - var array = this.array, offset = 0; + if ( ! ( mesh && mesh.isMesh ) ) { - for ( var i = 0, l = vectors.length; i < l; i ++ ) { + console.error( 'THREE.Geometry.mergeMesh(): mesh not an instance of THREE.Mesh.', mesh ); + return; - var vector = vectors[ i ]; + } - if ( vector === undefined ) { + mesh.matrixAutoUpdate && mesh.updateMatrix(); - console.warn( 'THREE.BufferAttribute.copyVector2sArray(): vector is undefined', i ); - vector = new Vector2(); + this.merge( mesh.geometry, mesh.matrix ); - } + }, - array[ offset ++ ] = vector.x; - array[ offset ++ ] = vector.y; + /* + * Checks for duplicate vertices with hashmap. + * Duplicated vertices are removed + * and faces' vertices are updated. + */ - } + mergeVertices: function () { - return this; + 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; - copyVector3sArray: function ( vectors ) { + for ( i = 0, il = this.vertices.length; i < il; i ++ ) { - var array = this.array, offset = 0; + v = this.vertices[ i ]; + key = Math.round( v.x * precision ) + '_' + Math.round( v.y * precision ) + '_' + Math.round( v.z * precision ); - for ( var i = 0, l = vectors.length; i < l; i ++ ) { + if ( verticesMap[ key ] === undefined ) { - var vector = vectors[ i ]; + verticesMap[ key ] = i; + unique.push( this.vertices[ i ] ); + changes[ i ] = unique.length - 1; - if ( vector === undefined ) { + } else { - console.warn( 'THREE.BufferAttribute.copyVector3sArray(): vector is undefined', i ); - vector = new Vector3(); + //console.log('Duplicate vertex found. ', i, ' could be using ', verticesMap[key]); + changes[ i ] = changes[ verticesMap[ key ] ]; } - array[ offset ++ ] = vector.x; - array[ offset ++ ] = vector.y; - array[ offset ++ ] = vector.z; - } - return this; - }, + // if faces are completely degenerate after merging vertices, we + // have to remove them from the geometry. + var faceIndicesToRemove = []; - copyVector4sArray: function ( vectors ) { + for ( i = 0, il = this.faces.length; i < il; i ++ ) { - var array = this.array, offset = 0; + face = this.faces[ i ]; - for ( var i = 0, l = vectors.length; i < l; i ++ ) { + face.a = changes[ face.a ]; + face.b = changes[ face.b ]; + face.c = changes[ face.c ]; - var vector = vectors[ i ]; + indices = [ face.a, face.b, face.c ]; - if ( vector === undefined ) { + // 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 ++ ) { - console.warn( 'THREE.BufferAttribute.copyVector4sArray(): vector is undefined', i ); - vector = new Vector4(); + if ( indices[ n ] === indices[ ( n + 1 ) % 3 ] ) { - } + faceIndicesToRemove.push( i ); + break; - array[ offset ++ ] = vector.x; - array[ offset ++ ] = vector.y; - array[ offset ++ ] = vector.z; - array[ offset ++ ] = vector.w; + } + + } } - return this; + for ( i = faceIndicesToRemove.length - 1; i >= 0; i -- ) { - }, + var idx = faceIndicesToRemove[ i ]; - set: function ( value, offset ) { + this.faces.splice( idx, 1 ); - if ( offset === undefined ) offset = 0; + for ( j = 0, jl = this.faceVertexUvs.length; j < jl; j ++ ) { - this.array.set( value, offset ); + this.faceVertexUvs[ j ].splice( idx, 1 ); - return this; + } - }, + } - getX: function ( index ) { + // Use unique set of vertices - return this.array[ index * this.itemSize ]; + var diff = this.vertices.length - unique.length; + this.vertices = unique; + return diff; }, - setX: function ( index, x ) { + sortFacesByMaterialIndex: function () { - this.array[ index * this.itemSize ] = x; + var faces = this.faces; + var length = faces.length; - return this; + // tag faces - }, + for ( var i = 0; i < length; i ++ ) { - getY: function ( index ) { + faces[ i ]._id = i; - return this.array[ index * this.itemSize + 1 ]; + } - }, + // sort faces - setY: function ( index, y ) { + function materialIndexSort( a, b ) { - this.array[ index * this.itemSize + 1 ] = y; + return a.materialIndex - b.materialIndex; - return this; + } - }, + faces.sort( materialIndexSort ); - getZ: function ( index ) { + // sort uvs - return this.array[ index * this.itemSize + 2 ]; + var uvs1 = this.faceVertexUvs[ 0 ]; + var uvs2 = this.faceVertexUvs[ 1 ]; - }, + var newUvs1, newUvs2; - setZ: function ( index, z ) { + if ( uvs1 && uvs1.length === length ) newUvs1 = []; + if ( uvs2 && uvs2.length === length ) newUvs2 = []; - this.array[ index * this.itemSize + 2 ] = z; + for ( var i = 0; i < length; i ++ ) { - return this; + var id = faces[ i ]._id; - }, + if ( newUvs1 ) newUvs1.push( uvs1[ id ] ); + if ( newUvs2 ) newUvs2.push( uvs2[ id ] ); - getW: function ( index ) { + } - return this.array[ index * this.itemSize + 3 ]; + if ( newUvs1 ) this.faceVertexUvs[ 0 ] = newUvs1; + if ( newUvs2 ) this.faceVertexUvs[ 1 ] = newUvs2; }, - setW: function ( index, w ) { - - this.array[ index * this.itemSize + 3 ] = w; - - return this; + toJSON: function () { - }, + var data = { + metadata: { + version: 4.5, + type: 'Geometry', + generator: 'Geometry.toJSON' + } + }; - setXY: function ( index, x, y ) { + // standard Geometry serialization - index *= this.itemSize; + data.uuid = this.uuid; + data.type = this.type; + if ( this.name !== '' ) data.name = this.name; - this.array[ index + 0 ] = x; - this.array[ index + 1 ] = y; + if ( this.parameters !== undefined ) { - return this; + var parameters = this.parameters; - }, + for ( var key in parameters ) { - setXYZ: function ( index, x, y, z ) { + if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ]; - index *= this.itemSize; + } - this.array[ index + 0 ] = x; - this.array[ index + 1 ] = y; - this.array[ index + 2 ] = z; + return data; - return this; + } - }, + var vertices = []; - setXYZW: function ( index, x, y, z, w ) { + for ( var i = 0; i < this.vertices.length; i ++ ) { - index *= this.itemSize; + var vertex = this.vertices[ i ]; + vertices.push( vertex.x, vertex.y, vertex.z ); - this.array[ index + 0 ] = x; - this.array[ index + 1 ] = y; - this.array[ index + 2 ] = z; - this.array[ index + 3 ] = w; + } - return this; + var faces = []; + var normals = []; + var normalsHash = {}; + var colors = []; + var colorsHash = {}; + var uvs = []; + var uvsHash = {}; - }, + for ( var i = 0; i < this.faces.length; i ++ ) { - onUpload: function ( callback ) { + var face = this.faces[ i ]; - this.onUploadCallback = callback; + 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; - return this; + var faceType = 0; - }, + faceType = setBit( faceType, 0, 0 ); // isQuad + faceType = setBit( faceType, 1, hasMaterial ); + faceType = setBit( faceType, 2, hasFaceUv ); + faceType = setBit( faceType, 3, hasFaceVertexUv ); + faceType = setBit( faceType, 4, hasFaceNormal ); + faceType = setBit( faceType, 5, hasFaceVertexNormal ); + faceType = setBit( faceType, 6, hasFaceColor ); + faceType = setBit( faceType, 7, hasFaceVertexColor ); - clone: function () { + faces.push( faceType ); + faces.push( face.a, face.b, face.c ); + faces.push( face.materialIndex ); - return new this.constructor( this.array, this.itemSize ).copy( this ); + if ( hasFaceVertexUv ) { - } + var faceVertexUvs = this.faceVertexUvs[ 0 ][ i ]; -} ); + faces.push( + getUvIndex( faceVertexUvs[ 0 ] ), + getUvIndex( faceVertexUvs[ 1 ] ), + getUvIndex( faceVertexUvs[ 2 ] ) + ); -// + } -function Int8BufferAttribute( array, itemSize ) { + if ( hasFaceNormal ) { - BufferAttribute.call( this, new Int8Array( array ), itemSize ); + faces.push( getNormalIndex( face.normal ) ); -} + } -Int8BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); -Int8BufferAttribute.prototype.constructor = Int8BufferAttribute; + if ( hasFaceVertexNormal ) { + var vertexNormals = face.vertexNormals; -function Uint8BufferAttribute( array, itemSize ) { + faces.push( + getNormalIndex( vertexNormals[ 0 ] ), + getNormalIndex( vertexNormals[ 1 ] ), + getNormalIndex( vertexNormals[ 2 ] ) + ); - BufferAttribute.call( this, new Uint8Array( array ), itemSize ); + } -} + if ( hasFaceColor ) { -Uint8BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); -Uint8BufferAttribute.prototype.constructor = Uint8BufferAttribute; + faces.push( getColorIndex( face.color ) ); + } -function Uint8ClampedBufferAttribute( array, itemSize ) { + if ( hasFaceVertexColor ) { - BufferAttribute.call( this, new Uint8ClampedArray( array ), itemSize ); + var vertexColors = face.vertexColors; -} + faces.push( + getColorIndex( vertexColors[ 0 ] ), + getColorIndex( vertexColors[ 1 ] ), + getColorIndex( vertexColors[ 2 ] ) + ); -Uint8ClampedBufferAttribute.prototype = Object.create( BufferAttribute.prototype ); -Uint8ClampedBufferAttribute.prototype.constructor = Uint8ClampedBufferAttribute; + } + } -function Int16BufferAttribute( array, itemSize ) { + function setBit( value, position, enabled ) { - BufferAttribute.call( this, new Int16Array( array ), itemSize ); + return enabled ? value | ( 1 << position ) : value & ( ~ ( 1 << position ) ); -} + } -Int16BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); -Int16BufferAttribute.prototype.constructor = Int16BufferAttribute; + function getNormalIndex( normal ) { + var hash = normal.x.toString() + normal.y.toString() + normal.z.toString(); -function Uint16BufferAttribute( array, itemSize ) { + if ( normalsHash[ hash ] !== undefined ) { - BufferAttribute.call( this, new Uint16Array( array ), itemSize ); + return normalsHash[ hash ]; -} + } -Uint16BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); -Uint16BufferAttribute.prototype.constructor = Uint16BufferAttribute; + normalsHash[ hash ] = normals.length / 3; + normals.push( normal.x, normal.y, normal.z ); + return normalsHash[ hash ]; -function Int32BufferAttribute( array, itemSize ) { + } - BufferAttribute.call( this, new Int32Array( array ), itemSize ); + function getColorIndex( color ) { -} + var hash = color.r.toString() + color.g.toString() + color.b.toString(); -Int32BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); -Int32BufferAttribute.prototype.constructor = Int32BufferAttribute; + if ( colorsHash[ hash ] !== undefined ) { + return colorsHash[ hash ]; -function Uint32BufferAttribute( array, itemSize ) { + } - BufferAttribute.call( this, new Uint32Array( array ), itemSize ); + colorsHash[ hash ] = colors.length; + colors.push( color.getHex() ); -} + return colorsHash[ hash ]; -Uint32BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); -Uint32BufferAttribute.prototype.constructor = Uint32BufferAttribute; + } + function getUvIndex( uv ) { -function Float32BufferAttribute( array, itemSize ) { + var hash = uv.x.toString() + uv.y.toString(); - BufferAttribute.call( this, new Float32Array( array ), itemSize ); + if ( uvsHash[ hash ] !== undefined ) { -} + return uvsHash[ hash ]; -Float32BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); -Float32BufferAttribute.prototype.constructor = Float32BufferAttribute; + } + uvsHash[ hash ] = uvs.length / 2; + uvs.push( uv.x, uv.y ); -function Float64BufferAttribute( array, itemSize ) { + return uvsHash[ hash ]; - BufferAttribute.call( this, new Float64Array( array ), itemSize ); + } -} + data.data = {}; -Float64BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); -Float64BufferAttribute.prototype.constructor = Float64BufferAttribute; + 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; -/** - * @author mrdoob / http://mrdoob.com/ - */ + return data; -function DirectGeometry() { + }, - this.indices = []; - this.vertices = []; - this.normals = []; - this.colors = []; - this.uvs = []; - this.uvs2 = []; + clone: function () { - this.groups = []; + /* + // Handle primitives - this.morphTargets = {}; + var parameters = this.parameters; - this.skinWeights = []; - this.skinIndices = []; + if ( parameters !== undefined ) { - // this.lineDistances = []; + var values = []; - this.boundingBox = null; - this.boundingSphere = null; + for ( var key in parameters ) { - // update flags + values.push( parameters[ key ] ); - this.verticesNeedUpdate = false; - this.normalsNeedUpdate = false; - this.colorsNeedUpdate = false; - this.uvsNeedUpdate = false; - this.groupsNeedUpdate = false; + } -} + var geometry = Object.create( this.constructor.prototype ); + this.constructor.apply( geometry, values ); + return geometry; -Object.assign( DirectGeometry.prototype, { + } - computeGroups: function ( geometry ) { + return new this.constructor().copy( this ); + */ - var group; - var groups = []; - var materialIndex = undefined; + return new Geometry().copy( this ); - var faces = geometry.faces; + }, - for ( var i = 0; i < faces.length; i ++ ) { + copy: function ( source ) { - var face = faces[ i ]; + var i, il, j, jl, k, kl; - // materials + // reset - if ( face.materialIndex !== materialIndex ) { + this.vertices = []; + this.colors = []; + this.faces = []; + this.faceVertexUvs = [[]]; + this.morphTargets = []; + this.morphNormals = []; + this.skinWeights = []; + this.skinIndices = []; + this.lineDistances = []; + this.boundingBox = null; + this.boundingSphere = null; - materialIndex = face.materialIndex; + // name - if ( group !== undefined ) { + this.name = source.name; - group.count = ( i * 3 ) - group.start; - groups.push( group ); + // vertices - } + var vertices = source.vertices; - group = { - start: i * 3, - materialIndex: materialIndex - }; + for ( i = 0, il = vertices.length; i < il; i ++ ) { - } + this.vertices.push( vertices[ i ].clone() ); } - if ( group !== undefined ) { + // colors - group.count = ( i * 3 ) - group.start; - groups.push( group ); + var colors = source.colors; - } + for ( i = 0, il = colors.length; i < il; i ++ ) { - this.groups = groups; + this.colors.push( colors[ i ].clone() ); - }, + } - fromGeometry: function ( geometry ) { + // faces - var faces = geometry.faces; - var vertices = geometry.vertices; - var faceVertexUvs = geometry.faceVertexUvs; + var faces = source.faces; - var hasFaceVertexUv = faceVertexUvs[ 0 ] && faceVertexUvs[ 0 ].length > 0; - var hasFaceVertexUv2 = faceVertexUvs[ 1 ] && faceVertexUvs[ 1 ].length > 0; + for ( i = 0, il = faces.length; i < il; i ++ ) { - // morphs + this.faces.push( faces[ i ].clone() ); - var morphTargets = geometry.morphTargets; - var morphTargetsLength = morphTargets.length; + } - var morphTargetsPosition; + // face vertex uvs - if ( morphTargetsLength > 0 ) { + for ( i = 0, il = source.faceVertexUvs.length; i < il; i ++ ) { - morphTargetsPosition = []; + var faceVertexUvs = source.faceVertexUvs[ i ]; - for ( var i = 0; i < morphTargetsLength; i ++ ) { + if ( this.faceVertexUvs[ i ] === undefined ) { - morphTargetsPosition[ i ] = []; + this.faceVertexUvs[ i ] = []; } - this.morphTargets.position = morphTargetsPosition; - - } + for ( j = 0, jl = faceVertexUvs.length; j < jl; j ++ ) { - var morphNormals = geometry.morphNormals; - var morphNormalsLength = morphNormals.length; + var uvs = faceVertexUvs[ j ], uvsCopy = []; - var morphTargetsNormal; + for ( k = 0, kl = uvs.length; k < kl; k ++ ) { - if ( morphNormalsLength > 0 ) { + var uv = uvs[ k ]; - morphTargetsNormal = []; + uvsCopy.push( uv.clone() ); - for ( var i = 0; i < morphNormalsLength; i ++ ) { + } - morphTargetsNormal[ i ] = []; + this.faceVertexUvs[ i ].push( uvsCopy ); } - this.morphTargets.normal = morphTargetsNormal; - } - // skins - - var skinIndices = geometry.skinIndices; - var skinWeights = geometry.skinWeights; - - var hasSkinIndices = skinIndices.length === vertices.length; - var hasSkinWeights = skinWeights.length === vertices.length; - - // + // morph targets - for ( var i = 0; i < faces.length; i ++ ) { + var morphTargets = source.morphTargets; - var face = faces[ i ]; + for ( i = 0, il = morphTargets.length; i < il; i ++ ) { - this.vertices.push( vertices[ face.a ], vertices[ face.b ], vertices[ face.c ] ); + var morphTarget = {}; + morphTarget.name = morphTargets[ i ].name; - var vertexNormals = face.vertexNormals; + // vertices - if ( vertexNormals.length === 3 ) { + if ( morphTargets[ i ].vertices !== undefined ) { - this.normals.push( vertexNormals[ 0 ], vertexNormals[ 1 ], vertexNormals[ 2 ] ); + morphTarget.vertices = []; - } else { + for ( j = 0, jl = morphTargets[ i ].vertices.length; j < jl; j ++ ) { - var normal = face.normal; + morphTarget.vertices.push( morphTargets[ i ].vertices[ j ].clone() ); - this.normals.push( normal, normal, normal ); + } } - var vertexColors = face.vertexColors; + // normals - if ( vertexColors.length === 3 ) { + if ( morphTargets[ i ].normals !== undefined ) { - this.colors.push( vertexColors[ 0 ], vertexColors[ 1 ], vertexColors[ 2 ] ); + morphTarget.normals = []; - } else { + for ( j = 0, jl = morphTargets[ i ].normals.length; j < jl; j ++ ) { - var color = face.color; + morphTarget.normals.push( morphTargets[ i ].normals[ j ].clone() ); - this.colors.push( color, color, color ); + } } - if ( hasFaceVertexUv === true ) { - - var vertexUvs = faceVertexUvs[ 0 ][ i ]; - - if ( vertexUvs !== undefined ) { - - this.uvs.push( vertexUvs[ 0 ], vertexUvs[ 1 ], vertexUvs[ 2 ] ); + this.morphTargets.push( morphTarget ); - } else { + } - console.warn( 'THREE.DirectGeometry.fromGeometry(): Undefined vertexUv ', i ); + // morph normals - this.uvs.push( new Vector2(), new Vector2(), new Vector2() ); + var morphNormals = source.morphNormals; - } + for ( i = 0, il = morphNormals.length; i < il; i ++ ) { - } + var morphNormal = {}; - if ( hasFaceVertexUv2 === true ) { + // vertex normals - var vertexUvs = faceVertexUvs[ 1 ][ i ]; + if ( morphNormals[ i ].vertexNormals !== undefined ) { - if ( vertexUvs !== undefined ) { + morphNormal.vertexNormals = []; - this.uvs2.push( vertexUvs[ 0 ], vertexUvs[ 1 ], vertexUvs[ 2 ] ); + for ( j = 0, jl = morphNormals[ i ].vertexNormals.length; j < jl; j ++ ) { - } else { + var srcVertexNormal = morphNormals[ i ].vertexNormals[ j ]; + var destVertexNormal = {}; - console.warn( 'THREE.DirectGeometry.fromGeometry(): Undefined vertexUv2 ', i ); + destVertexNormal.a = srcVertexNormal.a.clone(); + destVertexNormal.b = srcVertexNormal.b.clone(); + destVertexNormal.c = srcVertexNormal.c.clone(); - this.uvs2.push( new Vector2(), new Vector2(), new Vector2() ); + morphNormal.vertexNormals.push( destVertexNormal ); } } - // morphs + // face normals - for ( var j = 0; j < morphTargetsLength; j ++ ) { + if ( morphNormals[ i ].faceNormals !== undefined ) { - var morphTarget = morphTargets[ j ].vertices; + morphNormal.faceNormals = []; - morphTargetsPosition[ j ].push( morphTarget[ face.a ], morphTarget[ face.b ], morphTarget[ face.c ] ); + for ( j = 0, jl = morphNormals[ i ].faceNormals.length; j < jl; j ++ ) { + + morphNormal.faceNormals.push( morphNormals[ i ].faceNormals[ j ].clone() ); + + } } - for ( var j = 0; j < morphNormalsLength; j ++ ) { + this.morphNormals.push( morphNormal ); - var morphNormal = morphNormals[ j ].vertexNormals[ i ]; + } - morphTargetsNormal[ j ].push( morphNormal.a, morphNormal.b, morphNormal.c ); + // skin weights - } + var skinWeights = source.skinWeights; - // skins + for ( i = 0, il = skinWeights.length; i < il; i ++ ) { - if ( hasSkinIndices ) { + this.skinWeights.push( skinWeights[ i ].clone() ); - this.skinIndices.push( skinIndices[ face.a ], skinIndices[ face.b ], skinIndices[ face.c ] ); + } - } + // skin indices - if ( hasSkinWeights ) { + var skinIndices = source.skinIndices; - this.skinWeights.push( skinWeights[ face.a ], skinWeights[ face.b ], skinWeights[ face.c ] ); + for ( i = 0, il = skinIndices.length; i < il; i ++ ) { - } + this.skinIndices.push( skinIndices[ i ].clone() ); } - this.computeGroups( geometry ); + // line distances - this.verticesNeedUpdate = geometry.verticesNeedUpdate; - this.normalsNeedUpdate = geometry.normalsNeedUpdate; - this.colorsNeedUpdate = geometry.colorsNeedUpdate; - this.uvsNeedUpdate = geometry.uvsNeedUpdate; - this.groupsNeedUpdate = geometry.groupsNeedUpdate; + var lineDistances = source.lineDistances; - return this; + for ( i = 0, il = lineDistances.length; i < il; i ++ ) { - } + this.lineDistances.push( lineDistances[ i ] ); -} ); + } -function arrayMax( array ) { + // bounding box - if ( array.length === 0 ) return - Infinity; + var boundingBox = source.boundingBox; - var max = array[ 0 ]; + if ( boundingBox !== null ) { - for ( var i = 1, l = array.length; i < l; ++ i ) { + this.boundingBox = boundingBox.clone(); - if ( array[ i ] > max ) max = array[ i ]; + } - } + // bounding sphere - return max; + var boundingSphere = source.boundingSphere; -} + if ( boundingSphere !== null ) { -/** - * @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 - */ + this.boundingSphere = boundingSphere.clone(); -var count = 0; -function GeometryIdCount() { return count++; } + } -function Geometry() { + // update flags - Object.defineProperty( this, 'id', { value: GeometryIdCount() } ); + 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; - this.uuid = _Math.generateUUID(); + return this; - this.name = ''; - this.type = 'Geometry'; + }, - this.vertices = []; - this.colors = []; - this.faces = []; - this.faceVertexUvs = [[]]; + dispose: function () { - this.morphTargets = []; - this.morphNormals = []; + this.dispatchEvent( { type: 'dispose' } ); - this.skinWeights = []; - this.skinIndices = []; + } - this.lineDistances = []; +} ); - this.boundingBox = null; - this.boundingSphere = null; +/** + * @author mrdoob / http://mrdoob.com/ + */ - // update flags +function BufferAttribute( array, itemSize, normalized ) { - this.elementsNeedUpdate = false; - this.verticesNeedUpdate = false; - this.uvsNeedUpdate = false; - this.normalsNeedUpdate = false; - this.colorsNeedUpdate = false; - this.lineDistancesNeedUpdate = false; - this.groupsNeedUpdate = false; + if ( Array.isArray( array ) ) { -} + throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' ); -Object.assign( Geometry.prototype, EventDispatcher.prototype, { + } - isGeometry: true, + this.uuid = _Math.generateUUID(); + this.name = ''; - applyMatrix: function ( matrix ) { + this.array = array; + this.itemSize = itemSize; + this.count = array !== undefined ? array.length / itemSize : 0; + this.normalized = normalized === true; - var normalMatrix = new Matrix3().getNormalMatrix( matrix ); + this.dynamic = false; + this.updateRange = { offset: 0, count: - 1 }; - for ( var i = 0, il = this.vertices.length; i < il; i ++ ) { + this.onUploadCallback = function () {}; - var vertex = this.vertices[ i ]; - vertex.applyMatrix4( matrix ); + this.version = 0; - } +} - for ( var i = 0, il = this.faces.length; i < il; i ++ ) { +Object.defineProperty( BufferAttribute.prototype, 'needsUpdate', { - var face = this.faces[ i ]; - face.normal.applyMatrix3( normalMatrix ).normalize(); + set: function ( value ) { - for ( var j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) { + if ( value === true ) this.version ++; - face.vertexNormals[ j ].applyMatrix3( normalMatrix ).normalize(); + } - } +} ); - } +Object.assign( BufferAttribute.prototype, { - if ( this.boundingBox !== null ) { + isBufferAttribute: true, - this.computeBoundingBox(); + setArray: function ( array ) { + + if ( Array.isArray( array ) ) { + + throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' ); } - if ( this.boundingSphere !== null ) { + this.count = array !== undefined ? array.length / this.itemSize : 0; + this.array = array; - this.computeBoundingSphere(); + }, - } + setDynamic: function ( value ) { - this.verticesNeedUpdate = true; - this.normalsNeedUpdate = true; + this.dynamic = value; return this; }, - rotateX: function () { + copy: function ( source ) { - // rotate geometry around world x-axis + this.array = new source.array.constructor( source.array ); + this.itemSize = source.itemSize; + this.count = source.count; + this.normalized = source.normalized; - var m1 = new Matrix4(); + this.dynamic = source.dynamic; - return function rotateX( angle ) { + return this; - m1.makeRotationX( angle ); + }, - this.applyMatrix( m1 ); + copyAt: function ( index1, attribute, index2 ) { - return this; + index1 *= this.itemSize; + index2 *= attribute.itemSize; - }; + for ( var i = 0, l = this.itemSize; i < l; i ++ ) { - }(), + this.array[ index1 + i ] = attribute.array[ index2 + i ]; - rotateY: function () { + } - // rotate geometry around world y-axis + return this; - var m1 = new Matrix4(); + }, - return function rotateY( angle ) { + copyArray: function ( array ) { - m1.makeRotationY( angle ); + this.array.set( array ); - this.applyMatrix( m1 ); + return this; - return this; + }, - }; + copyColorsArray: function ( colors ) { - }(), + var array = this.array, offset = 0; - rotateZ: function () { + for ( var i = 0, l = colors.length; i < l; i ++ ) { - // rotate geometry around world z-axis + var color = colors[ i ]; - var m1 = new Matrix4(); + if ( color === undefined ) { - return function rotateZ( angle ) { + console.warn( 'THREE.BufferAttribute.copyColorsArray(): color is undefined', i ); + color = new Color(); - m1.makeRotationZ( angle ); + } - this.applyMatrix( m1 ); + array[ offset ++ ] = color.r; + array[ offset ++ ] = color.g; + array[ offset ++ ] = color.b; - return this; + } - }; + return this; - }(), + }, - translate: function () { + copyIndicesArray: function ( indices ) { - // translate geometry + var array = this.array, offset = 0; - var m1 = new Matrix4(); + for ( var i = 0, l = indices.length; i < l; i ++ ) { - return function translate( x, y, z ) { + var index = indices[ i ]; - m1.makeTranslation( x, y, z ); + array[ offset ++ ] = index.a; + array[ offset ++ ] = index.b; + array[ offset ++ ] = index.c; - this.applyMatrix( m1 ); + } - return this; + return this; - }; + }, - }(), + copyVector2sArray: function ( vectors ) { - scale: function () { + var array = this.array, offset = 0; - // scale geometry + for ( var i = 0, l = vectors.length; i < l; i ++ ) { - var m1 = new Matrix4(); + var vector = vectors[ i ]; - return function scale( x, y, z ) { + if ( vector === undefined ) { - m1.makeScale( x, y, z ); + console.warn( 'THREE.BufferAttribute.copyVector2sArray(): vector is undefined', i ); + vector = new Vector2(); - this.applyMatrix( m1 ); + } - return this; + array[ offset ++ ] = vector.x; + array[ offset ++ ] = vector.y; - }; + } - }(), + return this; - lookAt: function () { + }, - var obj = new Object3D(); + copyVector3sArray: function ( vectors ) { - return function lookAt( vector ) { + var array = this.array, offset = 0; - obj.lookAt( vector ); + for ( var i = 0, l = vectors.length; i < l; i ++ ) { - obj.updateMatrix(); + var vector = vectors[ i ]; - this.applyMatrix( obj.matrix ); + if ( vector === undefined ) { - }; + console.warn( 'THREE.BufferAttribute.copyVector3sArray(): vector is undefined', i ); + vector = new Vector3(); - }(), + } - fromBufferGeometry: function ( geometry ) { + array[ offset ++ ] = vector.x; + array[ offset ++ ] = vector.y; + array[ offset ++ ] = vector.z; - var scope = this; + } - var indices = geometry.index !== null ? geometry.index.array : undefined; - var attributes = geometry.attributes; + return this; - 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; + }, - if ( uvs2 !== undefined ) this.faceVertexUvs[ 1 ] = []; + copyVector4sArray: function ( vectors ) { - var tempNormals = []; - var tempUVs = []; - var tempUVs2 = []; + var array = this.array, offset = 0; - for ( var i = 0, j = 0; i < positions.length; i += 3, j += 2 ) { + for ( var i = 0, l = vectors.length; i < l; i ++ ) { - scope.vertices.push( new Vector3( positions[ i ], positions[ i + 1 ], positions[ i + 2 ] ) ); + var vector = vectors[ i ]; - if ( normals !== undefined ) { + if ( vector === undefined ) { - tempNormals.push( new Vector3( normals[ i ], normals[ i + 1 ], normals[ i + 2 ] ) ); + console.warn( 'THREE.BufferAttribute.copyVector4sArray(): vector is undefined', i ); + vector = new Vector4(); } - if ( colors !== undefined ) { + array[ offset ++ ] = vector.x; + array[ offset ++ ] = vector.y; + array[ offset ++ ] = vector.z; + array[ offset ++ ] = vector.w; - scope.colors.push( new Color( colors[ i ], colors[ i + 1 ], colors[ i + 2 ] ) ); + } - } + return this; - if ( uvs !== undefined ) { + }, - tempUVs.push( new Vector2( uvs[ j ], uvs[ j + 1 ] ) ); + set: function ( value, offset ) { - } + if ( offset === undefined ) offset = 0; - if ( uvs2 !== undefined ) { + this.array.set( value, offset ); - tempUVs2.push( new Vector2( uvs2[ j ], uvs2[ j + 1 ] ) ); + return this; - } + }, - } + getX: function ( index ) { - function addFace( a, b, c, materialIndex ) { + return this.array[ index * this.itemSize ]; - var vertexNormals = normals !== undefined ? [ tempNormals[ a ].clone(), tempNormals[ b ].clone(), tempNormals[ c ].clone() ] : []; - var vertexColors = colors !== undefined ? [ scope.colors[ a ].clone(), scope.colors[ b ].clone(), scope.colors[ c ].clone() ] : []; + }, - var face = new Face3( a, b, c, vertexNormals, vertexColors, materialIndex ); + setX: function ( index, x ) { - scope.faces.push( face ); + this.array[ index * this.itemSize ] = x; - if ( uvs !== undefined ) { + return this; - scope.faceVertexUvs[ 0 ].push( [ tempUVs[ a ].clone(), tempUVs[ b ].clone(), tempUVs[ c ].clone() ] ); + }, - } + getY: function ( index ) { - if ( uvs2 !== undefined ) { + return this.array[ index * this.itemSize + 1 ]; - scope.faceVertexUvs[ 1 ].push( [ tempUVs2[ a ].clone(), tempUVs2[ b ].clone(), tempUVs2[ c ].clone() ] ); + }, - } + setY: function ( index, y ) { - } + this.array[ index * this.itemSize + 1 ] = y; - var groups = geometry.groups; + return this; - if ( groups.length > 0 ) { + }, - for ( var i = 0; i < groups.length; i ++ ) { + getZ: function ( index ) { - var group = groups[ i ]; + return this.array[ index * this.itemSize + 2 ]; - var start = group.start; - var count = group.count; + }, - for ( var j = start, jl = start + count; j < jl; j += 3 ) { + setZ: function ( index, z ) { - if ( indices !== undefined ) { + this.array[ index * this.itemSize + 2 ] = z; - addFace( indices[ j ], indices[ j + 1 ], indices[ j + 2 ], group.materialIndex ); + return this; - } else { + }, - addFace( j, j + 1, j + 2, group.materialIndex ); + getW: function ( index ) { - } + return this.array[ index * this.itemSize + 3 ]; - } + }, - } + setW: function ( index, w ) { - } else { + this.array[ index * this.itemSize + 3 ] = w; - if ( indices !== undefined ) { + return this; - for ( var i = 0; i < indices.length; i += 3 ) { + }, - addFace( indices[ i ], indices[ i + 1 ], indices[ i + 2 ] ); + setXY: function ( index, x, y ) { - } + index *= this.itemSize; - } else { + this.array[ index + 0 ] = x; + this.array[ index + 1 ] = y; - for ( var i = 0; i < positions.length / 3; i += 3 ) { + return this; - addFace( i, i + 1, i + 2 ); + }, - } + setXYZ: function ( index, x, y, z ) { - } + index *= this.itemSize; - } + this.array[ index + 0 ] = x; + this.array[ index + 1 ] = y; + this.array[ index + 2 ] = z; - this.computeFaceNormals(); + return this; - if ( geometry.boundingBox !== null ) { + }, - this.boundingBox = geometry.boundingBox.clone(); + setXYZW: function ( index, x, y, z, w ) { - } + index *= this.itemSize; - if ( geometry.boundingSphere !== null ) { + this.array[ index + 0 ] = x; + this.array[ index + 1 ] = y; + this.array[ index + 2 ] = z; + this.array[ index + 3 ] = w; - this.boundingSphere = geometry.boundingSphere.clone(); + return this; - } + }, + + onUpload: function ( callback ) { + + this.onUploadCallback = callback; return this; }, - center: function () { - - this.computeBoundingBox(); + clone: function () { - var offset = this.boundingBox.getCenter().negate(); + return new this.constructor( this.array, this.itemSize ).copy( this ); - this.translate( offset.x, offset.y, offset.z ); + } - return offset; +} ); - }, +// - normalize: function () { +function Int8BufferAttribute( array, itemSize ) { - this.computeBoundingSphere(); + BufferAttribute.call( this, new Int8Array( array ), itemSize ); - var center = this.boundingSphere.center; - var radius = this.boundingSphere.radius; +} - var s = radius === 0 ? 1 : 1.0 / radius; +Int8BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); +Int8BufferAttribute.prototype.constructor = Int8BufferAttribute; - var matrix = new Matrix4(); - matrix.set( - s, 0, 0, - s * center.x, - 0, s, 0, - s * center.y, - 0, 0, s, - s * center.z, - 0, 0, 0, 1 - ); - this.applyMatrix( matrix ); +function Uint8BufferAttribute( array, itemSize ) { - return this; + BufferAttribute.call( this, new Uint8Array( array ), itemSize ); - }, +} - computeFaceNormals: function () { +Uint8BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); +Uint8BufferAttribute.prototype.constructor = Uint8BufferAttribute; - var cb = new Vector3(), ab = new Vector3(); - for ( var f = 0, fl = this.faces.length; f < fl; f ++ ) { +function Uint8ClampedBufferAttribute( array, itemSize ) { - var face = this.faces[ f ]; + BufferAttribute.call( this, new Uint8ClampedArray( array ), itemSize ); - var vA = this.vertices[ face.a ]; - var vB = this.vertices[ face.b ]; - var vC = this.vertices[ face.c ]; +} - cb.subVectors( vC, vB ); - ab.subVectors( vA, vB ); - cb.cross( ab ); +Uint8ClampedBufferAttribute.prototype = Object.create( BufferAttribute.prototype ); +Uint8ClampedBufferAttribute.prototype.constructor = Uint8ClampedBufferAttribute; - cb.normalize(); - face.normal.copy( cb ); +function Int16BufferAttribute( array, itemSize ) { - } + BufferAttribute.call( this, new Int16Array( array ), itemSize ); - }, +} - computeVertexNormals: function ( areaWeighted ) { +Int16BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); +Int16BufferAttribute.prototype.constructor = Int16BufferAttribute; - if ( areaWeighted === undefined ) areaWeighted = true; - var v, vl, f, fl, face, vertices; +function Uint16BufferAttribute( array, itemSize ) { - vertices = new Array( this.vertices.length ); + BufferAttribute.call( this, new Uint16Array( array ), itemSize ); - for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) { +} - vertices[ v ] = new Vector3(); +Uint16BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); +Uint16BufferAttribute.prototype.constructor = Uint16BufferAttribute; - } - if ( areaWeighted ) { +function Int32BufferAttribute( array, itemSize ) { - // vertex normals weighted by triangle areas - // http://www.iquilezles.org/www/articles/normals/normals.htm + BufferAttribute.call( this, new Int32Array( array ), itemSize ); - var vA, vB, vC; - var cb = new Vector3(), ab = new Vector3(); +} - for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { +Int32BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); +Int32BufferAttribute.prototype.constructor = Int32BufferAttribute; - face = this.faces[ f ]; - vA = this.vertices[ face.a ]; - vB = this.vertices[ face.b ]; - vC = this.vertices[ face.c ]; +function Uint32BufferAttribute( array, itemSize ) { - cb.subVectors( vC, vB ); - ab.subVectors( vA, vB ); - cb.cross( ab ); + BufferAttribute.call( this, new Uint32Array( array ), itemSize ); - vertices[ face.a ].add( cb ); - vertices[ face.b ].add( cb ); - vertices[ face.c ].add( cb ); +} - } +Uint32BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); +Uint32BufferAttribute.prototype.constructor = Uint32BufferAttribute; - } else { - this.computeFaceNormals(); +function Float32BufferAttribute( array, itemSize ) { - for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { + BufferAttribute.call( this, new Float32Array( array ), itemSize ); - face = this.faces[ f ]; +} - vertices[ face.a ].add( face.normal ); - vertices[ face.b ].add( face.normal ); - vertices[ face.c ].add( face.normal ); +Float32BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); +Float32BufferAttribute.prototype.constructor = Float32BufferAttribute; - } - } +function Float64BufferAttribute( array, itemSize ) { - for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) { + BufferAttribute.call( this, new Float64Array( array ), itemSize ); - vertices[ v ].normalize(); +} - } +Float64BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); +Float64BufferAttribute.prototype.constructor = Float64BufferAttribute; - for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { +/** + * @author mrdoob / http://mrdoob.com/ + */ - face = this.faces[ f ]; +function DirectGeometry() { - var vertexNormals = face.vertexNormals; + this.indices = []; + this.vertices = []; + this.normals = []; + this.colors = []; + this.uvs = []; + this.uvs2 = []; - if ( vertexNormals.length === 3 ) { + this.groups = []; - vertexNormals[ 0 ].copy( vertices[ face.a ] ); - vertexNormals[ 1 ].copy( vertices[ face.b ] ); - vertexNormals[ 2 ].copy( vertices[ face.c ] ); + this.morphTargets = {}; - } else { + this.skinWeights = []; + this.skinIndices = []; - vertexNormals[ 0 ] = vertices[ face.a ].clone(); - vertexNormals[ 1 ] = vertices[ face.b ].clone(); - vertexNormals[ 2 ] = vertices[ face.c ].clone(); + // this.lineDistances = []; - } + this.boundingBox = null; + this.boundingSphere = null; - } + // update flags - if ( this.faces.length > 0 ) { + this.verticesNeedUpdate = false; + this.normalsNeedUpdate = false; + this.colorsNeedUpdate = false; + this.uvsNeedUpdate = false; + this.groupsNeedUpdate = false; - this.normalsNeedUpdate = true; +} - } +Object.assign( DirectGeometry.prototype, { - }, + computeGroups: function ( geometry ) { - computeFlatVertexNormals: function () { + var group; + var groups = []; + var materialIndex = undefined; - var f, fl, face; + var faces = geometry.faces; - this.computeFaceNormals(); + for ( var i = 0; i < faces.length; i ++ ) { - for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { + var face = faces[ i ]; - face = this.faces[ f ]; + // materials - var vertexNormals = face.vertexNormals; + if ( face.materialIndex !== materialIndex ) { - if ( vertexNormals.length === 3 ) { + materialIndex = face.materialIndex; - vertexNormals[ 0 ].copy( face.normal ); - vertexNormals[ 1 ].copy( face.normal ); - vertexNormals[ 2 ].copy( face.normal ); + if ( group !== undefined ) { - } else { + group.count = ( i * 3 ) - group.start; + groups.push( group ); - vertexNormals[ 0 ] = face.normal.clone(); - vertexNormals[ 1 ] = face.normal.clone(); - vertexNormals[ 2 ] = face.normal.clone(); + } + + group = { + start: i * 3, + materialIndex: materialIndex + }; } } - if ( this.faces.length > 0 ) { + if ( group !== undefined ) { - this.normalsNeedUpdate = true; + group.count = ( i * 3 ) - group.start; + groups.push( group ); } + this.groups = groups; + }, - computeMorphNormals: function () { + fromGeometry: function ( geometry ) { - var i, il, f, fl, face; + var faces = geometry.faces; + var vertices = geometry.vertices; + var faceVertexUvs = geometry.faceVertexUvs; - // save original normals - // - create temp variables on first access - // otherwise just copy (for faster repeated calls) + var hasFaceVertexUv = faceVertexUvs[ 0 ] && faceVertexUvs[ 0 ].length > 0; + var hasFaceVertexUv2 = faceVertexUvs[ 1 ] && faceVertexUvs[ 1 ].length > 0; - for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { + // morphs - face = this.faces[ f ]; + var morphTargets = geometry.morphTargets; + var morphTargetsLength = morphTargets.length; - if ( ! face.__originalFaceNormal ) { + var morphTargetsPosition; - face.__originalFaceNormal = face.normal.clone(); + if ( morphTargetsLength > 0 ) { - } else { + morphTargetsPosition = []; - face.__originalFaceNormal.copy( face.normal ); + for ( var i = 0; i < morphTargetsLength; i ++ ) { + + morphTargetsPosition[ i ] = []; } - if ( ! face.__originalVertexNormals ) face.__originalVertexNormals = []; + this.morphTargets.position = morphTargetsPosition; - for ( i = 0, il = face.vertexNormals.length; i < il; i ++ ) { + } - if ( ! face.__originalVertexNormals[ i ] ) { + var morphNormals = geometry.morphNormals; + var morphNormalsLength = morphNormals.length; - face.__originalVertexNormals[ i ] = face.vertexNormals[ i ].clone(); + var morphTargetsNormal; - } else { + if ( morphNormalsLength > 0 ) { - face.__originalVertexNormals[ i ].copy( face.vertexNormals[ i ] ); + morphTargetsNormal = []; - } + for ( var i = 0; i < morphNormalsLength; i ++ ) { + + morphTargetsNormal[ i ] = []; } + this.morphTargets.normal = morphTargetsNormal; + } - // use temp geometry to compute face and vertex normals for each morph + // skins - var tmpGeo = new Geometry(); - tmpGeo.faces = this.faces; + var skinIndices = geometry.skinIndices; + var skinWeights = geometry.skinWeights; - for ( i = 0, il = this.morphTargets.length; i < il; i ++ ) { + var hasSkinIndices = skinIndices.length === vertices.length; + var hasSkinWeights = skinWeights.length === vertices.length; - // create on first access + // - if ( ! this.morphNormals[ i ] ) { + for ( var i = 0; i < faces.length; i ++ ) { - this.morphNormals[ i ] = {}; - this.morphNormals[ i ].faceNormals = []; - this.morphNormals[ i ].vertexNormals = []; + var face = faces[ i ]; - var dstNormalsFace = this.morphNormals[ i ].faceNormals; - var dstNormalsVertex = this.morphNormals[ i ].vertexNormals; + this.vertices.push( vertices[ face.a ], vertices[ face.b ], vertices[ face.c ] ); - var faceNormal, vertexNormals; + var vertexNormals = face.vertexNormals; - for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { + if ( vertexNormals.length === 3 ) { - faceNormal = new Vector3(); - vertexNormals = { a: new Vector3(), b: new Vector3(), c: new Vector3() }; + this.normals.push( vertexNormals[ 0 ], vertexNormals[ 1 ], vertexNormals[ 2 ] ); - dstNormalsFace.push( faceNormal ); - dstNormalsVertex.push( vertexNormals ); + } else { - } + var normal = face.normal; - } + this.normals.push( normal, normal, normal ); - var morphNormals = this.morphNormals[ i ]; + } - // set vertices to morph target + var vertexColors = face.vertexColors; - tmpGeo.vertices = this.morphTargets[ i ].vertices; + if ( vertexColors.length === 3 ) { - // compute morph normals + this.colors.push( vertexColors[ 0 ], vertexColors[ 1 ], vertexColors[ 2 ] ); - tmpGeo.computeFaceNormals(); - tmpGeo.computeVertexNormals(); + } else { - // store morph normals + var color = face.color; - var faceNormal, vertexNormals; + this.colors.push( color, color, color ); - for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { + } - face = this.faces[ f ]; + if ( hasFaceVertexUv === true ) { - faceNormal = morphNormals.faceNormals[ f ]; - vertexNormals = morphNormals.vertexNormals[ f ]; + var vertexUvs = faceVertexUvs[ 0 ][ i ]; - faceNormal.copy( face.normal ); + if ( vertexUvs !== undefined ) { - vertexNormals.a.copy( face.vertexNormals[ 0 ] ); - vertexNormals.b.copy( face.vertexNormals[ 1 ] ); - vertexNormals.c.copy( face.vertexNormals[ 2 ] ); + this.uvs.push( vertexUvs[ 0 ], vertexUvs[ 1 ], vertexUvs[ 2 ] ); - } + } else { - } + console.warn( 'THREE.DirectGeometry.fromGeometry(): Undefined vertexUv ', i ); - // restore original normals + this.uvs.push( new Vector2(), new Vector2(), new Vector2() ); - for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { + } - face = this.faces[ f ]; + } - face.normal = face.__originalFaceNormal; - face.vertexNormals = face.__originalVertexNormals; + if ( hasFaceVertexUv2 === true ) { - } + var vertexUvs = faceVertexUvs[ 1 ][ i ]; - }, + if ( vertexUvs !== undefined ) { - computeLineDistances: function () { + this.uvs2.push( vertexUvs[ 0 ], vertexUvs[ 1 ], vertexUvs[ 2 ] ); - var d = 0; - var vertices = this.vertices; + } else { - for ( var i = 0, il = vertices.length; i < il; i ++ ) { + console.warn( 'THREE.DirectGeometry.fromGeometry(): Undefined vertexUv2 ', i ); - if ( i > 0 ) { + this.uvs2.push( new Vector2(), new Vector2(), new Vector2() ); - d += vertices[ i ].distanceTo( vertices[ i - 1 ] ); + } } - this.lineDistances[ i ] = d; - - } - - }, + // morphs - computeBoundingBox: function () { + for ( var j = 0; j < morphTargetsLength; j ++ ) { - if ( this.boundingBox === null ) { + var morphTarget = morphTargets[ j ].vertices; - this.boundingBox = new Box3(); + morphTargetsPosition[ j ].push( morphTarget[ face.a ], morphTarget[ face.b ], morphTarget[ face.c ] ); - } + } - this.boundingBox.setFromPoints( this.vertices ); + for ( var j = 0; j < morphNormalsLength; j ++ ) { - }, + var morphNormal = morphNormals[ j ].vertexNormals[ i ]; - computeBoundingSphere: function () { + morphTargetsNormal[ j ].push( morphNormal.a, morphNormal.b, morphNormal.c ); - if ( this.boundingSphere === null ) { + } - this.boundingSphere = new Sphere(); + // skins - } + if ( hasSkinIndices ) { - this.boundingSphere.setFromPoints( this.vertices ); + this.skinIndices.push( skinIndices[ face.a ], skinIndices[ face.b ], skinIndices[ face.c ] ); - }, + } - merge: function ( geometry, matrix, materialIndexOffset ) { + if ( hasSkinWeights ) { - if ( ( geometry && geometry.isGeometry ) === false ) { + this.skinWeights.push( skinWeights[ face.a ], skinWeights[ face.b ], skinWeights[ face.c ] ); - console.error( 'THREE.Geometry.merge(): geometry not an instance of THREE.Geometry.', geometry ); - return; + } } - var normalMatrix, - vertexOffset = this.vertices.length, - vertices1 = this.vertices, - vertices2 = geometry.vertices, - faces1 = this.faces, - faces2 = geometry.faces, - uvs1 = this.faceVertexUvs[ 0 ], - uvs2 = geometry.faceVertexUvs[ 0 ], - colors1 = this.colors, - colors2 = geometry.colors; + this.computeGroups( geometry ); - if ( materialIndexOffset === undefined ) materialIndexOffset = 0; + this.verticesNeedUpdate = geometry.verticesNeedUpdate; + this.normalsNeedUpdate = geometry.normalsNeedUpdate; + this.colorsNeedUpdate = geometry.colorsNeedUpdate; + this.uvsNeedUpdate = geometry.uvsNeedUpdate; + this.groupsNeedUpdate = geometry.groupsNeedUpdate; - if ( matrix !== undefined ) { + return this; - normalMatrix = new Matrix3().getNormalMatrix( matrix ); + } - } +} ); - // vertices +/** + * @author mrdoob / http://mrdoob.com/ + */ - for ( var i = 0, il = vertices2.length; i < il; i ++ ) { +function arrayMax( array ) { - var vertex = vertices2[ i ]; + if ( array.length === 0 ) return - Infinity; - var vertexCopy = vertex.clone(); + var max = array[ 0 ]; - if ( matrix !== undefined ) vertexCopy.applyMatrix4( matrix ); + for ( var i = 1, l = array.length; i < l; ++ i ) { - vertices1.push( vertexCopy ); + if ( array[ i ] > max ) max = array[ i ]; - } + } - // colors + return max; - for ( var i = 0, il = colors2.length; i < il; i ++ ) { +} - colors1.push( colors2[ i ].clone() ); +/** + * @author alteredq / http://alteredqualia.com/ + * @author mrdoob / http://mrdoob.com/ + */ - } +function BufferGeometry() { - // faces + Object.defineProperty( this, 'id', { value: GeometryIdCount() } ); - for ( i = 0, il = faces2.length; i < il; i ++ ) { + this.uuid = _Math.generateUUID(); - var face = faces2[ i ], faceCopy, normal, color, - faceVertexNormals = face.vertexNormals, - faceVertexColors = face.vertexColors; + this.name = ''; + this.type = 'BufferGeometry'; - faceCopy = new Face3( face.a + vertexOffset, face.b + vertexOffset, face.c + vertexOffset ); - faceCopy.normal.copy( face.normal ); + this.index = null; + this.attributes = {}; - if ( normalMatrix !== undefined ) { + this.morphAttributes = {}; - faceCopy.normal.applyMatrix3( normalMatrix ).normalize(); + this.groups = []; - } + this.boundingBox = null; + this.boundingSphere = null; - for ( var j = 0, jl = faceVertexNormals.length; j < jl; j ++ ) { + this.drawRange = { start: 0, count: Infinity }; - normal = faceVertexNormals[ j ].clone(); +} - if ( normalMatrix !== undefined ) { +BufferGeometry.MaxIndex = 65535; - normal.applyMatrix3( normalMatrix ).normalize(); +Object.assign( BufferGeometry.prototype, EventDispatcher.prototype, { - } + isBufferGeometry: true, - faceCopy.vertexNormals.push( normal ); + getIndex: function () { - } + return this.index; - faceCopy.color.copy( face.color ); + }, - for ( var j = 0, jl = faceVertexColors.length; j < jl; j ++ ) { + setIndex: function ( index ) { - color = faceVertexColors[ j ]; - faceCopy.vertexColors.push( color.clone() ); + if ( Array.isArray( index ) ) { - } + this.index = new ( arrayMax( index ) > 65535 ? Uint32BufferAttribute : Uint16BufferAttribute )( index, 1 ); - faceCopy.materialIndex = face.materialIndex + materialIndexOffset; + } else { - faces1.push( faceCopy ); + this.index = index; } - // uvs - - for ( i = 0, il = uvs2.length; i < il; i ++ ) { - - var uv = uvs2[ i ], uvCopy = []; - - if ( uv === undefined ) { - - continue; + }, - } + addAttribute: function ( name, attribute ) { - for ( var j = 0, jl = uv.length; j < jl; j ++ ) { + if ( ! ( attribute && attribute.isBufferAttribute ) && ! ( attribute && attribute.isInterleavedBufferAttribute ) ) { - uvCopy.push( uv[ j ].clone() ); + console.warn( 'THREE.BufferGeometry: .addAttribute() now expects ( name, attribute ).' ); - } + this.addAttribute( name, new BufferAttribute( arguments[ 1 ], arguments[ 2 ] ) ); - uvs1.push( uvCopy ); + return; } - }, - - mergeMesh: function ( mesh ) { + if ( name === 'index' ) { - if ( ( mesh && mesh.isMesh ) === false ) { + console.warn( 'THREE.BufferGeometry.addAttribute: Use .setIndex() for index attribute.' ); + this.setIndex( attribute ); - console.error( 'THREE.Geometry.mergeMesh(): mesh not an instance of THREE.Mesh.', mesh ); return; } - mesh.matrixAutoUpdate && mesh.updateMatrix(); + this.attributes[ name ] = attribute; - this.merge( mesh.geometry, mesh.matrix ); + return this; }, - /* - * Checks for duplicate vertices with hashmap. - * Duplicated vertices are removed - * and faces' vertices are updated. - */ - - mergeVertices: function () { + getAttribute: function ( name ) { - var verticesMap = {}; // Hashmap for looking up vertices by position coordinates (and making sure they are unique) - var unique = [], changes = []; + return this.attributes[ name ]; - 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; + }, - for ( i = 0, il = this.vertices.length; i < il; i ++ ) { + removeAttribute: function ( name ) { - v = this.vertices[ i ]; - key = Math.round( v.x * precision ) + '_' + Math.round( v.y * precision ) + '_' + Math.round( v.z * precision ); + delete this.attributes[ name ]; - if ( verticesMap[ key ] === undefined ) { + return this; - verticesMap[ key ] = i; - unique.push( this.vertices[ i ] ); - changes[ i ] = unique.length - 1; + }, - } else { + addGroup: function ( start, count, materialIndex ) { - //console.log('Duplicate vertex found. ', i, ' could be using ', verticesMap[key]); - changes[ i ] = changes[ verticesMap[ key ] ]; + this.groups.push( { - } + start: start, + count: count, + materialIndex: materialIndex !== undefined ? materialIndex : 0 - } + } ); + }, - // if faces are completely degenerate after merging vertices, we - // have to remove them from the geometry. - var faceIndicesToRemove = []; + clearGroups: function () { - for ( i = 0, il = this.faces.length; i < il; i ++ ) { + this.groups = []; - face = this.faces[ i ]; + }, - face.a = changes[ face.a ]; - face.b = changes[ face.b ]; - face.c = changes[ face.c ]; + setDrawRange: function ( start, count ) { - indices = [ face.a, face.b, face.c ]; + this.drawRange.start = start; + this.drawRange.count = count; - // if any duplicate vertices are found in a Face3 - // we have to remove the face as nothing can be saved - for ( var n = 0; n < 3; n ++ ) { + }, - if ( indices[ n ] === indices[ ( n + 1 ) % 3 ] ) { + applyMatrix: function ( matrix ) { - faceIndicesToRemove.push( i ); - break; + var position = this.attributes.position; - } + if ( position !== undefined ) { - } + matrix.applyToBufferAttribute( position ); + position.needsUpdate = true; } - for ( i = faceIndicesToRemove.length - 1; i >= 0; i -- ) { - - var idx = faceIndicesToRemove[ i ]; - - this.faces.splice( idx, 1 ); + var normal = this.attributes.normal; - for ( j = 0, jl = this.faceVertexUvs.length; j < jl; j ++ ) { + if ( normal !== undefined ) { - this.faceVertexUvs[ j ].splice( idx, 1 ); + var normalMatrix = new Matrix3().getNormalMatrix( matrix ); - } + normalMatrix.applyToBufferAttribute( normal ); + normal.needsUpdate = true; } - // Use unique set of vertices - - var diff = this.vertices.length - unique.length; - this.vertices = unique; - return diff; - - }, - - sortFacesByMaterialIndex: function () { - - var faces = this.faces; - var length = faces.length; - - // tag faces - - for ( var i = 0; i < length; i ++ ) { + if ( this.boundingBox !== null ) { - faces[ i ]._id = i; + this.computeBoundingBox(); } - // sort faces - - function materialIndexSort( a, b ) { + if ( this.boundingSphere !== null ) { - return a.materialIndex - b.materialIndex; + this.computeBoundingSphere(); } - faces.sort( materialIndexSort ); + return this; - // sort uvs + }, - var uvs1 = this.faceVertexUvs[ 0 ]; - var uvs2 = this.faceVertexUvs[ 1 ]; + rotateX: function () { - var newUvs1, newUvs2; + // rotate geometry around world x-axis - if ( uvs1 && uvs1.length === length ) newUvs1 = []; - if ( uvs2 && uvs2.length === length ) newUvs2 = []; + var m1 = new Matrix4(); - for ( var i = 0; i < length; i ++ ) { + return function rotateX( angle ) { - var id = faces[ i ]._id; + m1.makeRotationX( angle ); - if ( newUvs1 ) newUvs1.push( uvs1[ id ] ); - if ( newUvs2 ) newUvs2.push( uvs2[ id ] ); + this.applyMatrix( m1 ); - } + return this; - if ( newUvs1 ) this.faceVertexUvs[ 0 ] = newUvs1; - if ( newUvs2 ) this.faceVertexUvs[ 1 ] = newUvs2; + }; - }, + }(), - toJSON: function () { + rotateY: function () { - var data = { - metadata: { - version: 4.5, - type: 'Geometry', - generator: 'Geometry.toJSON' - } - }; + // rotate geometry around world y-axis - // standard Geometry serialization + var m1 = new Matrix4(); - data.uuid = this.uuid; - data.type = this.type; - if ( this.name !== '' ) data.name = this.name; + return function rotateY( angle ) { - if ( this.parameters !== undefined ) { + m1.makeRotationY( angle ); - var parameters = this.parameters; + this.applyMatrix( m1 ); - for ( var key in parameters ) { + return this; - if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ]; + }; - } + }(), - return data; + rotateZ: function () { - } + // rotate geometry around world z-axis - var vertices = []; + var m1 = new Matrix4(); - for ( var i = 0; i < this.vertices.length; i ++ ) { + return function rotateZ( angle ) { - var vertex = this.vertices[ i ]; - vertices.push( vertex.x, vertex.y, vertex.z ); + m1.makeRotationZ( angle ); - } + this.applyMatrix( m1 ); - var faces = []; - var normals = []; - var normalsHash = {}; - var colors = []; - var colorsHash = {}; - var uvs = []; - var uvsHash = {}; + return this; - for ( var i = 0; i < this.faces.length; i ++ ) { + }; - var face = this.faces[ i ]; + }(), - 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; + translate: function () { - var faceType = 0; + // translate geometry - 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 ); + var m1 = new Matrix4(); - faces.push( faceType ); - faces.push( face.a, face.b, face.c ); - faces.push( face.materialIndex ); + return function translate( x, y, z ) { - if ( hasFaceVertexUv ) { + m1.makeTranslation( x, y, z ); - var faceVertexUvs = this.faceVertexUvs[ 0 ][ i ]; + this.applyMatrix( m1 ); - faces.push( - getUvIndex( faceVertexUvs[ 0 ] ), - getUvIndex( faceVertexUvs[ 1 ] ), - getUvIndex( faceVertexUvs[ 2 ] ) - ); + return this; - } + }; - if ( hasFaceNormal ) { + }(), - faces.push( getNormalIndex( face.normal ) ); + scale: function () { - } + // scale geometry - if ( hasFaceVertexNormal ) { + var m1 = new Matrix4(); - var vertexNormals = face.vertexNormals; + return function scale( x, y, z ) { - faces.push( - getNormalIndex( vertexNormals[ 0 ] ), - getNormalIndex( vertexNormals[ 1 ] ), - getNormalIndex( vertexNormals[ 2 ] ) - ); + m1.makeScale( x, y, z ); - } + this.applyMatrix( m1 ); - if ( hasFaceColor ) { + return this; - faces.push( getColorIndex( face.color ) ); + }; - } + }(), - if ( hasFaceVertexColor ) { + lookAt: function () { - var vertexColors = face.vertexColors; + var obj = new Object3D(); - faces.push( - getColorIndex( vertexColors[ 0 ] ), - getColorIndex( vertexColors[ 1 ] ), - getColorIndex( vertexColors[ 2 ] ) - ); + return function lookAt( vector ) { - } + obj.lookAt( vector ); - } + obj.updateMatrix(); - function setBit( value, position, enabled ) { + this.applyMatrix( obj.matrix ); - return enabled ? value | ( 1 << position ) : value & ( ~ ( 1 << position ) ); + }; - } + }(), - function getNormalIndex( normal ) { + center: function () { - var hash = normal.x.toString() + normal.y.toString() + normal.z.toString(); + this.computeBoundingBox(); - if ( normalsHash[ hash ] !== undefined ) { + var offset = this.boundingBox.getCenter().negate(); - return normalsHash[ hash ]; + this.translate( offset.x, offset.y, offset.z ); - } + return offset; - normalsHash[ hash ] = normals.length / 3; - normals.push( normal.x, normal.y, normal.z ); + }, - return normalsHash[ hash ]; + setFromObject: function ( object ) { - } + // console.log( 'THREE.BufferGeometry.setFromObject(). Converting', object, this ); - function getColorIndex( color ) { + var geometry = object.geometry; - var hash = color.r.toString() + color.g.toString() + color.b.toString(); + if ( object.isPoints || object.isLine ) { - if ( colorsHash[ hash ] !== undefined ) { + var positions = new Float32BufferAttribute( geometry.vertices.length * 3, 3 ); + var colors = new Float32BufferAttribute( geometry.colors.length * 3, 3 ); - return colorsHash[ hash ]; + this.addAttribute( 'position', positions.copyVector3sArray( geometry.vertices ) ); + this.addAttribute( 'color', colors.copyColorsArray( geometry.colors ) ); - } + if ( geometry.lineDistances && geometry.lineDistances.length === geometry.vertices.length ) { - colorsHash[ hash ] = colors.length; - colors.push( color.getHex() ); + var lineDistances = new Float32BufferAttribute( geometry.lineDistances.length, 1 ); - return colorsHash[ hash ]; + this.addAttribute( 'lineDistance', lineDistances.copyArray( geometry.lineDistances ) ); - } + } - function getUvIndex( uv ) { + if ( geometry.boundingSphere !== null ) { - var hash = uv.x.toString() + uv.y.toString(); + this.boundingSphere = geometry.boundingSphere.clone(); - if ( uvsHash[ hash ] !== undefined ) { + } - return uvsHash[ hash ]; + if ( geometry.boundingBox !== null ) { + + this.boundingBox = geometry.boundingBox.clone(); } - uvsHash[ hash ] = uvs.length / 2; - uvs.push( uv.x, uv.y ); + } else if ( object.isMesh ) { - return uvsHash[ hash ]; + if ( geometry && geometry.isGeometry ) { - } + this.fromGeometry( geometry ); - data.data = {}; + } - data.data.vertices = vertices; - data.data.normals = normals; - if ( colors.length > 0 ) data.data.colors = colors; - if ( uvs.length > 0 ) data.data.uvs = [ uvs ]; // temporal backward compatibility - data.data.faces = faces; + } - return data; + return this; }, - clone: function () { + updateFromObject: function ( object ) { - /* - // Handle primitives + var geometry = object.geometry; - var parameters = this.parameters; + if ( object.isMesh ) { - if ( parameters !== undefined ) { + var direct = geometry.__directGeometry; - var values = []; + if ( geometry.elementsNeedUpdate === true ) { - for ( var key in parameters ) { + direct = undefined; + geometry.elementsNeedUpdate = false; - values.push( parameters[ key ] ); + } - } + if ( direct === undefined ) { - var geometry = Object.create( this.constructor.prototype ); - this.constructor.apply( geometry, values ); - return geometry; + return this.fromGeometry( geometry ); - } + } - return new this.constructor().copy( this ); - */ + direct.verticesNeedUpdate = geometry.verticesNeedUpdate; + direct.normalsNeedUpdate = geometry.normalsNeedUpdate; + direct.colorsNeedUpdate = geometry.colorsNeedUpdate; + direct.uvsNeedUpdate = geometry.uvsNeedUpdate; + direct.groupsNeedUpdate = geometry.groupsNeedUpdate; - return new Geometry().copy( this ); + geometry.verticesNeedUpdate = false; + geometry.normalsNeedUpdate = false; + geometry.colorsNeedUpdate = false; + geometry.uvsNeedUpdate = false; + geometry.groupsNeedUpdate = false; - }, + geometry = direct; - copy: function ( source ) { + } - var i, il, j, jl, k, kl; + var attribute; - // reset + if ( geometry.verticesNeedUpdate === true ) { - this.vertices = []; - this.colors = []; - this.faces = []; - this.faceVertexUvs = [[]]; - this.morphTargets = []; - this.morphNormals = []; - this.skinWeights = []; - this.skinIndices = []; - this.lineDistances = []; - this.boundingBox = null; - this.boundingSphere = null; + attribute = this.attributes.position; - // name + if ( attribute !== undefined ) { - this.name = source.name; + attribute.copyVector3sArray( geometry.vertices ); + attribute.needsUpdate = true; - // vertices + } - var vertices = source.vertices; + geometry.verticesNeedUpdate = false; - for ( i = 0, il = vertices.length; i < il; i ++ ) { + } - this.vertices.push( vertices[ i ].clone() ); + if ( geometry.normalsNeedUpdate === true ) { - } + attribute = this.attributes.normal; - // colors + if ( attribute !== undefined ) { - var colors = source.colors; + attribute.copyVector3sArray( geometry.normals ); + attribute.needsUpdate = true; - for ( i = 0, il = colors.length; i < il; i ++ ) { + } - this.colors.push( colors[ i ].clone() ); + geometry.normalsNeedUpdate = false; } - // faces + if ( geometry.colorsNeedUpdate === true ) { - var faces = source.faces; + attribute = this.attributes.color; - for ( i = 0, il = faces.length; i < il; i ++ ) { + if ( attribute !== undefined ) { - this.faces.push( faces[ i ].clone() ); + attribute.copyColorsArray( geometry.colors ); + attribute.needsUpdate = true; - } + } - // face vertex uvs + geometry.colorsNeedUpdate = false; - for ( i = 0, il = source.faceVertexUvs.length; i < il; i ++ ) { + } - var faceVertexUvs = source.faceVertexUvs[ i ]; + if ( geometry.uvsNeedUpdate ) { - if ( this.faceVertexUvs[ i ] === undefined ) { + attribute = this.attributes.uv; - this.faceVertexUvs[ i ] = []; + if ( attribute !== undefined ) { - } + attribute.copyVector2sArray( geometry.uvs ); + attribute.needsUpdate = true; - for ( j = 0, jl = faceVertexUvs.length; j < jl; j ++ ) { + } - var uvs = faceVertexUvs[ j ], uvsCopy = []; + geometry.uvsNeedUpdate = false; - for ( k = 0, kl = uvs.length; k < kl; k ++ ) { + } - var uv = uvs[ k ]; + if ( geometry.lineDistancesNeedUpdate ) { - uvsCopy.push( uv.clone() ); + attribute = this.attributes.lineDistance; - } + if ( attribute !== undefined ) { - this.faceVertexUvs[ i ].push( uvsCopy ); + attribute.copyArray( geometry.lineDistances ); + attribute.needsUpdate = true; } + geometry.lineDistancesNeedUpdate = false; + } - // morph targets + if ( geometry.groupsNeedUpdate ) { - var morphTargets = source.morphTargets; + geometry.computeGroups( object.geometry ); + this.groups = geometry.groups; - for ( i = 0, il = morphTargets.length; i < il; i ++ ) { + geometry.groupsNeedUpdate = false; - var morphTarget = {}; - morphTarget.name = morphTargets[ i ].name; + } - // vertices + return this; - if ( morphTargets[ i ].vertices !== undefined ) { + }, - morphTarget.vertices = []; + fromGeometry: function ( geometry ) { - for ( j = 0, jl = morphTargets[ i ].vertices.length; j < jl; j ++ ) { + geometry.__directGeometry = new DirectGeometry().fromGeometry( geometry ); - morphTarget.vertices.push( morphTargets[ i ].vertices[ j ].clone() ); + return this.fromDirectGeometry( geometry.__directGeometry ); - } + }, - } + fromDirectGeometry: function ( geometry ) { - // normals + var positions = new Float32Array( geometry.vertices.length * 3 ); + this.addAttribute( 'position', new BufferAttribute( positions, 3 ).copyVector3sArray( geometry.vertices ) ); - if ( morphTargets[ i ].normals !== undefined ) { + if ( geometry.normals.length > 0 ) { - morphTarget.normals = []; + var normals = new Float32Array( geometry.normals.length * 3 ); + this.addAttribute( 'normal', new BufferAttribute( normals, 3 ).copyVector3sArray( geometry.normals ) ); - for ( j = 0, jl = morphTargets[ i ].normals.length; j < jl; j ++ ) { + } - morphTarget.normals.push( morphTargets[ i ].normals[ j ].clone() ); + if ( geometry.colors.length > 0 ) { - } + var colors = new Float32Array( geometry.colors.length * 3 ); + this.addAttribute( 'color', new BufferAttribute( colors, 3 ).copyColorsArray( geometry.colors ) ); - } + } - this.morphTargets.push( morphTarget ); + if ( geometry.uvs.length > 0 ) { + + var uvs = new Float32Array( geometry.uvs.length * 2 ); + this.addAttribute( 'uv', new BufferAttribute( uvs, 2 ).copyVector2sArray( geometry.uvs ) ); } - // morph normals + if ( geometry.uvs2.length > 0 ) { - var morphNormals = source.morphNormals; + var uvs2 = new Float32Array( geometry.uvs2.length * 2 ); + this.addAttribute( 'uv2', new BufferAttribute( uvs2, 2 ).copyVector2sArray( geometry.uvs2 ) ); - for ( i = 0, il = morphNormals.length; i < il; i ++ ) { + } - var morphNormal = {}; + if ( geometry.indices.length > 0 ) { - // vertex normals + var TypeArray = arrayMax( geometry.indices ) > 65535 ? Uint32Array : Uint16Array; + var indices = new TypeArray( geometry.indices.length * 3 ); + this.setIndex( new BufferAttribute( indices, 1 ).copyIndicesArray( geometry.indices ) ); - if ( morphNormals[ i ].vertexNormals !== undefined ) { + } - morphNormal.vertexNormals = []; + // groups - for ( j = 0, jl = morphNormals[ i ].vertexNormals.length; j < jl; j ++ ) { + this.groups = geometry.groups; - var srcVertexNormal = morphNormals[ i ].vertexNormals[ j ]; - var destVertexNormal = {}; + // morphs - destVertexNormal.a = srcVertexNormal.a.clone(); - destVertexNormal.b = srcVertexNormal.b.clone(); - destVertexNormal.c = srcVertexNormal.c.clone(); + for ( var name in geometry.morphTargets ) { - morphNormal.vertexNormals.push( destVertexNormal ); + var array = []; + var morphTargets = geometry.morphTargets[ name ]; - } + for ( var i = 0, l = morphTargets.length; i < l; i ++ ) { + + var morphTarget = morphTargets[ i ]; + + var attribute = new Float32BufferAttribute( morphTarget.length * 3, 3 ); + + array.push( attribute.copyVector3sArray( morphTarget ) ); } - // face normals + this.morphAttributes[ name ] = array; - if ( morphNormals[ i ].faceNormals !== undefined ) { + } - morphNormal.faceNormals = []; + // skinning - for ( j = 0, jl = morphNormals[ i ].faceNormals.length; j < jl; j ++ ) { + if ( geometry.skinIndices.length > 0 ) { - morphNormal.faceNormals.push( morphNormals[ i ].faceNormals[ j ].clone() ); + var skinIndices = new Float32BufferAttribute( geometry.skinIndices.length * 4, 4 ); + this.addAttribute( 'skinIndex', skinIndices.copyVector4sArray( geometry.skinIndices ) ); - } + } - } + if ( geometry.skinWeights.length > 0 ) { - this.morphNormals.push( morphNormal ); + var skinWeights = new Float32BufferAttribute( geometry.skinWeights.length * 4, 4 ); + this.addAttribute( 'skinWeight', skinWeights.copyVector4sArray( geometry.skinWeights ) ); } - // skin weights + // - var skinWeights = source.skinWeights; + if ( geometry.boundingSphere !== null ) { - for ( i = 0, il = skinWeights.length; i < il; i ++ ) { + this.boundingSphere = geometry.boundingSphere.clone(); - this.skinWeights.push( skinWeights[ i ].clone() ); + } + + if ( geometry.boundingBox !== null ) { + + this.boundingBox = geometry.boundingBox.clone(); } - // skin indices + return this; - var skinIndices = source.skinIndices; + }, - for ( i = 0, il = skinIndices.length; i < il; i ++ ) { + computeBoundingBox: function () { - this.skinIndices.push( skinIndices[ i ].clone() ); + if ( this.boundingBox === null ) { + + this.boundingBox = new Box3(); } - // line distances + var position = this.attributes.position; - var lineDistances = source.lineDistances; + if ( position !== undefined ) { - for ( i = 0, il = lineDistances.length; i < il; i ++ ) { + this.boundingBox.setFromBufferAttribute( position ); - this.lineDistances.push( lineDistances[ i ] ); + } else { + + this.boundingBox.makeEmpty(); } - // bounding box + if ( isNaN( this.boundingBox.min.x ) || isNaN( this.boundingBox.min.y ) || isNaN( this.boundingBox.min.z ) ) { - var boundingBox = source.boundingBox; + console.error( 'THREE.BufferGeometry.computeBoundingBox: Computed min/max have NaN values. The "position" attribute is likely to have NaN values.', this ); - if ( boundingBox !== null ) { + } - this.boundingBox = boundingBox.clone(); + }, - } + computeBoundingSphere: function () { - // bounding sphere + var box = new Box3(); + var vector = new Vector3(); - var boundingSphere = source.boundingSphere; + return function computeBoundingSphere() { - if ( boundingSphere !== null ) { + if ( this.boundingSphere === null ) { - this.boundingSphere = boundingSphere.clone(); + this.boundingSphere = new Sphere(); - } + } - // update flags + var position = this.attributes.position; - 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; + if ( position ) { - return this; + var center = this.boundingSphere.center; - }, + box.setFromBufferAttribute( position ); + box.getCenter( center ); - dispose: function () { + // hoping to find a boundingSphere with a radius smaller than the + // boundingSphere of the boundingBox: sqrt(3) smaller in the best case - this.dispatchEvent( { type: 'dispose' } ); + var maxRadiusSq = 0; - } + for ( var i = 0, il = position.count; i < il; i ++ ) { -} ); + vector.x = position.getX( i ); + vector.y = position.getY( i ); + vector.z = position.getZ( i ); + maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( vector ) ); -/** - * @author alteredq / http://alteredqualia.com/ - * @author mrdoob / http://mrdoob.com/ - */ + } -function BufferGeometry() { + this.boundingSphere.radius = Math.sqrt( maxRadiusSq ); - Object.defineProperty( this, 'id', { value: GeometryIdCount() } ); + if ( isNaN( this.boundingSphere.radius ) ) { - this.uuid = _Math.generateUUID(); + console.error( 'THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The "position" attribute is likely to have NaN values.', this ); - this.name = ''; - this.type = 'BufferGeometry'; + } - this.index = null; - this.attributes = {}; + } - this.morphAttributes = {}; + }; - this.groups = []; + }(), - this.boundingBox = null; - this.boundingSphere = null; + computeFaceNormals: function () { - this.drawRange = { start: 0, count: Infinity }; + // backwards compatibility -} + }, -BufferGeometry.MaxIndex = 65535; + computeVertexNormals: function () { -Object.assign( BufferGeometry.prototype, EventDispatcher.prototype, { + var index = this.index; + var attributes = this.attributes; + var groups = this.groups; - isBufferGeometry: true, + if ( attributes.position ) { - getIndex: function () { + var positions = attributes.position.array; - return this.index; + if ( attributes.normal === undefined ) { - }, + this.addAttribute( 'normal', new BufferAttribute( new Float32Array( positions.length ), 3 ) ); - setIndex: function ( index ) { + } else { - if ( Array.isArray( index ) ) { + // reset existing normals to zero - this.index = new ( arrayMax( index ) > 65535 ? Uint32BufferAttribute : Uint16BufferAttribute )( index, 1 ); + var array = attributes.normal.array; - } else { + for ( var i = 0, il = array.length; i < il; i ++ ) { - this.index = index; + array[ i ] = 0; - } + } - }, + } - addAttribute: function ( name, attribute ) { + var normals = attributes.normal.array; - if ( ( attribute && attribute.isBufferAttribute ) === false && ( attribute && attribute.isInterleavedBufferAttribute ) === false ) { + var vA, vB, vC; + var pA = new Vector3(), pB = new Vector3(), pC = new Vector3(); + var cb = new Vector3(), ab = new Vector3(); - console.warn( 'THREE.BufferGeometry: .addAttribute() now expects ( name, attribute ).' ); + // indexed elements - this.addAttribute( name, new BufferAttribute( arguments[ 1 ], arguments[ 2 ] ) ); + if ( index ) { - return; + var indices = index.array; - } + if ( groups.length === 0 ) { - if ( name === 'index' ) { + this.addGroup( 0, indices.length ); - console.warn( 'THREE.BufferGeometry.addAttribute: Use .setIndex() for index attribute.' ); - this.setIndex( attribute ); + } - return; + for ( var j = 0, jl = groups.length; j < jl; ++ j ) { - } + var group = groups[ j ]; + + var start = group.start; + var count = group.count; + + for ( var i = start, il = start + count; i < il; i += 3 ) { + + vA = indices[ i + 0 ] * 3; + vB = indices[ i + 1 ] * 3; + vC = indices[ i + 2 ] * 3; - this.attributes[ name ] = attribute; + pA.fromArray( positions, vA ); + pB.fromArray( positions, vB ); + pC.fromArray( positions, vC ); - return this; + cb.subVectors( pC, pB ); + ab.subVectors( pA, pB ); + cb.cross( ab ); - }, + normals[ vA ] += cb.x; + normals[ vA + 1 ] += cb.y; + normals[ vA + 2 ] += cb.z; - getAttribute: function ( name ) { + normals[ vB ] += cb.x; + normals[ vB + 1 ] += cb.y; + normals[ vB + 2 ] += cb.z; - return this.attributes[ name ]; + normals[ vC ] += cb.x; + normals[ vC + 1 ] += cb.y; + normals[ vC + 2 ] += cb.z; - }, + } - removeAttribute: function ( name ) { + } - delete this.attributes[ name ]; + } else { - return this; + // non-indexed elements (unconnected triangle soup) - }, + for ( var i = 0, il = positions.length; i < il; i += 9 ) { - addGroup: function ( start, count, materialIndex ) { + pA.fromArray( positions, i ); + pB.fromArray( positions, i + 3 ); + pC.fromArray( positions, i + 6 ); - this.groups.push( { + cb.subVectors( pC, pB ); + ab.subVectors( pA, pB ); + cb.cross( ab ); - start: start, - count: count, - materialIndex: materialIndex !== undefined ? materialIndex : 0 + normals[ i ] = cb.x; + normals[ i + 1 ] = cb.y; + normals[ i + 2 ] = cb.z; - } ); + normals[ i + 3 ] = cb.x; + normals[ i + 4 ] = cb.y; + normals[ i + 5 ] = cb.z; - }, + normals[ i + 6 ] = cb.x; + normals[ i + 7 ] = cb.y; + normals[ i + 8 ] = cb.z; - clearGroups: function () { + } - this.groups = []; + } - }, + this.normalizeNormals(); - setDrawRange: function ( start, count ) { + attributes.normal.needsUpdate = true; - this.drawRange.start = start; - this.drawRange.count = count; + } }, - applyMatrix: function ( matrix ) { - - var position = this.attributes.position; + merge: function ( geometry, offset ) { - if ( position !== undefined ) { + if ( ! ( geometry && geometry.isBufferGeometry ) ) { - matrix.applyToBufferAttribute( position ); - position.needsUpdate = true; + console.error( 'THREE.BufferGeometry.merge(): geometry not an instance of THREE.BufferGeometry.', geometry ); + return; } - var normal = this.attributes.normal; + if ( offset === undefined ) offset = 0; - if ( normal !== undefined ) { + var attributes = this.attributes; - var normalMatrix = new Matrix3().getNormalMatrix( matrix ); + for ( var key in attributes ) { - normalMatrix.applyToBufferAttribute( normal ); - normal.needsUpdate = true; + if ( geometry.attributes[ key ] === undefined ) continue; - } + var attribute1 = attributes[ key ]; + var attributeArray1 = attribute1.array; - if ( this.boundingBox !== null ) { + var attribute2 = geometry.attributes[ key ]; + var attributeArray2 = attribute2.array; - this.computeBoundingBox(); + var attributeSize = attribute2.itemSize; - } + for ( var i = 0, j = attributeSize * offset; i < attributeArray2.length; i ++, j ++ ) { - if ( this.boundingSphere !== null ) { + attributeArray1[ j ] = attributeArray2[ i ]; - this.computeBoundingSphere(); + } } @@ -13985,2163 +14412,2129 @@ Object.assign( BufferGeometry.prototype, EventDispatcher.prototype, { }, - rotateX: function () { - - // rotate geometry around world x-axis - - var m1 = new Matrix4(); + normalizeNormals: function () { - return function rotateX( angle ) { + var vector = new Vector3(); - m1.makeRotationX( angle ); + return function normalizeNormals() { - this.applyMatrix( m1 ); + var normals = this.attributes.normal; - return this; + for ( var i = 0, il = normals.count; i < il; i ++ ) { - }; + vector.x = normals.getX( i ); + vector.y = normals.getY( i ); + vector.z = normals.getZ( i ); - }(), + vector.normalize(); - rotateY: function () { + normals.setXYZ( i, vector.x, vector.y, vector.z ); - // rotate geometry around world y-axis + } - var m1 = new Matrix4(); + }; - return function rotateY( angle ) { + }(), - m1.makeRotationY( angle ); + toNonIndexed: function () { - this.applyMatrix( m1 ); + if ( this.index === null ) { + console.warn( 'THREE.BufferGeometry.toNonIndexed(): Geometry is already non-indexed.' ); return this; - }; + } - }(), + var geometry2 = new BufferGeometry(); - rotateZ: function () { + var indices = this.index.array; + var attributes = this.attributes; - // rotate geometry around world z-axis + for ( var name in attributes ) { - var m1 = new Matrix4(); + var attribute = attributes[ name ]; - return function rotateZ( angle ) { + var array = attribute.array; + var itemSize = attribute.itemSize; - m1.makeRotationZ( angle ); + var array2 = new array.constructor( indices.length * itemSize ); - this.applyMatrix( m1 ); + var index = 0, index2 = 0; - return this; + for ( var i = 0, l = indices.length; i < l; i ++ ) { - }; + index = indices[ i ] * itemSize; - }(), + for ( var j = 0; j < itemSize; j ++ ) { - translate: function () { + array2[ index2 ++ ] = array[ index ++ ]; - // translate geometry + } - var m1 = new Matrix4(); + } - return function translate( x, y, z ) { + geometry2.addAttribute( name, new BufferAttribute( array2, itemSize ) ); - m1.makeTranslation( x, y, z ); + } - this.applyMatrix( m1 ); + return geometry2; - return this; + }, - }; + toJSON: function () { - }(), + var data = { + metadata: { + version: 4.5, + type: 'BufferGeometry', + generator: 'BufferGeometry.toJSON' + } + }; - scale: function () { + // standard BufferGeometry serialization - // scale geometry + data.uuid = this.uuid; + data.type = this.type; + if ( this.name !== '' ) data.name = this.name; - var m1 = new Matrix4(); + if ( this.parameters !== undefined ) { - return function scale( x, y, z ) { + var parameters = this.parameters; - m1.makeScale( x, y, z ); + for ( var key in parameters ) { - this.applyMatrix( m1 ); + if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ]; - return this; + } - }; + return data; - }(), + } - lookAt: function () { + data.data = { attributes: {} }; - var obj = new Object3D(); + var index = this.index; - return function lookAt( vector ) { + if ( index !== null ) { - obj.lookAt( vector ); + var array = Array.prototype.slice.call( index.array ); - obj.updateMatrix(); + data.data.index = { + type: index.array.constructor.name, + array: array + }; - this.applyMatrix( obj.matrix ); + } - }; + var attributes = this.attributes; - }(), + for ( var key in attributes ) { - center: function () { + var attribute = attributes[ key ]; - this.computeBoundingBox(); + var array = Array.prototype.slice.call( attribute.array ); - var offset = this.boundingBox.getCenter().negate(); + data.data.attributes[ key ] = { + itemSize: attribute.itemSize, + type: attribute.array.constructor.name, + array: array, + normalized: attribute.normalized + }; - this.translate( offset.x, offset.y, offset.z ); + } - return offset; + var groups = this.groups; - }, + if ( groups.length > 0 ) { - setFromObject: function ( object ) { + data.data.groups = JSON.parse( JSON.stringify( groups ) ); - // console.log( 'THREE.BufferGeometry.setFromObject(). Converting', object, this ); + } - var geometry = object.geometry; + var boundingSphere = this.boundingSphere; - if ( object.isPoints || object.isLine ) { + if ( boundingSphere !== null ) { - var positions = new Float32BufferAttribute( geometry.vertices.length * 3, 3 ); - var colors = new Float32BufferAttribute( geometry.colors.length * 3, 3 ); + data.data.boundingSphere = { + center: boundingSphere.center.toArray(), + radius: boundingSphere.radius + }; - this.addAttribute( 'position', positions.copyVector3sArray( geometry.vertices ) ); - this.addAttribute( 'color', colors.copyColorsArray( geometry.colors ) ); + } - if ( geometry.lineDistances && geometry.lineDistances.length === geometry.vertices.length ) { + return data; - var lineDistances = new Float32BufferAttribute( geometry.lineDistances.length, 1 ); + }, - this.addAttribute( 'lineDistance', lineDistances.copyArray( geometry.lineDistances ) ); + clone: function () { - } + /* + // Handle primitives - if ( geometry.boundingSphere !== null ) { + var parameters = this.parameters; - this.boundingSphere = geometry.boundingSphere.clone(); + if ( parameters !== undefined ) { - } + var values = []; - if ( geometry.boundingBox !== null ) { + for ( var key in parameters ) { - this.boundingBox = geometry.boundingBox.clone(); + values.push( parameters[ key ] ); - } + } - } else if ( object.isMesh ) { + var geometry = Object.create( this.constructor.prototype ); + this.constructor.apply( geometry, values ); + return geometry; - if ( geometry && geometry.isGeometry ) { + } - this.fromGeometry( geometry ); + return new this.constructor().copy( this ); + */ - } + return new BufferGeometry().copy( this ); - } + }, - return this; + copy: function ( source ) { - }, + var name, i, l; - updateFromObject: function ( object ) { + // reset - var geometry = object.geometry; + this.index = null; + this.attributes = {}; + this.morphAttributes = {}; + this.groups = []; + this.boundingBox = null; + this.boundingSphere = null; - if ( object.isMesh ) { + // name - var direct = geometry.__directGeometry; + this.name = source.name; - if ( geometry.elementsNeedUpdate === true ) { + // index - direct = undefined; - geometry.elementsNeedUpdate = false; + var index = source.index; - } + if ( index !== null ) { - if ( direct === undefined ) { + this.setIndex( index.clone() ); - return this.fromGeometry( geometry ); + } - } + // attributes - direct.verticesNeedUpdate = geometry.verticesNeedUpdate; - direct.normalsNeedUpdate = geometry.normalsNeedUpdate; - direct.colorsNeedUpdate = geometry.colorsNeedUpdate; - direct.uvsNeedUpdate = geometry.uvsNeedUpdate; - direct.groupsNeedUpdate = geometry.groupsNeedUpdate; + var attributes = source.attributes; - geometry.verticesNeedUpdate = false; - geometry.normalsNeedUpdate = false; - geometry.colorsNeedUpdate = false; - geometry.uvsNeedUpdate = false; - geometry.groupsNeedUpdate = false; + for ( name in attributes ) { - geometry = direct; + var attribute = attributes[ name ]; + this.addAttribute( name, attribute.clone() ); } - var attribute; + // morph attributes - if ( geometry.verticesNeedUpdate === true ) { + var morphAttributes = source.morphAttributes; - attribute = this.attributes.position; + for ( name in morphAttributes ) { - if ( attribute !== undefined ) { + var array = []; + var morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes - attribute.copyVector3sArray( geometry.vertices ); - attribute.needsUpdate = true; + for ( i = 0, l = morphAttribute.length; i < l; i ++ ) { + + array.push( morphAttribute[ i ].clone() ); } - geometry.verticesNeedUpdate = false; + this.morphAttributes[ name ] = array; } - if ( geometry.normalsNeedUpdate === true ) { - - attribute = this.attributes.normal; - - if ( attribute !== undefined ) { + // groups - attribute.copyVector3sArray( geometry.normals ); - attribute.needsUpdate = true; + var groups = source.groups; - } + for ( i = 0, l = groups.length; i < l; i ++ ) { - geometry.normalsNeedUpdate = false; + var group = groups[ i ]; + this.addGroup( group.start, group.count, group.materialIndex ); } - if ( geometry.colorsNeedUpdate === true ) { - - attribute = this.attributes.color; - - if ( attribute !== undefined ) { + // bounding box - attribute.copyColorsArray( geometry.colors ); - attribute.needsUpdate = true; + var boundingBox = source.boundingBox; - } + if ( boundingBox !== null ) { - geometry.colorsNeedUpdate = false; + this.boundingBox = boundingBox.clone(); } - if ( geometry.uvsNeedUpdate ) { - - attribute = this.attributes.uv; - - if ( attribute !== undefined ) { + // bounding sphere - attribute.copyVector2sArray( geometry.uvs ); - attribute.needsUpdate = true; + var boundingSphere = source.boundingSphere; - } + if ( boundingSphere !== null ) { - geometry.uvsNeedUpdate = false; + this.boundingSphere = boundingSphere.clone(); } - if ( geometry.lineDistancesNeedUpdate ) { - - attribute = this.attributes.lineDistance; + // draw range - if ( attribute !== undefined ) { + this.drawRange.start = source.drawRange.start; + this.drawRange.count = source.drawRange.count; - attribute.copyArray( geometry.lineDistances ); - attribute.needsUpdate = true; + return this; - } + }, - geometry.lineDistancesNeedUpdate = false; + dispose: function () { - } + this.dispatchEvent( { type: 'dispose' } ); - if ( geometry.groupsNeedUpdate ) { + } - geometry.computeGroups( object.geometry ); - this.groups = geometry.groups; +} ); - geometry.groupsNeedUpdate = false; +/** + * @author mrdoob / http://mrdoob.com/ + * @author Mugen87 / https://github.com/Mugen87 + */ - } +// BoxGeometry - return this; +function BoxGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) { - }, + Geometry.call( this ); - fromGeometry: function ( geometry ) { + this.type = 'BoxGeometry'; - geometry.__directGeometry = new DirectGeometry().fromGeometry( geometry ); + this.parameters = { + width: width, + height: height, + depth: depth, + widthSegments: widthSegments, + heightSegments: heightSegments, + depthSegments: depthSegments + }; - return this.fromDirectGeometry( geometry.__directGeometry ); + this.fromBufferGeometry( new BoxBufferGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) ); + this.mergeVertices(); - }, +} - fromDirectGeometry: function ( geometry ) { +BoxGeometry.prototype = Object.create( Geometry.prototype ); +BoxGeometry.prototype.constructor = BoxGeometry; - var positions = new Float32Array( geometry.vertices.length * 3 ); - this.addAttribute( 'position', new BufferAttribute( positions, 3 ).copyVector3sArray( geometry.vertices ) ); +// BoxBufferGeometry - if ( geometry.normals.length > 0 ) { +function BoxBufferGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) { - var normals = new Float32Array( geometry.normals.length * 3 ); - this.addAttribute( 'normal', new BufferAttribute( normals, 3 ).copyVector3sArray( geometry.normals ) ); + BufferGeometry.call( this ); - } + this.type = 'BoxBufferGeometry'; - if ( geometry.colors.length > 0 ) { + this.parameters = { + width: width, + height: height, + depth: depth, + widthSegments: widthSegments, + heightSegments: heightSegments, + depthSegments: depthSegments + }; - var colors = new Float32Array( geometry.colors.length * 3 ); - this.addAttribute( 'color', new BufferAttribute( colors, 3 ).copyColorsArray( geometry.colors ) ); + var scope = this; - } + // segments - if ( geometry.uvs.length > 0 ) { + widthSegments = Math.floor( widthSegments ) || 1; + heightSegments = Math.floor( heightSegments ) || 1; + depthSegments = Math.floor( depthSegments ) || 1; - var uvs = new Float32Array( geometry.uvs.length * 2 ); - this.addAttribute( 'uv', new BufferAttribute( uvs, 2 ).copyVector2sArray( geometry.uvs ) ); + // buffers - } + var indices = []; + var vertices = []; + var normals = []; + var uvs = []; - if ( geometry.uvs2.length > 0 ) { + // helper variables - var uvs2 = new Float32Array( geometry.uvs2.length * 2 ); - this.addAttribute( 'uv2', new BufferAttribute( uvs2, 2 ).copyVector2sArray( geometry.uvs2 ) ); + var numberOfVertices = 0; + var groupStart = 0; - } + // build each side of the box geometry - if ( geometry.indices.length > 0 ) { + 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 - var TypeArray = arrayMax( geometry.indices ) > 65535 ? Uint32Array : Uint16Array; - var indices = new TypeArray( geometry.indices.length * 3 ); - this.setIndex( new BufferAttribute( indices, 1 ).copyIndicesArray( geometry.indices ) ); + // 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 ) ); - // groups + function buildPlane( u, v, w, udir, vdir, width, height, depth, gridX, gridY, materialIndex ) { - this.groups = geometry.groups; + var segmentWidth = width / gridX; + var segmentHeight = height / gridY; - // morphs + var widthHalf = width / 2; + var heightHalf = height / 2; + var depthHalf = depth / 2; - for ( var name in geometry.morphTargets ) { + var gridX1 = gridX + 1; + var gridY1 = gridY + 1; - var array = []; - var morphTargets = geometry.morphTargets[ name ]; + var vertexCounter = 0; + var groupCount = 0; - for ( var i = 0, l = morphTargets.length; i < l; i ++ ) { + var ix, iy; - var morphTarget = morphTargets[ i ]; + var vector = new Vector3(); - var attribute = new Float32BufferAttribute( morphTarget.length * 3, 3 ); + // generate vertices, normals and uvs - array.push( attribute.copyVector3sArray( morphTarget ) ); + for ( iy = 0; iy < gridY1; iy ++ ) { - } + var y = iy * segmentHeight - heightHalf; - this.morphAttributes[ name ] = array; + for ( ix = 0; ix < gridX1; ix ++ ) { - } + var x = ix * segmentWidth - widthHalf; - // skinning + // set values to correct vector component - if ( geometry.skinIndices.length > 0 ) { + vector[ u ] = x * udir; + vector[ v ] = y * vdir; + vector[ w ] = depthHalf; - var skinIndices = new Float32BufferAttribute( geometry.skinIndices.length * 4, 4 ); - this.addAttribute( 'skinIndex', skinIndices.copyVector4sArray( geometry.skinIndices ) ); + // now apply vector to vertex buffer - } + vertices.push( vector.x, vector.y, vector.z ); - if ( geometry.skinWeights.length > 0 ) { + // set values to correct vector component - var skinWeights = new Float32BufferAttribute( geometry.skinWeights.length * 4, 4 ); - this.addAttribute( 'skinWeight', skinWeights.copyVector4sArray( geometry.skinWeights ) ); + vector[ u ] = 0; + vector[ v ] = 0; + vector[ w ] = depth > 0 ? 1 : - 1; - } + // now apply vector to normal buffer - // + normals.push( vector.x, vector.y, vector.z ); - if ( geometry.boundingSphere !== null ) { + // uvs - this.boundingSphere = geometry.boundingSphere.clone(); + uvs.push( ix / gridX ); + uvs.push( 1 - ( iy / gridY ) ); - } + // counters - if ( geometry.boundingBox !== null ) { + vertexCounter += 1; - this.boundingBox = geometry.boundingBox.clone(); + } } - return this; - - }, + // indices - computeBoundingBox: function () { + // 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 - if ( this.boundingBox === null ) { + for ( iy = 0; iy < gridY; iy ++ ) { - this.boundingBox = new Box3(); + for ( ix = 0; ix < gridX; ix ++ ) { - } + 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; - var position = this.attributes.position; + // faces - if ( position !== undefined ) { + indices.push( a, b, d ); + indices.push( b, c, d ); - this.boundingBox.setFromBufferAttribute( position ); + // increase counter - } else { + groupCount += 6; - this.boundingBox.makeEmpty(); + } } - if ( isNaN( this.boundingBox.min.x ) || isNaN( this.boundingBox.min.y ) || isNaN( this.boundingBox.min.z ) ) { - - console.error( 'THREE.BufferGeometry.computeBoundingBox: Computed min/max have NaN values. The "position" attribute is likely to have NaN values.', this ); + // add a group to the geometry. this will ensure multi material support - } + scope.addGroup( groupStart, groupCount, materialIndex ); - }, + // calculate new start value for groups - computeBoundingSphere: function () { + groupStart += groupCount; - var box = new Box3(); - var vector = new Vector3(); + // update total number of vertices - return function computeBoundingSphere() { + numberOfVertices += vertexCounter; - if ( this.boundingSphere === null ) { + } - this.boundingSphere = new Sphere(); +} - } +BoxBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); +BoxBufferGeometry.prototype.constructor = BoxBufferGeometry; - var position = this.attributes.position; +/** + * @author mrdoob / http://mrdoob.com/ + * @author Mugen87 / https://github.com/Mugen87 + */ - if ( position ) { +// PlaneGeometry - var center = this.boundingSphere.center; +function PlaneGeometry( width, height, widthSegments, heightSegments ) { - box.setFromBufferAttribute( position ); - box.getCenter( center ); + Geometry.call( this ); - // hoping to find a boundingSphere with a radius smaller than the - // boundingSphere of the boundingBox: sqrt(3) smaller in the best case + this.type = 'PlaneGeometry'; - var maxRadiusSq = 0; + this.parameters = { + width: width, + height: height, + widthSegments: widthSegments, + heightSegments: heightSegments + }; - for ( var i = 0, il = position.count; i < il; i ++ ) { + this.fromBufferGeometry( new PlaneBufferGeometry( width, height, widthSegments, heightSegments ) ); + this.mergeVertices(); - vector.x = position.getX( i ); - vector.y = position.getY( i ); - vector.z = position.getZ( i ); - maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( vector ) ); +} - } +PlaneGeometry.prototype = Object.create( Geometry.prototype ); +PlaneGeometry.prototype.constructor = PlaneGeometry; - this.boundingSphere.radius = Math.sqrt( maxRadiusSq ); +// PlaneBufferGeometry - if ( isNaN( this.boundingSphere.radius ) ) { +function PlaneBufferGeometry( width, height, widthSegments, heightSegments ) { - console.error( 'THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The "position" attribute is likely to have NaN values.', this ); + BufferGeometry.call( this ); - } + this.type = 'PlaneBufferGeometry'; - } + this.parameters = { + width: width, + height: height, + widthSegments: widthSegments, + heightSegments: heightSegments + }; - }; + var width_half = width / 2; + var height_half = height / 2; - }(), + var gridX = Math.floor( widthSegments ) || 1; + var gridY = Math.floor( heightSegments ) || 1; - computeFaceNormals: function () { + var gridX1 = gridX + 1; + var gridY1 = gridY + 1; - // backwards compatibility + var segment_width = width / gridX; + var segment_height = height / gridY; - }, + var ix, iy; - computeVertexNormals: function () { + // buffers - var index = this.index; - var attributes = this.attributes; - var groups = this.groups; + var indices = []; + var vertices = []; + var normals = []; + var uvs = []; - if ( attributes.position ) { + // generate vertices, normals and uvs - var positions = attributes.position.array; + for ( iy = 0; iy < gridY1; iy ++ ) { - if ( attributes.normal === undefined ) { + var y = iy * segment_height - height_half; - this.addAttribute( 'normal', new BufferAttribute( new Float32Array( positions.length ), 3 ) ); + for ( ix = 0; ix < gridX1; ix ++ ) { - } else { + var x = ix * segment_width - width_half; - // reset existing normals to zero + vertices.push( x, - y, 0 ); - var array = attributes.normal.array; + normals.push( 0, 0, 1 ); - for ( var i = 0, il = array.length; i < il; i ++ ) { + uvs.push( ix / gridX ); + uvs.push( 1 - ( iy / gridY ) ); - array[ i ] = 0; + } - } + } - } + // indices - var normals = attributes.normal.array; + for ( iy = 0; iy < gridY; iy ++ ) { - var vA, vB, vC; - var pA = new Vector3(), pB = new Vector3(), pC = new Vector3(); - var cb = new Vector3(), ab = new Vector3(); + for ( ix = 0; ix < gridX; ix ++ ) { - // indexed elements + var a = ix + gridX1 * iy; + var b = ix + gridX1 * ( iy + 1 ); + var c = ( ix + 1 ) + gridX1 * ( iy + 1 ); + var d = ( ix + 1 ) + gridX1 * iy; - if ( index ) { + // faces - var indices = index.array; + indices.push( a, b, d ); + indices.push( b, c, d ); - if ( groups.length === 0 ) { + } - this.addGroup( 0, indices.length ); + } - } + // build geometry - for ( var j = 0, jl = groups.length; j < jl; ++ j ) { + this.setIndex( indices ); + this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); + this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); + this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); - var group = groups[ j ]; +} - var start = group.start; - var count = group.count; +PlaneBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); +PlaneBufferGeometry.prototype.constructor = PlaneBufferGeometry; - for ( var i = start, il = start + count; i < il; i += 3 ) { +/** + * @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.TextureCube( [posx, negx, posy, negy, posz, negz] ), + * combine: THREE.Multiply, + * reflectivity: , + * refractionRatio: , + * + * depthTest: , + * depthWrite: , + * + * wireframe: , + * wireframeLinewidth: , + * + * skinning: , + * morphTargets: + * } + */ - vA = indices[ i + 0 ] * 3; - vB = indices[ i + 1 ] * 3; - vC = indices[ i + 2 ] * 3; +function MeshBasicMaterial( parameters ) { - pA.fromArray( positions, vA ); - pB.fromArray( positions, vB ); - pC.fromArray( positions, vC ); + Material.call( this ); - cb.subVectors( pC, pB ); - ab.subVectors( pA, pB ); - cb.cross( ab ); + this.type = 'MeshBasicMaterial'; - normals[ vA ] += cb.x; - normals[ vA + 1 ] += cb.y; - normals[ vA + 2 ] += cb.z; + this.color = new Color( 0xffffff ); // emissive - normals[ vB ] += cb.x; - normals[ vB + 1 ] += cb.y; - normals[ vB + 2 ] += cb.z; + this.map = null; - normals[ vC ] += cb.x; - normals[ vC + 1 ] += cb.y; - normals[ vC + 2 ] += cb.z; + this.lightMap = null; + this.lightMapIntensity = 1.0; - } + this.aoMap = null; + this.aoMapIntensity = 1.0; - } + this.specularMap = null; - } else { + this.alphaMap = null; - // non-indexed elements (unconnected triangle soup) + this.envMap = null; + this.combine = MultiplyOperation; + this.reflectivity = 1; + this.refractionRatio = 0.98; - for ( var i = 0, il = positions.length; i < il; i += 9 ) { + this.wireframe = false; + this.wireframeLinewidth = 1; + this.wireframeLinecap = 'round'; + this.wireframeLinejoin = 'round'; - pA.fromArray( positions, i ); - pB.fromArray( positions, i + 3 ); - pC.fromArray( positions, i + 6 ); + this.skinning = false; + this.morphTargets = false; - cb.subVectors( pC, pB ); - ab.subVectors( pA, pB ); - cb.cross( ab ); + this.lights = false; - normals[ i ] = cb.x; - normals[ i + 1 ] = cb.y; - normals[ i + 2 ] = cb.z; + this.setValues( parameters ); - normals[ i + 3 ] = cb.x; - normals[ i + 4 ] = cb.y; - normals[ i + 5 ] = cb.z; +} - normals[ i + 6 ] = cb.x; - normals[ i + 7 ] = cb.y; - normals[ i + 8 ] = cb.z; +MeshBasicMaterial.prototype = Object.create( Material.prototype ); +MeshBasicMaterial.prototype.constructor = MeshBasicMaterial; - } +MeshBasicMaterial.prototype.isMeshBasicMaterial = true; - } +MeshBasicMaterial.prototype.copy = function ( source ) { - this.normalizeNormals(); + Material.prototype.copy.call( this, source ); - attributes.normal.needsUpdate = true; + this.color.copy( source.color ); - } + this.map = source.map; - }, + this.lightMap = source.lightMap; + this.lightMapIntensity = source.lightMapIntensity; - merge: function ( geometry, offset ) { + this.aoMap = source.aoMap; + this.aoMapIntensity = source.aoMapIntensity; - if ( ( geometry && geometry.isBufferGeometry ) === false ) { + this.specularMap = source.specularMap; - console.error( 'THREE.BufferGeometry.merge(): geometry not an instance of THREE.BufferGeometry.', geometry ); - return; + this.alphaMap = source.alphaMap; - } + this.envMap = source.envMap; + this.combine = source.combine; + this.reflectivity = source.reflectivity; + this.refractionRatio = source.refractionRatio; - if ( offset === undefined ) offset = 0; + this.wireframe = source.wireframe; + this.wireframeLinewidth = source.wireframeLinewidth; + this.wireframeLinecap = source.wireframeLinecap; + this.wireframeLinejoin = source.wireframeLinejoin; - var attributes = this.attributes; + this.skinning = source.skinning; + this.morphTargets = source.morphTargets; - for ( var key in attributes ) { + return this; - if ( geometry.attributes[ key ] === undefined ) continue; +}; - var attribute1 = attributes[ key ]; - var attributeArray1 = attribute1.array; +/** + * @author bhouston / http://clara.io + */ - var attribute2 = geometry.attributes[ key ]; - var attributeArray2 = attribute2.array; +function Ray( origin, direction ) { - var attributeSize = attribute2.itemSize; + this.origin = ( origin !== undefined ) ? origin : new Vector3(); + this.direction = ( direction !== undefined ) ? direction : new Vector3(); - for ( var i = 0, j = attributeSize * offset; i < attributeArray2.length; i ++, j ++ ) { +} - attributeArray1[ j ] = attributeArray2[ i ]; +Object.assign( Ray.prototype, { - } + set: function ( origin, direction ) { - } + this.origin.copy( origin ); + this.direction.copy( direction ); return this; }, - normalizeNormals: function () { - - var normals = this.attributes.normal; - - var x, y, z, n; + clone: function () { - for ( var i = 0, il = normals.count; i < il; i ++ ) { + return new this.constructor().copy( this ); - x = normals.getX( i ); - y = normals.getY( i ); - z = normals.getZ( i ); + }, - n = 1.0 / Math.sqrt( x * x + y * y + z * z ); + copy: function ( ray ) { - normals.setXYZ( i, x * n, y * n, z * n ); + this.origin.copy( ray.origin ); + this.direction.copy( ray.direction ); - } + return this; }, - toNonIndexed: function () { + at: function ( t, optionalTarget ) { - if ( this.index === null ) { + var result = optionalTarget || new Vector3(); - console.warn( 'THREE.BufferGeometry.toNonIndexed(): Geometry is already non-indexed.' ); - return this; + return result.copy( this.direction ).multiplyScalar( t ).add( this.origin ); - } + }, - var geometry2 = new BufferGeometry(); + lookAt: function ( v ) { - var indices = this.index.array; - var attributes = this.attributes; + this.direction.copy( v ).sub( this.origin ).normalize(); - for ( var name in attributes ) { + return this; - var attribute = attributes[ name ]; + }, - var array = attribute.array; - var itemSize = attribute.itemSize; + recast: function () { - var array2 = new array.constructor( indices.length * itemSize ); + var v1 = new Vector3(); - var index = 0, index2 = 0; + return function recast( t ) { - for ( var i = 0, l = indices.length; i < l; i ++ ) { + this.origin.copy( this.at( t, v1 ) ); - index = indices[ i ] * itemSize; + return this; - for ( var j = 0; j < itemSize; j ++ ) { + }; - array2[ index2 ++ ] = array[ index ++ ]; + }(), - } + closestPointToPoint: function ( point, optionalTarget ) { - } + var result = optionalTarget || new Vector3(); + result.subVectors( point, this.origin ); + var directionDistance = result.dot( this.direction ); - geometry2.addAttribute( name, new BufferAttribute( array2, itemSize ) ); + if ( directionDistance < 0 ) { + + return result.copy( this.origin ); } - return geometry2; + return result.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin ); }, - toJSON: function () { + distanceToPoint: function ( point ) { - var data = { - metadata: { - version: 4.5, - type: 'BufferGeometry', - generator: 'BufferGeometry.toJSON' - } - }; + return Math.sqrt( this.distanceSqToPoint( point ) ); - // standard BufferGeometry serialization + }, - data.uuid = this.uuid; - data.type = this.type; - if ( this.name !== '' ) data.name = this.name; + distanceSqToPoint: function () { - if ( this.parameters !== undefined ) { + var v1 = new Vector3(); - var parameters = this.parameters; + return function distanceSqToPoint( point ) { - for ( var key in parameters ) { + var directionDistance = v1.subVectors( point, this.origin ).dot( this.direction ); - if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ]; + // point behind the ray - } + if ( directionDistance < 0 ) { - return data; + return this.origin.distanceToSquared( point ); - } + } - data.data = { attributes: {} }; + v1.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin ); - var index = this.index; + return v1.distanceToSquared( point ); - if ( index !== null ) { + }; - var array = Array.prototype.slice.call( index.array ); + }(), - data.data.index = { - type: index.array.constructor.name, - array: array - }; + distanceSqToSegment: function () { - } + var segCenter = new Vector3(); + var segDir = new Vector3(); + var diff = new Vector3(); - var attributes = this.attributes; + return function distanceSqToSegment( v0, v1, optionalPointOnRay, optionalPointOnSegment ) { - for ( var key in attributes ) { + // 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 - var attribute = attributes[ key ]; + segCenter.copy( v0 ).add( v1 ).multiplyScalar( 0.5 ); + segDir.copy( v1 ).sub( v0 ).normalize(); + diff.copy( this.origin ).sub( segCenter ); - var array = Array.prototype.slice.call( attribute.array ); + 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; - data.data.attributes[ key ] = { - itemSize: attribute.itemSize, - type: attribute.array.constructor.name, - array: array, - normalized: attribute.normalized - }; + if ( det > 0 ) { - } + // The ray and segment are not parallel. - var groups = this.groups; + s0 = a01 * b1 - b0; + s1 = a01 * b0 - b1; + extDet = segExtent * det; + + if ( s0 >= 0 ) { - if ( groups.length > 0 ) { + if ( s1 >= - extDet ) { - data.data.groups = JSON.parse( JSON.stringify( groups ) ); + if ( s1 <= extDet ) { - } + // region 0 + // Minimum at interior points of ray and segment. - var boundingSphere = this.boundingSphere; + var invDet = 1 / det; + s0 *= invDet; + s1 *= invDet; + sqrDist = s0 * ( s0 + a01 * s1 + 2 * b0 ) + s1 * ( a01 * s0 + s1 + 2 * b1 ) + c; - if ( boundingSphere !== null ) { + } else { - data.data.boundingSphere = { - center: boundingSphere.center.toArray(), - radius: boundingSphere.radius - }; + // region 1 - } + s1 = segExtent; + s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); + sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; - return data; + } - }, + } else { - clone: function () { + // region 5 - /* - // Handle primitives + s1 = - segExtent; + s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); + sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; - var parameters = this.parameters; + } - if ( parameters !== undefined ) { + } else { - var values = []; + if ( s1 <= - extDet ) { - for ( var key in parameters ) { + // region 4 - values.push( parameters[ key ] ); + 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; - } + } else if ( s1 <= extDet ) { - var geometry = Object.create( this.constructor.prototype ); - this.constructor.apply( geometry, values ); - return geometry; + // region 3 - } + s0 = 0; + s1 = Math.min( Math.max( - segExtent, - b1 ), segExtent ); + sqrDist = s1 * ( s1 + 2 * b1 ) + c; - return new this.constructor().copy( this ); - */ + } else { - return new BufferGeometry().copy( this ); + // 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; - copy: function ( source ) { + } - var name, i, l; + } - // reset + } else { - this.index = null; - this.attributes = {}; - this.morphAttributes = {}; - this.groups = []; - this.boundingBox = null; - this.boundingSphere = null; + // Ray and segment are parallel. - // name + s1 = ( a01 > 0 ) ? - segExtent : segExtent; + s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); + sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; - this.name = source.name; + } - // index + if ( optionalPointOnRay ) { - var index = source.index; + optionalPointOnRay.copy( this.direction ).multiplyScalar( s0 ).add( this.origin ); - if ( index !== null ) { + } - this.setIndex( index.clone() ); + if ( optionalPointOnSegment ) { - } + optionalPointOnSegment.copy( segDir ).multiplyScalar( s1 ).add( segCenter ); - // attributes + } - var attributes = source.attributes; + return sqrDist; - for ( name in attributes ) { + }; - var attribute = attributes[ name ]; - this.addAttribute( name, attribute.clone() ); + }(), - } + intersectSphere: function () { - // morph attributes + var v1 = new Vector3(); - var morphAttributes = source.morphAttributes; + return function intersectSphere( sphere, optionalTarget ) { - for ( name in morphAttributes ) { + v1.subVectors( sphere.center, this.origin ); + var tca = v1.dot( this.direction ); + var d2 = v1.dot( v1 ) - tca * tca; + var radius2 = sphere.radius * sphere.radius; - var array = []; - var morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes + if ( d2 > radius2 ) return null; - for ( i = 0, l = morphAttribute.length; i < l; i ++ ) { + var thc = Math.sqrt( radius2 - d2 ); - array.push( morphAttribute[ i ].clone() ); + // t0 = first intersect point - entrance on front of sphere + var t0 = tca - thc; - } + // t1 = second intersect point - exit point on back of sphere + var t1 = tca + thc; - this.morphAttributes[ name ] = array; + // 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, optionalTarget ); - // groups + // else t0 is in front of the ray, so return the first collision point scaled by t0 + return this.at( t0, optionalTarget ); - var groups = source.groups; + }; - for ( i = 0, l = groups.length; i < l; i ++ ) { + }(), - var group = groups[ i ]; - this.addGroup( group.start, group.count, group.materialIndex ); + intersectsSphere: function ( sphere ) { - } + return this.distanceToPoint( sphere.center ) <= sphere.radius; - // bounding box + }, - var boundingBox = source.boundingBox; + distanceToPlane: function ( plane ) { - if ( boundingBox !== null ) { + var denominator = plane.normal.dot( this.direction ); - this.boundingBox = boundingBox.clone(); + if ( denominator === 0 ) { - } + // line is coplanar, return origin + if ( plane.distanceToPoint( this.origin ) === 0 ) { - // bounding sphere + return 0; - var boundingSphere = source.boundingSphere; + } - if ( boundingSphere !== null ) { + // Null is preferable to undefined since undefined means.... it is undefined - this.boundingSphere = boundingSphere.clone(); + return null; } - // draw range + var t = - ( this.origin.dot( plane.normal ) + plane.constant ) / denominator; - this.drawRange.start = source.drawRange.start; - this.drawRange.count = source.drawRange.count; + // Return if the ray never intersects the plane - return this; + return t >= 0 ? t : null; }, - dispose: function () { - - this.dispatchEvent( { type: 'dispose' } ); - - } - -} ); + intersectPlane: function ( plane, optionalTarget ) { -/** - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - * @author mikael emtinger / http://gomo.se/ - * @author jonobr1 / http://jonobr1.com/ - */ + var t = this.distanceToPlane( plane ); -function Mesh( geometry, material ) { + if ( t === null ) { - Object3D.call( this ); + return null; - this.type = 'Mesh'; + } - this.geometry = geometry !== undefined ? geometry : new BufferGeometry(); - this.material = material !== undefined ? material : new MeshBasicMaterial( { color: Math.random() * 0xffffff } ); + return this.at( t, optionalTarget ); - this.drawMode = TrianglesDrawMode; + }, - this.updateMorphTargets(); + intersectsPlane: function ( plane ) { -} + // check if the ray lies on the plane first -Mesh.prototype = Object.assign( Object.create( Object3D.prototype ), { + var distToPoint = plane.distanceToPoint( this.origin ); - constructor: Mesh, + if ( distToPoint === 0 ) { - isMesh: true, + return true; - setDrawMode: function ( value ) { + } - this.drawMode = value; + var denominator = plane.normal.dot( this.direction ); - }, + if ( denominator * distToPoint < 0 ) { - copy: function ( source ) { + return true; - Object3D.prototype.copy.call( this, source ); + } - this.drawMode = source.drawMode; + // ray origin is behind the plane (and is pointing behind it) - return this; + return false; }, - updateMorphTargets: function () { - - var geometry = this.geometry; - var m, ml, name; + intersectBox: function ( box, optionalTarget ) { - if ( geometry.isBufferGeometry ) { + var tmin, tmax, tymin, tymax, tzmin, tzmax; - var morphAttributes = geometry.morphAttributes; - var keys = Object.keys( morphAttributes ); + var invdirx = 1 / this.direction.x, + invdiry = 1 / this.direction.y, + invdirz = 1 / this.direction.z; - if ( keys.length > 0 ) { + var origin = this.origin; - var morphAttribute = morphAttributes[ keys[ 0 ] ]; + if ( invdirx >= 0 ) { - if ( morphAttribute !== undefined ) { + tmin = ( box.min.x - origin.x ) * invdirx; + tmax = ( box.max.x - origin.x ) * invdirx; - this.morphTargetInfluences = []; - this.morphTargetDictionary = {}; + } else { - for ( m = 0, ml = morphAttribute.length; m < ml; m ++ ) { + tmin = ( box.max.x - origin.x ) * invdirx; + tmax = ( box.min.x - origin.x ) * invdirx; - name = morphAttribute[ m ].name || String( m ); + } - this.morphTargetInfluences.push( 0 ); - this.morphTargetDictionary[ name ] = m; + if ( invdiry >= 0 ) { - } + tymin = ( box.min.y - origin.y ) * invdiry; + tymax = ( box.max.y - origin.y ) * invdiry; - } + } else { - } + tymin = ( box.max.y - origin.y ) * invdiry; + tymax = ( box.min.y - origin.y ) * invdiry; - } else { + } - var morphTargets = geometry.morphTargets; + if ( ( tmin > tymax ) || ( tymin > tmax ) ) return null; - if ( morphTargets !== undefined && morphTargets.length > 0 ) { + // These lines also handle the case where tmin or tmax is NaN + // (result of 0 * Infinity). x !== x returns true if x is NaN - this.morphTargetInfluences = []; - this.morphTargetDictionary = {}; + if ( tymin > tmin || tmin !== tmin ) tmin = tymin; - for ( m = 0, ml = morphTargets.length; m < ml; m ++ ) { + if ( tymax < tmax || tmax !== tmax ) tmax = tymax; - name = morphTargets[ m ].name || String( m ); + if ( invdirz >= 0 ) { - this.morphTargetInfluences.push( 0 ); - this.morphTargetDictionary[ name ] = m; + 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; } - }, + if ( ( tmin > tzmax ) || ( tzmin > tmax ) ) return null; - raycast: ( function () { + if ( tzmin > tmin || tmin !== tmin ) tmin = tzmin; - var inverseMatrix = new Matrix4(); - var ray = new Ray(); - var sphere = new Sphere(); + if ( tzmax < tmax || tmax !== tmax ) tmax = tzmax; - var vA = new Vector3(); - var vB = new Vector3(); - var vC = new Vector3(); + //return point closest to the ray (positive side) - var tempA = new Vector3(); - var tempB = new Vector3(); - var tempC = new Vector3(); + if ( tmax < 0 ) return null; - var uvA = new Vector2(); - var uvB = new Vector2(); - var uvC = new Vector2(); + return this.at( tmin >= 0 ? tmin : tmax, optionalTarget ); - var barycoord = new Vector3(); + }, - var intersectionPoint = new Vector3(); - var intersectionPointWorld = new Vector3(); + intersectsBox: ( function () { - function uvIntersection( point, p1, p2, p3, uv1, uv2, uv3 ) { + var v = new Vector3(); - Triangle.barycoordFromPoint( point, p1, p2, p3, barycoord ); + return function intersectsBox( box ) { - uv1.multiplyScalar( barycoord.x ); - uv2.multiplyScalar( barycoord.y ); - uv3.multiplyScalar( barycoord.z ); + return this.intersectBox( box, v ) !== null; - uv1.add( uv2 ).add( uv3 ); + }; - return uv1.clone(); + } )(), - } + intersectTriangle: function () { - function checkIntersection( object, raycaster, ray, pA, pB, pC, point ) { + // Compute the offset origin, edges, and normal. + var diff = new Vector3(); + var edge1 = new Vector3(); + var edge2 = new Vector3(); + var normal = new Vector3(); - var intersect; - var material = object.material; + return function intersectTriangle( a, b, c, backfaceCulling, optionalTarget ) { - if ( material.side === BackSide ) { + // from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteIntrRay3Triangle3.h - intersect = ray.intersectTriangle( pC, pB, pA, true, point ); + edge1.subVectors( b, a ); + edge2.subVectors( c, a ); + normal.crossVectors( edge1, edge2 ); - } else { + // 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; - intersect = ray.intersectTriangle( pA, pB, pC, material.side !== DoubleSide, point ); + if ( DdN > 0 ) { - } + if ( backfaceCulling ) return null; + sign = 1; - if ( intersect === null ) return null; + } else if ( DdN < 0 ) { - intersectionPointWorld.copy( point ); - intersectionPointWorld.applyMatrix4( object.matrixWorld ); + sign = - 1; + DdN = - DdN; - var distance = raycaster.ray.origin.distanceTo( intersectionPointWorld ); + } else { - if ( distance < raycaster.near || distance > raycaster.far ) return null; + return null; - return { - distance: distance, - point: intersectionPointWorld.clone(), - object: object - }; + } - } + diff.subVectors( this.origin, a ); + var DdQxE2 = sign * this.direction.dot( edge2.crossVectors( diff, edge2 ) ); - function checkBufferGeometryIntersection( object, raycaster, ray, position, uv, a, b, c ) { + // b1 < 0, no intersection + if ( DdQxE2 < 0 ) { - vA.fromBufferAttribute( position, a ); - vB.fromBufferAttribute( position, b ); - vC.fromBufferAttribute( position, c ); + return null; - var intersection = checkIntersection( object, raycaster, ray, vA, vB, vC, intersectionPoint ); + } - if ( intersection ) { + var DdE1xQ = sign * this.direction.dot( edge1.cross( diff ) ); - if ( uv ) { + // b2 < 0, no intersection + if ( DdE1xQ < 0 ) { - uvA.fromBufferAttribute( uv, a ); - uvB.fromBufferAttribute( uv, b ); - uvC.fromBufferAttribute( uv, c ); + return null; - intersection.uv = uvIntersection( intersectionPoint, vA, vB, vC, uvA, uvB, uvC ); + } - } + // b1+b2 > 1, no intersection + if ( DdQxE2 + DdE1xQ > DdN ) { - intersection.face = new Face3( a, b, c, Triangle.normal( vA, vB, vC ) ); - intersection.faceIndex = a; + return null; } - return intersection; - - } + // Line intersects triangle, check if ray does. + var QdN = - sign * diff.dot( normal ); - return function raycast( raycaster, intersects ) { + // t < 0, no intersection + if ( QdN < 0 ) { - var geometry = this.geometry; - var material = this.material; - var matrixWorld = this.matrixWorld; + return null; - if ( material === undefined ) return; + } - // Checking boundingSphere distance to ray + // Ray intersects triangle. + return this.at( QdN / DdN, optionalTarget ); - if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); + }; - sphere.copy( geometry.boundingSphere ); - sphere.applyMatrix4( matrixWorld ); + }(), - if ( raycaster.ray.intersectsSphere( sphere ) === false ) return; + applyMatrix4: function ( matrix4 ) { - // + this.origin.applyMatrix4( matrix4 ); + this.direction.transformDirection( matrix4 ); - inverseMatrix.getInverse( matrixWorld ); - ray.copy( raycaster.ray ).applyMatrix4( inverseMatrix ); + return this; - // Check boundingBox before continuing + }, - if ( geometry.boundingBox !== null ) { + equals: function ( ray ) { - if ( ray.intersectsBox( geometry.boundingBox ) === false ) return; + return ray.origin.equals( this.origin ) && ray.direction.equals( this.direction ); - } + } - var intersection; +} ); - if ( geometry.isBufferGeometry ) { +/** + * @author bhouston / http://clara.io + */ - var a, b, c; - var index = geometry.index; - var position = geometry.attributes.position; - var uv = geometry.attributes.uv; - var i, l; +function Line3( start, end ) { - if ( index !== null ) { + this.start = ( start !== undefined ) ? start : new Vector3(); + this.end = ( end !== undefined ) ? end : new Vector3(); - // indexed buffer geometry +} - for ( i = 0, l = index.count; i < l; i += 3 ) { +Object.assign( Line3.prototype, { - a = index.getX( i ); - b = index.getX( i + 1 ); - c = index.getX( i + 2 ); + set: function ( start, end ) { - intersection = checkBufferGeometryIntersection( this, raycaster, ray, position, uv, a, b, c ); + this.start.copy( start ); + this.end.copy( end ); - if ( intersection ) { + return this; - intersection.faceIndex = Math.floor( i / 3 ); // triangle number in indices buffer semantics - intersects.push( intersection ); + }, - } + clone: function () { - } + return new this.constructor().copy( this ); - } else { + }, - // non-indexed buffer geometry + copy: function ( line ) { - for ( i = 0, l = position.count; i < l; i += 3 ) { + this.start.copy( line.start ); + this.end.copy( line.end ); - a = i; - b = i + 1; - c = i + 2; + return this; - intersection = checkBufferGeometryIntersection( this, raycaster, ray, position, uv, a, b, c ); + }, - if ( intersection ) { + getCenter: function ( optionalTarget ) { - intersection.index = a; // triangle number in positions buffer semantics - intersects.push( intersection ); + var result = optionalTarget || new Vector3(); + return result.addVectors( this.start, this.end ).multiplyScalar( 0.5 ); - } + }, - } + delta: function ( optionalTarget ) { - } + var result = optionalTarget || new Vector3(); + return result.subVectors( this.end, this.start ); - } else if ( geometry.isGeometry ) { + }, - var fvA, fvB, fvC; - var isMultiMaterial = Array.isArray( material ); + distanceSq: function () { - var vertices = geometry.vertices; - var faces = geometry.faces; - var uvs; + return this.start.distanceToSquared( this.end ); - var faceVertexUvs = geometry.faceVertexUvs[ 0 ]; - if ( faceVertexUvs.length > 0 ) uvs = faceVertexUvs; + }, - for ( var f = 0, fl = faces.length; f < fl; f ++ ) { + distance: function () { - var face = faces[ f ]; - var faceMaterial = isMultiMaterial ? material[ face.materialIndex ] : material; + return this.start.distanceTo( this.end ); - if ( faceMaterial === undefined ) continue; + }, - fvA = vertices[ face.a ]; - fvB = vertices[ face.b ]; - fvC = vertices[ face.c ]; + at: function ( t, optionalTarget ) { - if ( faceMaterial.morphTargets === true ) { + var result = optionalTarget || new Vector3(); - var morphTargets = geometry.morphTargets; - var morphInfluences = this.morphTargetInfluences; + return this.delta( result ).multiplyScalar( t ).add( this.start ); - vA.set( 0, 0, 0 ); - vB.set( 0, 0, 0 ); - vC.set( 0, 0, 0 ); + }, - for ( var t = 0, tl = morphTargets.length; t < tl; t ++ ) { + closestPointToPointParameter: function () { - var influence = morphInfluences[ t ]; + var startP = new Vector3(); + var startEnd = new Vector3(); - if ( influence === 0 ) continue; + return function closestPointToPointParameter( point, clampToLine ) { - var targets = morphTargets[ t ].vertices; + startP.subVectors( point, this.start ); + startEnd.subVectors( this.end, this.start ); - vA.addScaledVector( tempA.subVectors( targets[ face.a ], fvA ), influence ); - vB.addScaledVector( tempB.subVectors( targets[ face.b ], fvB ), influence ); - vC.addScaledVector( tempC.subVectors( targets[ face.c ], fvC ), influence ); + var startEnd2 = startEnd.dot( startEnd ); + var startEnd_startP = startEnd.dot( startP ); - } + var t = startEnd_startP / startEnd2; - vA.add( fvA ); - vB.add( fvB ); - vC.add( fvC ); + if ( clampToLine ) { - fvA = vA; - fvB = vB; - fvC = vC; + t = _Math.clamp( t, 0, 1 ); - } + } - intersection = checkIntersection( this, raycaster, ray, fvA, fvB, fvC, intersectionPoint ); + return t; - if ( intersection ) { + }; - if ( uvs && uvs[ f ] ) { + }(), - var uvs_f = uvs[ f ]; - uvA.copy( uvs_f[ 0 ] ); - uvB.copy( uvs_f[ 1 ] ); - uvC.copy( uvs_f[ 2 ] ); + closestPointToPoint: function ( point, clampToLine, optionalTarget ) { - intersection.uv = uvIntersection( intersectionPoint, fvA, fvB, fvC, uvA, uvB, uvC ); + var t = this.closestPointToPointParameter( point, clampToLine ); - } + var result = optionalTarget || new Vector3(); - intersection.face = face; - intersection.faceIndex = f; - intersects.push( intersection ); + return this.delta( result ).multiplyScalar( t ).add( this.start ); - } + }, - } + applyMatrix4: function ( matrix ) { - } + this.start.applyMatrix4( matrix ); + this.end.applyMatrix4( matrix ); - }; + return this; - }() ), + }, - clone: function () { + equals: function ( line ) { - return new this.constructor( this.geometry, this.material ).copy( this ); + return line.start.equals( this.start ) && line.end.equals( this.end ); } } ); /** + * @author bhouston / http://clara.io * @author mrdoob / http://mrdoob.com/ - * @author Mugen87 / https://github.com/Mugen87 */ -// BoxGeometry - -function BoxGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) { - - Geometry.call( this ); - - this.type = 'BoxGeometry'; - - this.parameters = { - width: width, - height: height, - depth: depth, - widthSegments: widthSegments, - heightSegments: heightSegments, - depthSegments: depthSegments - }; +function Triangle( a, b, c ) { - this.fromBufferGeometry( new BoxBufferGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) ); - this.mergeVertices(); + this.a = ( a !== undefined ) ? a : new Vector3(); + this.b = ( b !== undefined ) ? b : new Vector3(); + this.c = ( c !== undefined ) ? c : new Vector3(); } -BoxGeometry.prototype = Object.create( Geometry.prototype ); -BoxGeometry.prototype.constructor = BoxGeometry; - -// BoxBufferGeometry +Object.assign( Triangle, { -function BoxBufferGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) { + normal: function () { - BufferGeometry.call( this ); + var v0 = new Vector3(); - this.type = 'BoxBufferGeometry'; + return function normal( a, b, c, optionalTarget ) { - this.parameters = { - width: width, - height: height, - depth: depth, - widthSegments: widthSegments, - heightSegments: heightSegments, - depthSegments: depthSegments - }; + var result = optionalTarget || new Vector3(); - var scope = this; + result.subVectors( c, b ); + v0.subVectors( a, b ); + result.cross( v0 ); - // segments + var resultLengthSq = result.lengthSq(); + if ( resultLengthSq > 0 ) { - widthSegments = Math.floor( widthSegments ) || 1; - heightSegments = Math.floor( heightSegments ) || 1; - depthSegments = Math.floor( depthSegments ) || 1; + return result.multiplyScalar( 1 / Math.sqrt( resultLengthSq ) ); - // buffers + } - var indices = []; - var vertices = []; - var normals = []; - var uvs = []; + return result.set( 0, 0, 0 ); - // helper variables + }; - var numberOfVertices = 0; - var groupStart = 0; + }(), - // build each side of the box geometry + // static/instance method to calculate barycentric coordinates + // based on: http://www.blackpawn.com/texts/pointinpoly/default.html + barycoordFromPoint: function () { - 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 + var v0 = new Vector3(); + var v1 = new Vector3(); + var v2 = new Vector3(); - // build geometry + return function barycoordFromPoint( point, a, b, c, optionalTarget ) { - this.setIndex( indices ); - this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); + v0.subVectors( c, a ); + v1.subVectors( b, a ); + v2.subVectors( point, a ); - function buildPlane( u, v, w, udir, vdir, width, height, depth, gridX, gridY, materialIndex ) { + var dot00 = v0.dot( v0 ); + var dot01 = v0.dot( v1 ); + var dot02 = v0.dot( v2 ); + var dot11 = v1.dot( v1 ); + var dot12 = v1.dot( v2 ); - var segmentWidth = width / gridX; - var segmentHeight = height / gridY; + var denom = ( dot00 * dot11 - dot01 * dot01 ); - var widthHalf = width / 2; - var heightHalf = height / 2; - var depthHalf = depth / 2; + var result = optionalTarget || new Vector3(); - var gridX1 = gridX + 1; - var gridY1 = gridY + 1; + // collinear or singular triangle + if ( denom === 0 ) { - var vertexCounter = 0; - var groupCount = 0; + // arbitrary location outside of triangle? + // not sure if this is the best idea, maybe should be returning undefined + return result.set( - 2, - 1, - 1 ); - var ix, iy; + } - var vector = new Vector3(); + var invDenom = 1 / denom; + var u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom; + var v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom; - // generate vertices, normals and uvs + // barycentric coordinates must always sum to 1 + return result.set( 1 - u - v, v, u ); - for ( iy = 0; iy < gridY1; iy ++ ) { + }; - var y = iy * segmentHeight - heightHalf; + }(), - for ( ix = 0; ix < gridX1; ix ++ ) { + containsPoint: function () { - var x = ix * segmentWidth - widthHalf; + var v1 = new Vector3(); - // set values to correct vector component + return function containsPoint( point, a, b, c ) { - vector[ u ] = x * udir; - vector[ v ] = y * vdir; - vector[ w ] = depthHalf; + var result = Triangle.barycoordFromPoint( point, a, b, c, v1 ); - // now apply vector to vertex buffer + return ( result.x >= 0 ) && ( result.y >= 0 ) && ( ( result.x + result.y ) <= 1 ); - vertices.push( vector.x, vector.y, vector.z ); + }; - // set values to correct vector component + }() - vector[ u ] = 0; - vector[ v ] = 0; - vector[ w ] = depth > 0 ? 1 : - 1; +} ); - // now apply vector to normal buffer +Object.assign( Triangle.prototype, { - normals.push( vector.x, vector.y, vector.z ); + set: function ( a, b, c ) { - // uvs + this.a.copy( a ); + this.b.copy( b ); + this.c.copy( c ); - uvs.push( ix / gridX ); - uvs.push( 1 - ( iy / gridY ) ); + return this; - // counters + }, - vertexCounter += 1; + setFromPointsAndIndices: function ( points, i0, i1, i2 ) { - } + this.a.copy( points[ i0 ] ); + this.b.copy( points[ i1 ] ); + this.c.copy( points[ i2 ] ); - } + return this; - // 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 + clone: function () { - for ( iy = 0; iy < gridY; iy ++ ) { + return new this.constructor().copy( this ); - for ( ix = 0; ix < gridX; ix ++ ) { + }, - 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; + copy: function ( triangle ) { - // faces + this.a.copy( triangle.a ); + this.b.copy( triangle.b ); + this.c.copy( triangle.c ); - indices.push( a, b, d ); - indices.push( b, c, d ); + return this; - // increase counter + }, - groupCount += 6; + area: function () { - } + var v0 = new Vector3(); + var v1 = new Vector3(); - } + return function area() { - // add a group to the geometry. this will ensure multi material support + v0.subVectors( this.c, this.b ); + v1.subVectors( this.a, this.b ); - scope.addGroup( groupStart, groupCount, materialIndex ); + return v0.cross( v1 ).length() * 0.5; - // calculate new start value for groups + }; - groupStart += groupCount; + }(), - // update total number of vertices + midpoint: function ( optionalTarget ) { - numberOfVertices += vertexCounter; + var result = optionalTarget || new Vector3(); + return result.addVectors( this.a, this.b ).add( this.c ).multiplyScalar( 1 / 3 ); - } + }, -} + normal: function ( optionalTarget ) { -BoxBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); -BoxBufferGeometry.prototype.constructor = BoxBufferGeometry; + return Triangle.normal( this.a, this.b, this.c, optionalTarget ); -/** - * @author mrdoob / http://mrdoob.com/ - * @author Mugen87 / https://github.com/Mugen87 - */ + }, -// PlaneGeometry + plane: function ( optionalTarget ) { -function PlaneGeometry( width, height, widthSegments, heightSegments ) { + var result = optionalTarget || new Plane(); - Geometry.call( this ); + return result.setFromCoplanarPoints( this.a, this.b, this.c ); - this.type = 'PlaneGeometry'; + }, - this.parameters = { - width: width, - height: height, - widthSegments: widthSegments, - heightSegments: heightSegments - }; + barycoordFromPoint: function ( point, optionalTarget ) { - this.fromBufferGeometry( new PlaneBufferGeometry( width, height, widthSegments, heightSegments ) ); - this.mergeVertices(); + return Triangle.barycoordFromPoint( point, this.a, this.b, this.c, optionalTarget ); -} + }, -PlaneGeometry.prototype = Object.create( Geometry.prototype ); -PlaneGeometry.prototype.constructor = PlaneGeometry; + containsPoint: function ( point ) { -// PlaneBufferGeometry + return Triangle.containsPoint( point, this.a, this.b, this.c ); -function PlaneBufferGeometry( width, height, widthSegments, heightSegments ) { + }, - BufferGeometry.call( this ); + closestPointToPoint: function () { - this.type = 'PlaneBufferGeometry'; + var plane = new Plane(); + var edgeList = [ new Line3(), new Line3(), new Line3() ]; + var projectedPoint = new Vector3(); + var closestPoint = new Vector3(); - this.parameters = { - width: width, - height: height, - widthSegments: widthSegments, - heightSegments: heightSegments - }; + return function closestPointToPoint( point, optionalTarget ) { - var width_half = width / 2; - var height_half = height / 2; + var result = optionalTarget || new Vector3(); + var minDistance = Infinity; - var gridX = Math.floor( widthSegments ) || 1; - var gridY = Math.floor( heightSegments ) || 1; + // project the point onto the plane of the triangle - var gridX1 = gridX + 1; - var gridY1 = gridY + 1; + plane.setFromCoplanarPoints( this.a, this.b, this.c ); + plane.projectPoint( point, projectedPoint ); - var segment_width = width / gridX; - var segment_height = height / gridY; + // check if the projection lies within the triangle - var ix, iy; + if( this.containsPoint( projectedPoint ) === true ) { - // buffers + // if so, this is the closest point - var indices = []; - var vertices = []; - var normals = []; - var uvs = []; + result.copy( projectedPoint ); - // generate vertices, normals and uvs + } else { - for ( iy = 0; iy < gridY1; iy ++ ) { + // if not, the point falls outside the triangle. the result is the closest point to the triangle's edges or vertices - var y = iy * segment_height - height_half; + edgeList[ 0 ].set( this.a, this.b ); + edgeList[ 1 ].set( this.b, this.c ); + edgeList[ 2 ].set( this.c, this.a ); - for ( ix = 0; ix < gridX1; ix ++ ) { + for( var i = 0; i < edgeList.length; i ++ ) { - var x = ix * segment_width - width_half; + edgeList[ i ].closestPointToPoint( projectedPoint, true, closestPoint ); - vertices.push( x, - y, 0 ); + var distance = projectedPoint.distanceToSquared( closestPoint ); - normals.push( 0, 0, 1 ); + if( distance < minDistance ) { - uvs.push( ix / gridX ); - uvs.push( 1 - ( iy / gridY ) ); + minDistance = distance; - } + result.copy( closestPoint ); - } + } - // indices + } - for ( iy = 0; iy < gridY; iy ++ ) { + } - for ( ix = 0; ix < gridX; ix ++ ) { + return result; - var a = ix + gridX1 * iy; - var b = ix + gridX1 * ( iy + 1 ); - var c = ( ix + 1 ) + gridX1 * ( iy + 1 ); - var d = ( ix + 1 ) + gridX1 * iy; + }; - // faces + }(), - indices.push( a, b, d ); - indices.push( b, c, d ); + equals: function ( triangle ) { - } + return triangle.a.equals( this.a ) && triangle.b.equals( this.b ) && triangle.c.equals( this.c ); } - // 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 ) ); - -} - -PlaneBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); -PlaneBufferGeometry.prototype.constructor = PlaneBufferGeometry; +} ); /** * @author mrdoob / http://mrdoob.com/ + * @author alteredq / http://alteredqualia.com/ * @author mikael emtinger / http://gomo.se/ - * @author WestLangley / http://github.com/WestLangley -*/ + * @author jonobr1 / http://jonobr1.com/ + */ -function Camera() { +function Mesh( geometry, material ) { Object3D.call( this ); - this.type = 'Camera'; + this.type = 'Mesh'; - this.matrixWorldInverse = new Matrix4(); - this.projectionMatrix = new Matrix4(); + this.geometry = geometry !== undefined ? geometry : new BufferGeometry(); + this.material = material !== undefined ? material : new MeshBasicMaterial( { color: Math.random() * 0xffffff } ); + + this.drawMode = TrianglesDrawMode; + + this.updateMorphTargets(); } -Camera.prototype = Object.assign( Object.create( Object3D.prototype ), { +Mesh.prototype = Object.assign( Object.create( Object3D.prototype ), { - constructor: Camera, + constructor: Mesh, - isCamera: true, + isMesh: true, + + setDrawMode: function ( value ) { + + this.drawMode = value; + + }, copy: function ( source ) { Object3D.prototype.copy.call( this, source ); - this.matrixWorldInverse.copy( source.matrixWorldInverse ); - this.projectionMatrix.copy( source.projectionMatrix ); + this.drawMode = source.drawMode; return this; }, - getWorldDirection: function () { - - var quaternion = new Quaternion(); - - return function getWorldDirection( optionalTarget ) { + updateMorphTargets: function () { - var result = optionalTarget || new Vector3(); + var geometry = this.geometry; + var m, ml, name; - this.getWorldQuaternion( quaternion ); + if ( geometry.isBufferGeometry ) { - return result.set( 0, 0, - 1 ).applyQuaternion( quaternion ); + var morphAttributes = geometry.morphAttributes; + var keys = Object.keys( morphAttributes ); - }; + if ( keys.length > 0 ) { - }(), + var morphAttribute = morphAttributes[ keys[ 0 ] ]; - clone: function () { + if ( morphAttribute !== undefined ) { - return new this.constructor().copy( this ); + this.morphTargetInfluences = []; + this.morphTargetDictionary = {}; - } + for ( m = 0, ml = morphAttribute.length; m < ml; m ++ ) { -} ); + name = morphAttribute[ m ].name || String( m ); -/** - * @author mrdoob / http://mrdoob.com/ - * @author greggman / http://games.greggman.com/ - * @author zz85 / http://www.lab4games.net/zz85/blog - * @author tschw - */ + this.morphTargetInfluences.push( 0 ); + this.morphTargetDictionary[ name ] = m; -function PerspectiveCamera( fov, aspect, near, far ) { + } - Camera.call( this ); + } - this.type = 'PerspectiveCamera'; + } - this.fov = fov !== undefined ? fov : 50; - this.zoom = 1; + } else { - this.near = near !== undefined ? near : 0.1; - this.far = far !== undefined ? far : 2000; - this.focus = 10; + var morphTargets = geometry.morphTargets; - this.aspect = aspect !== undefined ? aspect : 1; - this.view = null; + if ( morphTargets !== undefined && morphTargets.length > 0 ) { - this.filmGauge = 35; // width of the film (default in millimeters) - this.filmOffset = 0; // horizontal film offset (same unit as gauge) + this.morphTargetInfluences = []; + this.morphTargetDictionary = {}; - this.updateProjectionMatrix(); + for ( m = 0, ml = morphTargets.length; m < ml; m ++ ) { -} + name = morphTargets[ m ].name || String( m ); -PerspectiveCamera.prototype = Object.assign( Object.create( Camera.prototype ), { + this.morphTargetInfluences.push( 0 ); + this.morphTargetDictionary[ name ] = m; - constructor: PerspectiveCamera, + } - isPerspectiveCamera: true, + } - copy: function ( source ) { + } - Camera.prototype.copy.call( this, source ); + }, - this.fov = source.fov; - this.zoom = source.zoom; + raycast: ( function () { - this.near = source.near; - this.far = source.far; - this.focus = source.focus; + var inverseMatrix = new Matrix4(); + var ray = new Ray(); + var sphere = new Sphere(); - this.aspect = source.aspect; - this.view = source.view === null ? null : Object.assign( {}, source.view ); + var vA = new Vector3(); + var vB = new Vector3(); + var vC = new Vector3(); - this.filmGauge = source.filmGauge; - this.filmOffset = source.filmOffset; + var tempA = new Vector3(); + var tempB = new Vector3(); + var tempC = new Vector3(); - return this; + var uvA = new Vector2(); + var uvB = new Vector2(); + var uvC = new Vector2(); - }, + var barycoord = new Vector3(); - /** - * 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 ) { + var intersectionPoint = new Vector3(); + var intersectionPointWorld = new Vector3(); - // see http://www.bobatkins.com/photography/technical/field_of_view.html - var vExtentSlope = 0.5 * this.getFilmHeight() / focalLength; + function uvIntersection( point, p1, p2, p3, uv1, uv2, uv3 ) { - this.fov = _Math.RAD2DEG * 2 * Math.atan( vExtentSlope ); - this.updateProjectionMatrix(); + Triangle.barycoordFromPoint( point, p1, p2, p3, barycoord ); - }, + uv1.multiplyScalar( barycoord.x ); + uv2.multiplyScalar( barycoord.y ); + uv3.multiplyScalar( barycoord.z ); - /** - * Calculates the focal length from the current .fov and .filmGauge. - */ - getFocalLength: function () { + uv1.add( uv2 ).add( uv3 ); - var vExtentSlope = Math.tan( _Math.DEG2RAD * 0.5 * this.fov ); + return uv1.clone(); - return 0.5 * this.getFilmHeight() / vExtentSlope; + } - }, + function checkIntersection( object, material, raycaster, ray, pA, pB, pC, point ) { - getEffectiveFOV: function () { + var intersect; - return _Math.RAD2DEG * 2 * Math.atan( - Math.tan( _Math.DEG2RAD * 0.5 * this.fov ) / this.zoom ); + if ( material.side === BackSide ) { - }, + intersect = ray.intersectTriangle( pC, pB, pA, true, point ); - getFilmWidth: function () { + } else { - // film not completely covered in portrait format (aspect < 1) - return this.filmGauge * Math.min( this.aspect, 1 ); + intersect = ray.intersectTriangle( pA, pB, pC, material.side !== DoubleSide, point ); - }, + } - getFilmHeight: function () { + if ( intersect === null ) return null; - // film not completely covered in landscape format (aspect > 1) - return this.filmGauge / Math.max( this.aspect, 1 ); + intersectionPointWorld.copy( point ); + intersectionPointWorld.applyMatrix4( object.matrixWorld ); - }, + var distance = raycaster.ray.origin.distanceTo( intersectionPointWorld ); - /** - * 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.setOffset( fullWidth, fullHeight, w * 0, h * 0, w, h ); - * --B-- - * camera.setOffset( fullWidth, fullHeight, w * 1, h * 0, w, h ); - * --C-- - * camera.setOffset( fullWidth, fullHeight, w * 2, h * 0, w, h ); - * --D-- - * camera.setOffset( fullWidth, fullHeight, w * 0, h * 1, w, h ); - * --E-- - * camera.setOffset( fullWidth, fullHeight, w * 1, h * 1, w, h ); - * --F-- - * camera.setOffset( 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 ) { + if ( distance < raycaster.near || distance > raycaster.far ) return null; - this.aspect = fullWidth / fullHeight; + return { + distance: distance, + point: intersectionPointWorld.clone(), + object: object + }; - this.view = { - fullWidth: fullWidth, - fullHeight: fullHeight, - offsetX: x, - offsetY: y, - width: width, - height: height - }; + } - this.updateProjectionMatrix(); + function checkBufferGeometryIntersection( object, raycaster, ray, position, uv, a, b, c ) { - }, + vA.fromBufferAttribute( position, a ); + vB.fromBufferAttribute( position, b ); + vC.fromBufferAttribute( position, c ); - clearViewOffset: function () { + var intersection = checkIntersection( object, object.material, raycaster, ray, vA, vB, vC, intersectionPoint ); - this.view = null; - this.updateProjectionMatrix(); + if ( intersection ) { - }, + if ( uv ) { - updateProjectionMatrix: function () { + uvA.fromBufferAttribute( uv, a ); + uvB.fromBufferAttribute( uv, b ); + uvC.fromBufferAttribute( uv, c ); - 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; + intersection.uv = uvIntersection( intersectionPoint, vA, vB, vC, uvA, uvB, uvC ); - if ( view !== null ) { + } - var fullWidth = view.fullWidth, - fullHeight = view.fullHeight; + intersection.face = new Face3( a, b, c, Triangle.normal( vA, vB, vC ) ); + intersection.faceIndex = a; - left += view.offsetX * width / fullWidth; - top -= view.offsetY * height / fullHeight; - width *= view.width / fullWidth; - height *= view.height / fullHeight; + } + + return intersection; } - var skew = this.filmOffset; - if ( skew !== 0 ) left += near * skew / this.getFilmWidth(); + return function raycast( raycaster, intersects ) { - this.projectionMatrix.makePerspective( left, left + width, top, top - height, near, this.far ); + var geometry = this.geometry; + var material = this.material; + var matrixWorld = this.matrixWorld; - }, + if ( material === undefined ) return; - toJSON: function ( meta ) { + // Checking boundingSphere distance to ray - var data = Object3D.prototype.toJSON.call( this, meta ); + if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); - data.object.fov = this.fov; - data.object.zoom = this.zoom; + sphere.copy( geometry.boundingSphere ); + sphere.applyMatrix4( matrixWorld ); - data.object.near = this.near; - data.object.far = this.far; - data.object.focus = this.focus; + if ( raycaster.ray.intersectsSphere( sphere ) === false ) return; - data.object.aspect = this.aspect; + // - if ( this.view !== null ) data.object.view = Object.assign( {}, this.view ); + inverseMatrix.getInverse( matrixWorld ); + ray.copy( raycaster.ray ).applyMatrix4( inverseMatrix ); - data.object.filmGauge = this.filmGauge; - data.object.filmOffset = this.filmOffset; + // Check boundingBox before continuing - return data; + if ( geometry.boundingBox !== null ) { - } + if ( ray.intersectsBox( geometry.boundingBox ) === false ) return; -} ); + } -/** - * @author alteredq / http://alteredqualia.com/ - * @author arose / http://github.com/arose - */ + var intersection; -function OrthographicCamera( left, right, top, bottom, near, far ) { + if ( geometry.isBufferGeometry ) { - Camera.call( this ); + var a, b, c; + var index = geometry.index; + var position = geometry.attributes.position; + var uv = geometry.attributes.uv; + var i, l; - this.type = 'OrthographicCamera'; + if ( index !== null ) { - this.zoom = 1; - this.view = null; + // indexed buffer geometry - this.left = left; - this.right = right; - this.top = top; - this.bottom = bottom; + for ( i = 0, l = index.count; i < l; i += 3 ) { - this.near = ( near !== undefined ) ? near : 0.1; - this.far = ( far !== undefined ) ? far : 2000; + a = index.getX( i ); + b = index.getX( i + 1 ); + c = index.getX( i + 2 ); - this.updateProjectionMatrix(); + intersection = checkBufferGeometryIntersection( this, raycaster, ray, position, uv, a, b, c ); -} + if ( intersection ) { -OrthographicCamera.prototype = Object.assign( Object.create( Camera.prototype ), { + intersection.faceIndex = Math.floor( i / 3 ); // triangle number in indices buffer semantics + intersects.push( intersection ); - constructor: OrthographicCamera, + } - isOrthographicCamera: true, + } - copy: function ( source ) { + } else { - Camera.prototype.copy.call( this, source ); + // non-indexed buffer geometry - this.left = source.left; - this.right = source.right; - this.top = source.top; - this.bottom = source.bottom; - this.near = source.near; - this.far = source.far; + for ( i = 0, l = position.count; i < l; i += 3 ) { - this.zoom = source.zoom; - this.view = source.view === null ? null : Object.assign( {}, source.view ); + a = i; + b = i + 1; + c = i + 2; - return this; + intersection = checkBufferGeometryIntersection( this, raycaster, ray, position, uv, a, b, c ); - }, + if ( intersection ) { - setViewOffset: function( fullWidth, fullHeight, x, y, width, height ) { + intersection.index = a; // triangle number in positions buffer semantics + intersects.push( intersection ); - this.view = { - fullWidth: fullWidth, - fullHeight: fullHeight, - offsetX: x, - offsetY: y, - width: width, - height: height - }; + } - this.updateProjectionMatrix(); + } - }, + } - clearViewOffset: function() { + } else if ( geometry.isGeometry ) { - this.view = null; - this.updateProjectionMatrix(); + var fvA, fvB, fvC; + var isMultiMaterial = Array.isArray( material ); - }, + var vertices = geometry.vertices; + var faces = geometry.faces; + var uvs; - updateProjectionMatrix: function () { + var faceVertexUvs = geometry.faceVertexUvs[ 0 ]; + if ( faceVertexUvs.length > 0 ) uvs = faceVertexUvs; - var dx = ( this.right - this.left ) / ( 2 * this.zoom ); - var dy = ( this.top - this.bottom ) / ( 2 * this.zoom ); - var cx = ( this.right + this.left ) / 2; - var cy = ( this.top + this.bottom ) / 2; + for ( var f = 0, fl = faces.length; f < fl; f ++ ) { - var left = cx - dx; - var right = cx + dx; - var top = cy + dy; - var bottom = cy - dy; + var face = faces[ f ]; + var faceMaterial = isMultiMaterial ? material[ face.materialIndex ] : material; - if ( this.view !== null ) { + if ( faceMaterial === undefined ) continue; - var zoomW = this.zoom / ( this.view.width / this.view.fullWidth ); - var zoomH = this.zoom / ( this.view.height / this.view.fullHeight ); - var scaleW = ( this.right - this.left ) / this.view.width; - var scaleH = ( this.top - this.bottom ) / this.view.height; + fvA = vertices[ face.a ]; + fvB = vertices[ face.b ]; + fvC = vertices[ face.c ]; - left += scaleW * ( this.view.offsetX / zoomW ); - right = left + scaleW * ( this.view.width / zoomW ); - top -= scaleH * ( this.view.offsetY / zoomH ); - bottom = top - scaleH * ( this.view.height / zoomH ); + if ( faceMaterial.morphTargets === true ) { - } + var morphTargets = geometry.morphTargets; + var morphInfluences = this.morphTargetInfluences; - this.projectionMatrix.makeOrthographic( left, right, top, bottom, this.near, this.far ); + vA.set( 0, 0, 0 ); + vB.set( 0, 0, 0 ); + vC.set( 0, 0, 0 ); - }, + for ( var t = 0, tl = morphTargets.length; t < tl; t ++ ) { - toJSON: function ( meta ) { + var influence = morphInfluences[ t ]; - var data = Object3D.prototype.toJSON.call( this, meta ); + if ( influence === 0 ) continue; - data.object.zoom = this.zoom; - data.object.left = this.left; - data.object.right = this.right; - data.object.top = this.top; - data.object.bottom = this.bottom; - data.object.near = this.near; - data.object.far = this.far; + var targets = morphTargets[ t ].vertices; - if ( this.view !== null ) data.object.view = Object.assign( {}, this.view ); + vA.addScaledVector( tempA.subVectors( targets[ face.a ], fvA ), influence ); + vB.addScaledVector( tempB.subVectors( targets[ face.b ], fvB ), influence ); + vC.addScaledVector( tempC.subVectors( targets[ face.c ], fvC ), influence ); - return data; + } - } + vA.add( fvA ); + vB.add( fvB ); + vC.add( fvC ); -} ); + fvA = vA; + fvB = vB; + fvC = vC; -/** - * @author mrdoob / http://mrdoob.com/ - */ + } -function WebGLAttributes( gl ) { + intersection = checkIntersection( this, faceMaterial, raycaster, ray, fvA, fvB, fvC, intersectionPoint ); - var buffers = {}; + if ( intersection ) { - function createBuffer( attribute, bufferType ) { + if ( uvs && uvs[ f ] ) { - var array = attribute.array; - var usage = attribute.dynamic ? gl.DYNAMIC_DRAW : gl.STATIC_DRAW; + var uvs_f = uvs[ f ]; + uvA.copy( uvs_f[ 0 ] ); + uvB.copy( uvs_f[ 1 ] ); + uvC.copy( uvs_f[ 2 ] ); - var buffer = gl.createBuffer(); + intersection.uv = uvIntersection( intersectionPoint, fvA, fvB, fvC, uvA, uvB, uvC ); - gl.bindBuffer( bufferType, buffer ); - gl.bufferData( bufferType, array, usage ); + } - attribute.onUploadCallback(); + intersection.face = face; + intersection.faceIndex = f; + intersects.push( intersection ); - var type = gl.FLOAT; + } - if ( array instanceof Float32Array ) { + } - type = gl.FLOAT; + } - } else if ( array instanceof Float64Array ) { + }; - console.warn( 'THREE.WebGLAttributes: Unsupported data buffer format: Float64Array.' ); + }() ), - } else if ( array instanceof Uint16Array ) { + clone: function () { - type = gl.UNSIGNED_SHORT; + return new this.constructor( this.geometry, this.material ).copy( this ); - } else if ( array instanceof Int16Array ) { + } - type = gl.SHORT; +} ); - } else if ( array instanceof Uint32Array ) { +/** + * @author mrdoob / http://mrdoob.com/ + */ - type = gl.UNSIGNED_INT; +function WebGLBackground( renderer, state, geometries, premultipliedAlpha ) { - } else if ( array instanceof Int32Array ) { + var clearColor = new Color( 0x000000 ); + var clearAlpha = 0; - type = gl.INT; + var planeCamera, planeMesh; + var boxMesh; - } else if ( array instanceof Int8Array ) { + function render( renderList, scene, camera, forceClear ) { - type = gl.BYTE; + var background = scene.background; - } else if ( array instanceof Uint8Array ) { + if ( background === null ) { - type = gl.UNSIGNED_BYTE; + setClear( clearColor, clearAlpha ); - } + } else if ( background && background.isColor ) { - return { - buffer: buffer, - type: type, - bytesPerElement: array.BYTES_PER_ELEMENT, - version: attribute.version - }; + setClear( background, 1 ); + forceClear = true; - } + } - function updateBuffer( buffer, attribute, bufferType ) { + if ( renderer.autoClear || forceClear ) { - var array = attribute.array; - var updateRange = attribute.updateRange; + renderer.clear( renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil ); - gl.bindBuffer( bufferType, buffer ); + } - if ( attribute.dynamic === false ) { + if ( background && background.isCubeTexture ) { - gl.bufferData( bufferType, array, gl.STATIC_DRAW ); + if ( boxMesh === undefined ) { - } else if ( updateRange.count === - 1 ) { + boxMesh = new Mesh( + new BoxBufferGeometry( 1, 1, 1 ), + new ShaderMaterial( { + uniforms: ShaderLib.cube.uniforms, + vertexShader: ShaderLib.cube.vertexShader, + fragmentShader: ShaderLib.cube.fragmentShader, + side: BackSide, + depthTest: true, + depthWrite: false, + polygonOffset: true, + fog: false + } ) + ); - // Not using update ranges + boxMesh.geometry.removeAttribute( 'normal' ); + boxMesh.geometry.removeAttribute( 'uv' ); - gl.bufferSubData( bufferType, 0, array ); + boxMesh.onBeforeRender = function ( renderer, scene, camera ) { - } else if ( updateRange.count === 0 ) { + var scale = camera.far; - console.error( 'THREE.WebGLObjects.updateBuffer: dynamic THREE.BufferAttribute marked as needsUpdate but updateRange.count is 0, ensure you are using set methods or updating manually.' ); + this.matrixWorld.makeScale( scale, scale, scale ); + this.matrixWorld.copyPosition( camera.matrixWorld ); - } else { + this.material.polygonOffsetUnits = scale * 10; - gl.bufferSubData( bufferType, updateRange.offset * array.BYTES_PER_ELEMENT, - array.subarray( updateRange.offset, updateRange.offset + updateRange.count ) ); + }; - updateRange.count = 0; // reset range + geometries.update( boxMesh.geometry ); - } + } - } + boxMesh.material.uniforms.tCube.value = background; - // + renderList.push( boxMesh, boxMesh.geometry, boxMesh.material, 0, null ); - function get( attribute ) { + } else if ( background && background.isTexture ) { - if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data; + if ( planeCamera === undefined ) { - return buffers[ attribute.uuid ]; + planeCamera = new OrthographicCamera( - 1, 1, 1, - 1, 0, 1 ); - } + planeMesh = new Mesh( + new PlaneBufferGeometry( 2, 2 ), + new MeshBasicMaterial( { depthTest: false, depthWrite: false, fog: false } ) + ); - function remove( attribute ) { + geometries.update( planeMesh.geometry ); - var data = buffers[ attribute.uuid ]; + } - if ( data ) { + planeMesh.material.map = background; - gl.deleteBuffer( data.buffer ); + // TODO Push this to renderList - delete buffers[ attribute.uuid ]; + renderer.renderBufferDirect( planeCamera, null, planeMesh.geometry, planeMesh.material, planeMesh, null ); } } - function update( attribute, bufferType ) { + function setClear( color, alpha ) { - if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data; + state.buffers.color.setClear( color.r, color.g, color.b, alpha, premultipliedAlpha ); - var data = buffers[ attribute.uuid ]; + } - if ( data === undefined ) { + return { - buffers[ attribute.uuid ] = createBuffer( attribute, bufferType ); + getClearColor: function () { - } else if ( data.version < attribute.version ) { + return clearColor; - updateBuffer( data.buffer, attribute, bufferType ); + }, + setClearColor: function ( color, alpha ) { - data.version = attribute.version; + clearColor.set( color ); + clearAlpha = alpha !== undefined ? alpha : 1; + setClear( clearColor, clearAlpha ); - } + }, + getClearAlpha: function () { - } + return clearAlpha; - return { + }, + setClearAlpha: function ( alpha ) { - get: get, - remove: remove, - update: update + clearAlpha = alpha; + setClear( clearColor, clearAlpha ); + + }, + render: render }; @@ -16197,43 +16590,42 @@ function reversePainterSortStable( a, b ) { function WebGLRenderList() { - var opaque = []; - var opaqueLastIndex = - 1; + var renderItems = []; + var renderItemsIndex = 0; + var opaque = []; var transparent = []; - var transparentLastIndex = - 1; function init() { - opaqueLastIndex = - 1; - transparentLastIndex = - 1; + renderItemsIndex = 0; + + opaque.length = 0; + transparent.length = 0; } function push( object, geometry, material, z, group ) { - var array, index; + var renderItem = renderItems[ renderItemsIndex ]; - // allocate the next position in the appropriate array + if ( renderItem === undefined ) { - if ( material.transparent ) { + renderItem = { + id: object.id, + object: object, + geometry: geometry, + material: material, + program: material.program, + renderOrder: object.renderOrder, + z: z, + group: group + }; - array = transparent; - index = ++ transparentLastIndex; + renderItems[ renderItemsIndex ] = renderItem; } else { - array = opaque; - index = ++ opaqueLastIndex; - - } - - // recycle existing render item or grow the array - - var renderItem = array[ index ]; - - if ( renderItem ) { - renderItem.id = object.id; renderItem.object = object; renderItem.geometry = geometry; @@ -16243,37 +16635,18 @@ function WebGLRenderList() { renderItem.z = z; renderItem.group = group; - } else { - - renderItem = { - id: object.id, - object: object, - geometry: geometry, - material: material, - program: material.program, - renderOrder: object.renderOrder, - z: z, - group: group - }; - - // assert( index === array.length ); - array.push( renderItem ); - } - } - - function finish() { + ( material.transparent === true ? transparent : opaque ).push( renderItem ); - opaque.length = opaqueLastIndex + 1; - transparent.length = transparentLastIndex + 1; + renderItemsIndex ++; } function sort() { - opaque.sort( painterSortStable ); - transparent.sort( reversePainterSortStable ); + if ( opaque.length > 1 ) opaque.sort( painterSortStable ); + if ( transparent.length > 1 ) transparent.sort( reversePainterSortStable ); } @@ -16283,7 +16656,6 @@ function WebGLRenderList() { init: init, push: push, - finish: finish, sort: sort }; @@ -16329,47 +16701,143 @@ function WebGLRenderLists() { * @author mrdoob / http://mrdoob.com/ */ -function WebGLIndexedBufferRenderer( gl, extensions, infoRender ) { +function absNumericalSort( a, b ) { - var mode; + return Math.abs( b[ 1 ] ) - Math.abs( a[ 1 ] ); - function setMode( value ) { +} - mode = value; +function WebGLMorphtargets( gl ) { - } + var influencesList = {}; + var morphInfluences = new Float32Array( 8 ); - var type, size; + function update( object, geometry, material, program ) { - function setIndex( index ) { + var objectInfluences = object.morphTargetInfluences; - if ( index.array instanceof Uint32Array && extensions.get( 'OES_element_index_uint' ) ) { + var length = objectInfluences.length; - type = gl.UNSIGNED_INT; - size = 4; + var influences = influencesList[ geometry.id ]; - } else if ( index.array instanceof Uint16Array ) { + if ( influences === undefined ) { - type = gl.UNSIGNED_SHORT; - size = 2; + // initialise list - } else { + influences = []; - type = gl.UNSIGNED_BYTE; - size = 1; + for ( var i = 0; i < length; i ++ ) { + + influences[ i ] = [ i, 0 ]; + + } + + influencesList[ geometry.id ] = influences; + + } + + var morphTargets = material.morphTargets && geometry.morphAttributes.position; + var morphNormals = material.morphNormals && geometry.morphAttributes.normal; + + // Remove current morphAttributes + + for ( var i = 0; i < length; i ++ ) { + + var influence = influences[ i ]; + + if ( influence[ 1 ] !== 0 ) { + + if ( morphTargets ) geometry.removeAttribute( 'morphTarget' + i ); + if ( morphNormals ) geometry.removeAttribute( 'morphNormal' + i ); + + } + + } + + // Collect influences + + for ( var i = 0; i < length; i ++ ) { + + var influence = influences[ i ]; + + influence[ 0 ] = i; + influence[ 1 ] = objectInfluences[ i ]; + + } + + influences.sort( absNumericalSort ); + + // Add morphAttributes + + for ( var i = 0; i < 8; i ++ ) { + + var influence = influences[ i ]; + + if ( influence ) { + + var index = influence[ 0 ]; + var value = influence[ 1 ]; + + if ( value ) { + + if ( morphTargets ) geometry.addAttribute( 'morphTarget' + i, morphTargets[ index ] ); + if ( morphNormals ) geometry.addAttribute( 'morphNormal' + i, morphNormals[ index ] ); + + morphInfluences[ i ] = value; + continue; + + } + + } + + morphInfluences[ i ] = 0; } + program.getUniforms().setValue( gl, 'morphTargetInfluences', morphInfluences ); + + } + + return { + + update: update + + } + +} + +/** + * @author mrdoob / http://mrdoob.com/ + */ + +function WebGLIndexedBufferRenderer( gl, extensions, infoRender ) { + + var mode; + + function setMode( value ) { + + mode = value; + + } + + var type, bytesPerElement; + + function setIndex( value ) { + + type = value.type; + bytesPerElement = value.bytesPerElement; + } function render( start, count ) { - gl.drawElements( mode, count, type, start * size ); + gl.drawElements( mode, count, type, start * bytesPerElement ); infoRender.calls ++; infoRender.vertices += count; if ( mode === gl.TRIANGLES ) infoRender.faces += count / 3; + else if ( mode === gl.POINTS ) infoRender.points += count; } @@ -16384,12 +16852,13 @@ function WebGLIndexedBufferRenderer( gl, extensions, infoRender ) { } - extension.drawElementsInstancedANGLE( mode, count, type, start * size, geometry.maxInstancedCount ); + extension.drawElementsInstancedANGLE( mode, count, type, start * bytesPerElement, geometry.maxInstancedCount ); infoRender.calls ++; infoRender.vertices += count * geometry.maxInstancedCount; if ( mode === gl.TRIANGLES ) infoRender.faces += geometry.maxInstancedCount * count / 3; + else if ( mode === gl.POINTS ) infoRender.points += geometry.maxInstancedCount * count; } @@ -16424,6 +16893,7 @@ function WebGLBufferRenderer( gl, extensions, infoRender ) { infoRender.vertices += count; if ( mode === gl.TRIANGLES ) infoRender.faces += count / 3; + else if ( mode === gl.POINTS ) infoRender.points += count; } @@ -16456,6 +16926,7 @@ function WebGLBufferRenderer( gl, extensions, infoRender ) { infoRender.vertices += count * geometry.maxInstancedCount; if ( mode === gl.TRIANGLES ) infoRender.faces += geometry.maxInstancedCount * count / 3; + else if ( mode === gl.POINTS ) infoRender.points += geometry.maxInstancedCount * count; } @@ -16660,7 +17131,7 @@ function WebGLGeometries( gl, attributes, infoMemory ) { * @author mrdoob / http://mrdoob.com/ */ -function WebGLLights() { +function UniformsCache() { var lights = {}; @@ -16717,7 +17188,9 @@ function WebGLLights() { shadow: false, shadowBias: 0, shadowRadius: 1, - shadowMapSize: new Vector2() + shadowMapSize: new Vector2(), + shadowCameraNear: 1, + shadowCameraFar: 1000 }; break; @@ -16751,11 +17224,237 @@ function WebGLLights() { } +function WebGLLights() { + + var cache = new UniformsCache(); + + var state = { + + hash: '', + + ambient: [ 0, 0, 0 ], + directional: [], + directionalShadowMap: [], + directionalShadowMatrix: [], + spot: [], + spotShadowMap: [], + spotShadowMatrix: [], + rectArea: [], + point: [], + pointShadowMap: [], + pointShadowMatrix: [], + hemi: [] + + }; + + var vector3 = new Vector3(); + var matrix4 = new Matrix4(); + var matrix42 = new Matrix4(); + + function setup( lights, shadows, camera ) { + + var r = 0, g = 0, b = 0; + + var directionalLength = 0; + var pointLength = 0; + var spotLength = 0; + var rectAreaLength = 0; + var hemiLength = 0; + + var viewMatrix = camera.matrixWorldInverse; + + for ( var i = 0, l = lights.length; i < l; i ++ ) { + + var light = lights[ i ]; + + var color = light.color; + var intensity = light.intensity; + var distance = light.distance; + + var shadowMap = ( light.shadow && light.shadow.map ) ? light.shadow.map.texture : null; + + if ( light.isAmbientLight ) { + + r += color.r * intensity; + g += color.g * intensity; + b += color.b * intensity; + + } else if ( light.isDirectionalLight ) { + + var uniforms = cache.get( light ); + + uniforms.color.copy( light.color ).multiplyScalar( light.intensity ); + uniforms.direction.setFromMatrixPosition( light.matrixWorld ); + vector3.setFromMatrixPosition( light.target.matrixWorld ); + uniforms.direction.sub( vector3 ); + uniforms.direction.transformDirection( viewMatrix ); + + uniforms.shadow = light.castShadow; + + if ( light.castShadow ) { + + var shadow = light.shadow; + + uniforms.shadowBias = shadow.bias; + uniforms.shadowRadius = shadow.radius; + uniforms.shadowMapSize = shadow.mapSize; + + } + + state.directionalShadowMap[ directionalLength ] = shadowMap; + state.directionalShadowMatrix[ directionalLength ] = light.shadow.matrix; + state.directional[ directionalLength ] = uniforms; + + directionalLength ++; + + } else if ( light.isSpotLight ) { + + var uniforms = cache.get( light ); + + uniforms.position.setFromMatrixPosition( light.matrixWorld ); + uniforms.position.applyMatrix4( viewMatrix ); + + uniforms.color.copy( color ).multiplyScalar( intensity ); + uniforms.distance = distance; + + uniforms.direction.setFromMatrixPosition( light.matrixWorld ); + vector3.setFromMatrixPosition( light.target.matrixWorld ); + uniforms.direction.sub( vector3 ); + uniforms.direction.transformDirection( viewMatrix ); + + uniforms.coneCos = Math.cos( light.angle ); + uniforms.penumbraCos = Math.cos( light.angle * ( 1 - light.penumbra ) ); + uniforms.decay = ( light.distance === 0 ) ? 0.0 : light.decay; + + uniforms.shadow = light.castShadow; + + if ( light.castShadow ) { + + var shadow = light.shadow; + + uniforms.shadowBias = shadow.bias; + uniforms.shadowRadius = shadow.radius; + uniforms.shadowMapSize = shadow.mapSize; + + } + + state.spotShadowMap[ spotLength ] = shadowMap; + state.spotShadowMatrix[ spotLength ] = light.shadow.matrix; + state.spot[ spotLength ] = uniforms; + + spotLength ++; + + } else if ( light.isRectAreaLight ) { + + var uniforms = cache.get( light ); + + // (a) intensity controls irradiance of entire light + uniforms.color + .copy( color ) + .multiplyScalar( intensity / ( light.width * light.height ) ); + + // (b) intensity controls the radiance per light area + // uniforms.color.copy( color ).multiplyScalar( intensity ); + + uniforms.position.setFromMatrixPosition( light.matrixWorld ); + uniforms.position.applyMatrix4( viewMatrix ); + + // extract local rotation of light to derive width/height half vectors + matrix42.identity(); + matrix4.copy( light.matrixWorld ); + matrix4.premultiply( viewMatrix ); + matrix42.extractRotation( matrix4 ); + + uniforms.halfWidth.set( light.width * 0.5, 0.0, 0.0 ); + uniforms.halfHeight.set( 0.0, light.height * 0.5, 0.0 ); + + uniforms.halfWidth.applyMatrix4( matrix42 ); + uniforms.halfHeight.applyMatrix4( matrix42 ); + + // TODO (abelnation): RectAreaLight distance? + // uniforms.distance = distance; + + state.rectArea[ rectAreaLength ] = uniforms; + + rectAreaLength ++; + + } else if ( light.isPointLight ) { + + var uniforms = cache.get( light ); + + uniforms.position.setFromMatrixPosition( light.matrixWorld ); + uniforms.position.applyMatrix4( viewMatrix ); + + uniforms.color.copy( light.color ).multiplyScalar( light.intensity ); + uniforms.distance = light.distance; + uniforms.decay = ( light.distance === 0 ) ? 0.0 : light.decay; + + uniforms.shadow = light.castShadow; + + if ( light.castShadow ) { + + var shadow = light.shadow; + + uniforms.shadowBias = shadow.bias; + uniforms.shadowRadius = shadow.radius; + uniforms.shadowMapSize = shadow.mapSize; + uniforms.shadowCameraNear = shadow.camera.near; + uniforms.shadowCameraFar = shadow.camera.far; + + } + + state.pointShadowMap[ pointLength ] = shadowMap; + state.pointShadowMatrix[ pointLength ] = light.shadow.matrix; + state.point[ pointLength ] = uniforms; + + pointLength ++; + + } else if ( light.isHemisphereLight ) { + + var uniforms = cache.get( light ); + + uniforms.direction.setFromMatrixPosition( light.matrixWorld ); + uniforms.direction.transformDirection( viewMatrix ); + uniforms.direction.normalize(); + + uniforms.skyColor.copy( light.color ).multiplyScalar( intensity ); + uniforms.groundColor.copy( light.groundColor ).multiplyScalar( intensity ); + + state.hemi[ hemiLength ] = uniforms; + + hemiLength ++; + + } + + } + + state.ambient[ 0 ] = r; + state.ambient[ 1 ] = g; + state.ambient[ 2 ] = b; + + state.directional.length = directionalLength; + state.spot.length = spotLength; + state.rectArea.length = rectAreaLength; + state.point.length = pointLength; + state.hemi.length = hemiLength; + + // TODO (sam-g-steel) why aren't we using join + state.hash = directionalLength + ',' + pointLength + ',' + spotLength + ',' + rectAreaLength + ',' + hemiLength + ',' + shadows.length; + + } + + return { + setup: setup, + state: state + } + +} + /** * @author mrdoob / http://mrdoob.com/ */ -function WebGLObjects( gl, geometries, infoRender ) { +function WebGLObjects( geometries, infoRender ) { var updateList = {}; @@ -17036,15 +17735,14 @@ function unrollLoops( string ) { } -function WebGLProgram( renderer, code, material, parameters ) { +function WebGLProgram( renderer, extensions, code, material, shader, parameters ) { var gl = renderer.context; - var extensions = material.extensions; var defines = material.defines; - var vertexShader = material.__webglShader.vertexShader; - var fragmentShader = material.__webglShader.fragmentShader; + var vertexShader = shader.vertexShader; + var fragmentShader = shader.fragmentShader; var shadowMapTypeDefine = 'SHADOWMAP_TYPE_BASIC'; @@ -17120,7 +17818,7 @@ function WebGLProgram( renderer, code, material, parameters ) { // - var customExtensions = generateExtensions( extensions, parameters, renderer.extensions ); + var customExtensions = generateExtensions( material.extensions, parameters, extensions ); var customDefines = generateDefines( defines ); @@ -17156,7 +17854,7 @@ function WebGLProgram( renderer, code, material, parameters ) { 'precision ' + parameters.precision + ' float;', 'precision ' + parameters.precision + ' int;', - '#define SHADER_NAME ' + material.__webglShader.name, + '#define SHADER_NAME ' + shader.name, customDefines, @@ -17201,7 +17899,7 @@ function WebGLProgram( renderer, code, material, parameters ) { parameters.sizeAttenuation ? '#define USE_SIZEATTENUATION' : '', parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '', - parameters.logarithmicDepthBuffer && renderer.extensions.get( 'EXT_frag_depth' ) ? '#define USE_LOGDEPTHBUF_EXT' : '', + parameters.logarithmicDepthBuffer && extensions.get( 'EXT_frag_depth' ) ? '#define USE_LOGDEPTHBUF_EXT' : '', 'uniform mat4 modelMatrix;', 'uniform mat4 modelViewMatrix;', @@ -17263,7 +17961,7 @@ function WebGLProgram( renderer, code, material, parameters ) { 'precision ' + parameters.precision + ' float;', 'precision ' + parameters.precision + ' int;', - '#define SHADER_NAME ' + material.__webglShader.name, + '#define SHADER_NAME ' + shader.name, customDefines, @@ -17308,9 +18006,9 @@ function WebGLProgram( renderer, code, material, parameters ) { parameters.physicallyCorrectLights ? "#define PHYSICALLY_CORRECT_LIGHTS" : '', parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '', - parameters.logarithmicDepthBuffer && renderer.extensions.get( 'EXT_frag_depth' ) ? '#define USE_LOGDEPTHBUF_EXT' : '', + parameters.logarithmicDepthBuffer && extensions.get( 'EXT_frag_depth' ) ? '#define USE_LOGDEPTHBUF_EXT' : '', - parameters.envMap && renderer.extensions.get( 'EXT_shader_texture_lod' ) ? '#define TEXTURE_LOD_EXT' : '', + parameters.envMap && extensions.get( 'EXT_shader_texture_lod' ) ? '#define TEXTURE_LOD_EXT' : '', 'uniform mat4 viewMatrix;', 'uniform vec3 cameraPosition;', @@ -17437,12 +18135,11 @@ function WebGLProgram( renderer, code, material, parameters ) { var cachedUniforms; - this.getUniforms = function() { + this.getUniforms = function () { if ( cachedUniforms === undefined ) { - cachedUniforms = - new WebGLUniforms( gl, program, renderer ); + cachedUniforms = new WebGLUniforms( gl, program, renderer ); } @@ -17454,7 +18151,7 @@ function WebGLProgram( renderer, code, material, parameters ) { var cachedAttributes; - this.getAttributes = function() { + this.getAttributes = function () { if ( cachedAttributes === undefined ) { @@ -17517,12 +18214,13 @@ function WebGLProgram( renderer, code, material, parameters ) { * @author mrdoob / http://mrdoob.com/ */ -function WebGLPrograms( renderer, capabilities ) { +function WebGLPrograms( renderer, extensions, capabilities ) { var programs = []; var shaderIDs = { MeshDepthMaterial: 'depth', + MeshDistanceMaterial: 'distanceRGBA', MeshNormalMaterial: 'normal', MeshBasicMaterial: 'basic', MeshLambertMaterial: 'lambert', @@ -17532,7 +18230,8 @@ function WebGLPrograms( renderer, capabilities ) { MeshPhysicalMaterial: 'physical', LineBasicMaterial: 'basic', LineDashedMaterial: 'dashed', - PointsMaterial: 'points' + PointsMaterial: 'points', + ShadowMaterial: 'shadow' }; var parameterNames = [ @@ -17615,7 +18314,7 @@ function WebGLPrograms( renderer, capabilities ) { } - this.getParameters = function ( material, lights, fog, nClipPlanes, nClipIntersection, object ) { + this.getParameters = function ( material, lights, shadows, fog, nClipPlanes, nClipIntersection, object ) { var shaderID = shaderIDs[ material.type ]; @@ -17623,7 +18322,7 @@ function WebGLPrograms( renderer, capabilities ) { // (not to blow over maxLights budget) var maxBones = object.isSkinnedMesh ? allocateBones( object ) : 0; - var precision = renderer.getPrecision(); + var precision = capabilities.precision; if ( material.precision !== null ) { @@ -17674,7 +18373,7 @@ function WebGLPrograms( renderer, capabilities ) { useFog: material.fog, fogExp: ( fog && fog.isFogExp2 ), - flatShading: material.shading === FlatShading, + flatShading: material.flatShading, sizeAttenuation: material.sizeAttenuation, logarithmicDepthBuffer: capabilities.logarithmicDepthBuffer, @@ -17699,7 +18398,7 @@ function WebGLPrograms( renderer, capabilities ) { dithering: material.dithering, - shadowMapEnabled: renderer.shadowMap.enabled && object.receiveShadow && lights.shadows.length > 0, + shadowMapEnabled: renderer.shadowMap.enabled && object.receiveShadow && shadows.length > 0, shadowMapType: renderer.shadowMap.type, toneMapping: renderer.toneMapping, @@ -17751,13 +18450,15 @@ function WebGLPrograms( renderer, capabilities ) { } + array.push( material.onBeforeCompile.toString() ); + array.push( renderer.gammaOutput ); return array.join(); }; - this.acquireProgram = function ( material, parameters, code ) { + this.acquireProgram = function ( material, shader, parameters, code ) { var program; @@ -17779,7 +18480,7 @@ function WebGLPrograms( renderer, capabilities ) { if ( program === undefined ) { - program = new WebGLProgram( renderer, code, material, parameters ); + program = new WebGLProgram( renderer, extensions, code, material, shader, parameters ); programs.push( program ); } @@ -17813,7 +18514,7 @@ function WebGLPrograms( renderer, capabilities ) { * @author mrdoob / http://mrdoob.com/ */ -function WebGLTextures( _gl, extensions, state, properties, capabilities, paramThreeToGL, infoMemory ) { +function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, infoMemory ) { var _isWebGL2 = ( typeof WebGL2RenderingContext !== 'undefined' && _gl instanceof WebGL2RenderingContext ); @@ -17879,6 +18580,13 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, paramT } + function textureNeedsGenerateMipmaps( texture, isPowerOfTwo ) { + + return texture.generateMipmaps && isPowerOfTwo && + texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter; + + } + // Fallback filters for non-power-of-2 textures function filterFallback( f ) { @@ -18065,8 +18773,8 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, paramT var image = cubeImage[ 0 ], isPowerOfTwoImage = isPowerOfTwo( image ), - glFormat = paramThreeToGL( texture.format ), - glType = paramThreeToGL( texture.type ); + glFormat = utils.convert( texture.format ), + glType = utils.convert( texture.type ); setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture, isPowerOfTwoImage ); @@ -18100,7 +18808,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, paramT } else { - console.warn( "THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()" ); + console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()' ); } @@ -18116,7 +18824,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, paramT } - if ( texture.generateMipmaps && isPowerOfTwoImage ) { + if ( textureNeedsGenerateMipmaps( texture, isPowerOfTwoImage ) ) { _gl.generateMipmap( _gl.TEXTURE_CUBE_MAP ); @@ -18150,11 +18858,11 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, paramT if ( isPowerOfTwoImage ) { - _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, paramThreeToGL( texture.wrapS ) ); - _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, paramThreeToGL( texture.wrapT ) ); + _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, utils.convert( texture.wrapS ) ); + _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, utils.convert( texture.wrapT ) ); - _gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, paramThreeToGL( texture.magFilter ) ); - _gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, paramThreeToGL( texture.minFilter ) ); + _gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, utils.convert( texture.magFilter ) ); + _gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, utils.convert( texture.minFilter ) ); } else { @@ -18226,8 +18934,8 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, paramT } var isPowerOfTwoImage = isPowerOfTwo( image ), - glFormat = paramThreeToGL( texture.format ), - glType = paramThreeToGL( texture.type ); + glFormat = utils.convert( texture.format ), + glType = utils.convert( texture.type ); setTextureParameters( _gl.TEXTURE_2D, texture, isPowerOfTwoImage ); @@ -18261,7 +18969,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, paramT console.warn( 'THREE.WebGLRenderer: Use UnsignedShortType or UnsignedIntType for DepthFormat DepthTexture.' ); texture.type = UnsignedShortType; - glType = paramThreeToGL( texture.type ); + glType = utils.convert( texture.type ); } @@ -18278,10 +18986,10 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, paramT // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/) if ( texture.type !== UnsignedInt248Type ) { - console.warn( 'THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture.' ); + console.warn( 'THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture.' ); texture.type = UnsignedInt248Type; - glType = paramThreeToGL( texture.type ); + glType = utils.convert( texture.type ); } @@ -18326,7 +19034,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, paramT } else { - console.warn( "THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()" ); + console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()' ); } @@ -18365,7 +19073,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, paramT } - if ( texture.generateMipmaps && isPowerOfTwoImage ) _gl.generateMipmap( _gl.TEXTURE_2D ); + if ( textureNeedsGenerateMipmaps( texture, isPowerOfTwoImage ) ) _gl.generateMipmap( _gl.TEXTURE_2D ); textureProperties.__version = texture.version; @@ -18378,8 +19086,8 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, paramT // Setup storage for target texture and bind it to correct framebuffer function setupFrameBufferTexture( framebuffer, renderTarget, attachment, textureTarget ) { - var glFormat = paramThreeToGL( renderTarget.texture.format ); - var glType = paramThreeToGL( renderTarget.texture.type ); + var glFormat = utils.convert( renderTarget.texture.format ); + var glType = utils.convert( renderTarget.texture.type ); state.texImage2D( textureTarget, 0, glFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null ); _gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); _gl.framebufferTexture2D( _gl.FRAMEBUFFER, attachment, textureTarget, properties.get( renderTarget.texture ).__webglTexture, 0 ); @@ -18417,13 +19125,13 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, paramT function setupDepthTexture( framebuffer, renderTarget ) { var isCube = ( renderTarget && renderTarget.isWebGLRenderTargetCube ); - if ( isCube ) throw new Error('Depth Texture with cube render targets is not supported!'); + if ( isCube ) throw new Error( 'Depth Texture with cube render targets is not supported' ); _gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); if ( !( renderTarget.depthTexture && renderTarget.depthTexture.isDepthTexture ) ) { - throw new Error('renderTarget.depthTexture must be an instance of THREE.DepthTexture'); + throw new Error( 'renderTarget.depthTexture must be an instance of THREE.DepthTexture' ); } @@ -18450,7 +19158,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, paramT } else { - throw new Error('Unknown depthTexture format') + throw new Error( 'Unknown depthTexture format' ); } @@ -18465,7 +19173,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, paramT if ( renderTarget.depthTexture ) { - if ( isCube ) throw new Error('target.depthTexture not supported in Cube render targets'); + if ( isCube ) throw new Error( 'target.depthTexture not supported in Cube render targets' ); setupDepthTexture( renderTargetProperties.__webglFramebuffer, renderTarget ); @@ -18543,7 +19251,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, paramT } - if ( renderTarget.texture.generateMipmaps && isTargetPowerOfTwo ) _gl.generateMipmap( _gl.TEXTURE_CUBE_MAP ); + if ( textureNeedsGenerateMipmaps( renderTarget.texture, isTargetPowerOfTwo ) ) _gl.generateMipmap( _gl.TEXTURE_CUBE_MAP ); state.bindTexture( _gl.TEXTURE_CUBE_MAP, null ); } else { @@ -18552,7 +19260,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, paramT setTextureParameters( _gl.TEXTURE_2D, renderTarget.texture, isTargetPowerOfTwo ); setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D ); - if ( renderTarget.texture.generateMipmaps && isTargetPowerOfTwo ) _gl.generateMipmap( _gl.TEXTURE_2D ); + if ( textureNeedsGenerateMipmaps( renderTarget.texture, isTargetPowerOfTwo ) ) _gl.generateMipmap( _gl.TEXTURE_2D ); state.bindTexture( _gl.TEXTURE_2D, null ); } @@ -18570,12 +19278,11 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, paramT function updateRenderTargetMipmap( renderTarget ) { var texture = renderTarget.texture; + var isTargetPowerOfTwo = isPowerOfTwo( renderTarget ); - if ( texture.generateMipmaps && isPowerOfTwo( renderTarget ) && - texture.minFilter !== NearestFilter && - texture.minFilter !== LinearFilter ) { + if ( textureNeedsGenerateMipmaps( texture, isTargetPowerOfTwo ) ) { - var target = (renderTarget && renderTarget.isWebGLRenderTargetCube) ? _gl.TEXTURE_CUBE_MAP : _gl.TEXTURE_2D; + var target = renderTarget.isWebGLRenderTargetCube ? _gl.TEXTURE_CUBE_MAP : _gl.TEXTURE_2D; var webglTexture = properties.get( texture ).__webglTexture; state.bindTexture( target, webglTexture ); @@ -18642,7 +19349,7 @@ function WebGLProperties() { * @author mrdoob / http://mrdoob.com/ */ -function WebGLState( gl, extensions, paramThreeToGL ) { +function WebGLState( gl, extensions, utils ) { function ColorBuffer() { @@ -18650,7 +19357,7 @@ function WebGLState( gl, extensions, paramThreeToGL ) { var color = new Vector4(); var currentColorMask = null; - var currentColorClear = new Vector4(); + var currentColorClear = new Vector4( 0, 0, 0, 0 ); return { @@ -18695,7 +19402,7 @@ function WebGLState( gl, extensions, paramThreeToGL ) { locked = false; currentColorMask = null; - currentColorClear.set( 0, 0, 0, 1 ); + currentColorClear.set( - 1, 0, 0, 0 ); // set to invalid state } @@ -18958,6 +19665,8 @@ function WebGLState( gl, extensions, paramThreeToGL ) { var compressedTextureFormats = null; + var currentProgram = null; + var currentBlending = null; var currentBlendEquation = null; var currentBlendSrc = null; @@ -18975,8 +19684,6 @@ function WebGLState( gl, extensions, paramThreeToGL ) { var currentPolygonOffsetFactor = null; var currentPolygonOffsetUnits = null; - var currentScissorTest = null; - var maxTextures = gl.getParameter( gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS ); var version = parseFloat( /^WebGL\ ([0-9])/.exec( gl.getParameter( gl.VERSION ) )[ 1 ] ); @@ -19011,25 +19718,23 @@ function WebGLState( gl, extensions, paramThreeToGL ) { emptyTextures[ gl.TEXTURE_2D ] = createTexture( gl.TEXTURE_2D, gl.TEXTURE_2D, 1 ); emptyTextures[ gl.TEXTURE_CUBE_MAP ] = createTexture( gl.TEXTURE_CUBE_MAP, gl.TEXTURE_CUBE_MAP_POSITIVE_X, 6 ); - // - - function init() { + // init - colorBuffer.setClear( 0, 0, 0, 1 ); - depthBuffer.setClear( 1 ); - stencilBuffer.setClear( 0 ); + colorBuffer.setClear( 0, 0, 0, 1 ); + depthBuffer.setClear( 1 ); + stencilBuffer.setClear( 0 ); - enable( gl.DEPTH_TEST ); - depthBuffer.setFunc( LessEqualDepth ); + enable( gl.DEPTH_TEST ); + depthBuffer.setFunc( LessEqualDepth ); - setFlipSided( false ); - setCullFace( CullFaceBack ); - enable( gl.CULL_FACE ); + setFlipSided( false ); + setCullFace( CullFaceBack ); + enable( gl.CULL_FACE ); - enable( gl.BLEND ); - setBlending( NormalBlending ); + enable( gl.BLEND ); + setBlending( NormalBlending ); - } + // function initAttributes() { @@ -19148,6 +19853,22 @@ function WebGLState( gl, extensions, paramThreeToGL ) { } + function useProgram( program ) { + + if ( currentProgram !== program ) { + + gl.useProgram( program ); + + currentProgram = program; + + return true; + + } + + return false; + + } + function setBlending( blending, blendEquation, blendSrc, blendDst, blendEquationAlpha, blendSrcAlpha, blendDstAlpha, premultipliedAlpha ) { if ( blending !== NoBlending ) { @@ -19160,72 +19881,83 @@ function WebGLState( gl, extensions, paramThreeToGL ) { } - if ( ( blending !== CustomBlending ) && ( blending !== currentBlending || premultipliedAlpha !== currentPremultipledAlpha ) ) { + if ( blending !== CustomBlending ) { - if ( blending === AdditiveBlending ) { + if ( blending !== currentBlending || premultipliedAlpha !== currentPremultipledAlpha ) { - if ( premultipliedAlpha ) { + switch ( blending ) { - gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD ); - gl.blendFuncSeparate( gl.ONE, gl.ONE, gl.ONE, gl.ONE ); + case AdditiveBlending: - } else { + if ( premultipliedAlpha ) { - gl.blendEquation( gl.FUNC_ADD ); - gl.blendFunc( gl.SRC_ALPHA, gl.ONE ); + gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD ); + gl.blendFuncSeparate( gl.ONE, gl.ONE, gl.ONE, gl.ONE ); - } + } else { - } else if ( blending === SubtractiveBlending ) { + gl.blendEquation( gl.FUNC_ADD ); + gl.blendFunc( gl.SRC_ALPHA, gl.ONE ); - if ( premultipliedAlpha ) { + } + break; - gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD ); - gl.blendFuncSeparate( gl.ZERO, gl.ZERO, gl.ONE_MINUS_SRC_COLOR, gl.ONE_MINUS_SRC_ALPHA ); + case SubtractiveBlending: - } else { + if ( premultipliedAlpha ) { - gl.blendEquation( gl.FUNC_ADD ); - gl.blendFunc( gl.ZERO, gl.ONE_MINUS_SRC_COLOR ); + gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD ); + gl.blendFuncSeparate( gl.ZERO, gl.ZERO, gl.ONE_MINUS_SRC_COLOR, gl.ONE_MINUS_SRC_ALPHA ); - } + } else { - } else if ( blending === MultiplyBlending ) { + gl.blendEquation( gl.FUNC_ADD ); + gl.blendFunc( gl.ZERO, gl.ONE_MINUS_SRC_COLOR ); - if ( premultipliedAlpha ) { + } + break; - gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD ); - gl.blendFuncSeparate( gl.ZERO, gl.SRC_COLOR, gl.ZERO, gl.SRC_ALPHA ); + case MultiplyBlending: - } else { + if ( premultipliedAlpha ) { - gl.blendEquation( gl.FUNC_ADD ); - gl.blendFunc( gl.ZERO, gl.SRC_COLOR ); + gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD ); + gl.blendFuncSeparate( gl.ZERO, gl.SRC_COLOR, gl.ZERO, gl.SRC_ALPHA ); - } + } else { - } else { + gl.blendEquation( gl.FUNC_ADD ); + gl.blendFunc( gl.ZERO, gl.SRC_COLOR ); + + } + break; - if ( premultipliedAlpha ) { + default: - gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD ); - gl.blendFuncSeparate( gl.ONE, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA ); + if ( premultipliedAlpha ) { - } else { + gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD ); + gl.blendFuncSeparate( gl.ONE, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA ); - gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD ); - gl.blendFuncSeparate( gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA ); + } else { + + gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD ); + gl.blendFuncSeparate( gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA ); + + } } } - currentBlending = blending; - currentPremultipledAlpha = premultipliedAlpha; - - } + currentBlendEquation = null; + currentBlendSrc = null; + currentBlendDst = null; + currentBlendEquationAlpha = null; + currentBlendSrcAlpha = null; + currentBlendDstAlpha = null; - if ( blending === CustomBlending ) { + } else { blendEquationAlpha = blendEquationAlpha || blendEquation; blendSrcAlpha = blendSrcAlpha || blendSrc; @@ -19233,7 +19965,7 @@ function WebGLState( gl, extensions, paramThreeToGL ) { if ( blendEquation !== currentBlendEquation || blendEquationAlpha !== currentBlendEquationAlpha ) { - gl.blendEquationSeparate( paramThreeToGL( blendEquation ), paramThreeToGL( blendEquationAlpha ) ); + gl.blendEquationSeparate( utils.convert( blendEquation ), utils.convert( blendEquationAlpha ) ); currentBlendEquation = blendEquation; currentBlendEquationAlpha = blendEquationAlpha; @@ -19242,7 +19974,7 @@ function WebGLState( gl, extensions, paramThreeToGL ) { if ( blendSrc !== currentBlendSrc || blendDst !== currentBlendDst || blendSrcAlpha !== currentBlendSrcAlpha || blendDstAlpha !== currentBlendDstAlpha ) { - gl.blendFuncSeparate( paramThreeToGL( blendSrc ), paramThreeToGL( blendDst ), paramThreeToGL( blendSrcAlpha ), paramThreeToGL( blendDstAlpha ) ); + gl.blendFuncSeparate( utils.convert( blendSrc ), utils.convert( blendDst ), utils.convert( blendSrcAlpha ), utils.convert( blendDstAlpha ) ); currentBlendSrc = blendSrc; currentBlendDst = blendDst; @@ -19251,17 +19983,11 @@ function WebGLState( gl, extensions, paramThreeToGL ) { } - } else { - - currentBlendEquation = null; - currentBlendSrc = null; - currentBlendDst = null; - currentBlendEquationAlpha = null; - currentBlendSrcAlpha = null; - currentBlendDstAlpha = null; - } + currentBlending = blending; + currentPremultipledAlpha = premultipliedAlpha; + } function setMaterial( material ) { @@ -19376,16 +20102,8 @@ function WebGLState( gl, extensions, paramThreeToGL ) { } - function getScissorTest() { - - return currentScissorTest; - - } - function setScissorTest( scissorTest ) { - currentScissorTest = scissorTest; - if ( scissorTest ) { enable( gl.SCISSOR_TEST ); @@ -19515,6 +20233,8 @@ function WebGLState( gl, extensions, paramThreeToGL ) { currentTextureSlot = null; currentBoundTextures = {}; + currentProgram = null; + currentBlending = null; currentFlipSided = null; @@ -19534,7 +20254,6 @@ function WebGLState( gl, extensions, paramThreeToGL ) { stencil: stencilBuffer }, - init: init, initAttributes: initAttributes, enableAttribute: enableAttribute, enableAttributeAndDivisor: enableAttributeAndDivisor, @@ -19543,6 +20262,8 @@ function WebGLState( gl, extensions, paramThreeToGL ) { disable: disable, getCompressedTextureFormats: getCompressedTextureFormats, + useProgram: useProgram, + setBlending: setBlending, setMaterial: setMaterial, @@ -19552,7 +20273,6 @@ function WebGLState( gl, extensions, paramThreeToGL ) { setLineWidth: setLineWidth, setPolygonOffset: setPolygonOffset, - getScissorTest: getScissorTest, setScissorTest: setScissorTest, activeTexture: activeTexture, @@ -19637,7 +20357,7 @@ function WebGLCapabilities( gl, extensions, parameters ) { } - var logarithmicDepthBuffer = parameters.logarithmicDepthBuffer === true && !! extensions.get( 'EXT_frag_depth' ); + var logarithmicDepthBuffer = parameters.logarithmicDepthBuffer === true; var maxTextures = gl.getParameter( gl.MAX_TEXTURE_IMAGE_UNITS ); var maxVertexTextures = gl.getParameter( gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS ); @@ -19679,6 +20399,240 @@ function WebGLCapabilities( gl, extensions, parameters ) { } +/** + * @author mrdoob / http://mrdoob.com/ + */ + +function ArrayCamera( array ) { + + PerspectiveCamera.call( this ); + + this.cameras = array || []; + +} + +ArrayCamera.prototype = Object.assign( Object.create( PerspectiveCamera.prototype ), { + + constructor: ArrayCamera, + + isArrayCamera: true + +} ); + +/** + * @author mrdoob / http://mrdoob.com/ + */ + +function WebVRManager( renderer ) { + + var scope = this; + + var device = null; + var frameData = null; + + if ( 'VRFrameData' in window ) { + + frameData = new window.VRFrameData(); + + } + + var matrixWorldInverse = new Matrix4(); + + var standingMatrix = new Matrix4(); + var standingMatrixInverse = new Matrix4(); + + var cameraL = new PerspectiveCamera(); + cameraL.bounds = new Vector4( 0.0, 0.0, 0.5, 1.0 ); + cameraL.layers.enable( 1 ); + + var cameraR = new PerspectiveCamera(); + cameraR.bounds = new Vector4( 0.5, 0.0, 0.5, 1.0 ); + cameraR.layers.enable( 2 ); + + var cameraVR = new ArrayCamera( [ cameraL, cameraR ] ); + cameraVR.layers.enable( 1 ); + cameraVR.layers.enable( 2 ); + + // + + var currentSize, currentPixelRatio; + + function onVRDisplayPresentChange() { + + if ( device !== null && device.isPresenting ) { + + var eyeParameters = device.getEyeParameters( 'left' ); + var renderWidth = eyeParameters.renderWidth; + var renderHeight = eyeParameters.renderHeight; + + currentPixelRatio = renderer.getPixelRatio(); + currentSize = renderer.getSize(); + + renderer.setDrawingBufferSize( renderWidth * 2, renderHeight, 1 ); + + } else if ( scope.enabled ) { + + renderer.setDrawingBufferSize( currentSize.width, currentSize.height, currentPixelRatio ); + + } + + } + + window.addEventListener( 'vrdisplaypresentchange', onVRDisplayPresentChange, false ); + + // + + this.enabled = false; + this.standing = false; + + this.getDevice = function () { + + return device; + + }; + + this.setDevice = function ( value ) { + + if ( value !== undefined ) device = value; + + }; + + this.getCamera = function ( camera ) { + + if ( device === null ) return camera; + + device.depthNear = camera.near; + device.depthFar = camera.far; + + device.getFrameData( frameData ); + + // + + var pose = frameData.pose; + + if ( pose.position !== null ) { + + camera.position.fromArray( pose.position ); + + } else { + + camera.position.set( 0, 0, 0 ); + + } + + if ( pose.orientation !== null ) { + + camera.quaternion.fromArray( pose.orientation ); + + } + + camera.updateMatrixWorld(); + + var stageParameters = device.stageParameters; + + if ( this.standing && stageParameters ) { + + standingMatrix.fromArray( stageParameters.sittingToStandingTransform ); + standingMatrixInverse.getInverse( standingMatrix ); + + camera.matrixWorld.multiply( standingMatrix ); + camera.matrixWorldInverse.multiply( standingMatrixInverse ); + + } + + if ( device.isPresenting === false ) return camera; + + // + + cameraL.near = camera.near; + cameraR.near = camera.near; + + cameraL.far = camera.far; + cameraR.far = camera.far; + + cameraVR.matrixWorld.copy( camera.matrixWorld ); + cameraVR.matrixWorldInverse.copy( camera.matrixWorldInverse ); + + cameraL.matrixWorldInverse.fromArray( frameData.leftViewMatrix ); + cameraR.matrixWorldInverse.fromArray( frameData.rightViewMatrix ); + + if ( this.standing && stageParameters ) { + + cameraL.matrixWorldInverse.multiply( standingMatrixInverse ); + cameraR.matrixWorldInverse.multiply( standingMatrixInverse ); + + } + + var parent = camera.parent; + + if ( parent !== null ) { + + matrixWorldInverse.getInverse( parent.matrixWorld ); + + cameraL.matrixWorldInverse.multiply( matrixWorldInverse ); + cameraR.matrixWorldInverse.multiply( matrixWorldInverse ); + + } + + // envMap and Mirror needs camera.matrixWorld + + cameraL.matrixWorld.getInverse( cameraL.matrixWorldInverse ); + cameraR.matrixWorld.getInverse( cameraR.matrixWorldInverse ); + + cameraL.projectionMatrix.fromArray( frameData.leftProjectionMatrix ); + cameraR.projectionMatrix.fromArray( frameData.rightProjectionMatrix ); + + // HACK @mrdoob + // https://github.com/w3c/webvr/issues/203 + + cameraVR.projectionMatrix.copy( cameraL.projectionMatrix ); + + // + + var layers = device.getLayers(); + + if ( layers.length ) { + + var layer = layers[ 0 ]; + + if ( layer.leftBounds !== null && layer.leftBounds.length === 4 ) { + + cameraL.bounds.fromArray( layer.leftBounds ); + + } + + if ( layer.rightBounds !== null && layer.rightBounds.length === 4 ) { + + cameraR.bounds.fromArray( layer.rightBounds ); + + } + + } + + return cameraVR; + + }; + + this.getStandingMatrix = function () { + + return standingMatrix; + + }; + + this.submitFrame = function () { + + if ( device && device.isPresenting ) device.submitFrame(); + + }; + + this.dispose = function() { + + window.removeEventListener( 'vrdisplaypresentchange', onVRDisplayPresentChange ); + + }; + +} + /** * @author mrdoob / http://mrdoob.com/ */ @@ -19902,7 +20856,142 @@ function WebGLClipping() { } -// import { Sphere } from '../math/Sphere'; +/** + * @author thespite / http://www.twitter.com/thespite + */ + +function WebGLUtils ( gl, extensions ) { + + function convert ( p ) { + + var extension; + + if ( p === RepeatWrapping ) return gl.REPEAT; + if ( p === ClampToEdgeWrapping ) return gl.CLAMP_TO_EDGE; + if ( p === MirroredRepeatWrapping ) return gl.MIRRORED_REPEAT; + + if ( p === NearestFilter ) return gl.NEAREST; + if ( p === NearestMipMapNearestFilter ) return gl.NEAREST_MIPMAP_NEAREST; + if ( p === NearestMipMapLinearFilter ) return gl.NEAREST_MIPMAP_LINEAR; + + if ( p === LinearFilter ) return gl.LINEAR; + if ( p === LinearMipMapNearestFilter ) return gl.LINEAR_MIPMAP_NEAREST; + if ( p === LinearMipMapLinearFilter ) return gl.LINEAR_MIPMAP_LINEAR; + + if ( p === UnsignedByteType ) return gl.UNSIGNED_BYTE; + if ( p === UnsignedShort4444Type ) return gl.UNSIGNED_SHORT_4_4_4_4; + if ( p === UnsignedShort5551Type ) return gl.UNSIGNED_SHORT_5_5_5_1; + if ( p === UnsignedShort565Type ) return gl.UNSIGNED_SHORT_5_6_5; + + if ( p === ByteType ) return gl.BYTE; + if ( p === ShortType ) return gl.SHORT; + if ( p === UnsignedShortType ) return gl.UNSIGNED_SHORT; + if ( p === IntType ) return gl.INT; + if ( p === UnsignedIntType ) return gl.UNSIGNED_INT; + if ( p === FloatType ) return gl.FLOAT; + + if ( p === HalfFloatType ) { + + extension = extensions.get( 'OES_texture_half_float' ); + + if ( extension !== null ) return extension.HALF_FLOAT_OES; + + } + + if ( p === AlphaFormat ) return gl.ALPHA; + if ( p === RGBFormat ) return gl.RGB; + if ( p === RGBAFormat ) return gl.RGBA; + if ( p === LuminanceFormat ) return gl.LUMINANCE; + if ( p === LuminanceAlphaFormat ) return gl.LUMINANCE_ALPHA; + if ( p === DepthFormat ) return gl.DEPTH_COMPONENT; + if ( p === DepthStencilFormat ) return gl.DEPTH_STENCIL; + + if ( p === AddEquation ) return gl.FUNC_ADD; + if ( p === SubtractEquation ) return gl.FUNC_SUBTRACT; + if ( p === ReverseSubtractEquation ) return gl.FUNC_REVERSE_SUBTRACT; + + if ( p === ZeroFactor ) return gl.ZERO; + if ( p === OneFactor ) return gl.ONE; + if ( p === SrcColorFactor ) return gl.SRC_COLOR; + if ( p === OneMinusSrcColorFactor ) return gl.ONE_MINUS_SRC_COLOR; + if ( p === SrcAlphaFactor ) return gl.SRC_ALPHA; + if ( p === OneMinusSrcAlphaFactor ) return gl.ONE_MINUS_SRC_ALPHA; + if ( p === DstAlphaFactor ) return gl.DST_ALPHA; + if ( p === OneMinusDstAlphaFactor ) return gl.ONE_MINUS_DST_ALPHA; + + if ( p === DstColorFactor ) return gl.DST_COLOR; + if ( p === OneMinusDstColorFactor ) return gl.ONE_MINUS_DST_COLOR; + if ( p === SrcAlphaSaturateFactor ) return gl.SRC_ALPHA_SATURATE; + + if ( p === RGB_S3TC_DXT1_Format || p === RGBA_S3TC_DXT1_Format || + p === RGBA_S3TC_DXT3_Format || p === RGBA_S3TC_DXT5_Format ) { + + extension = extensions.get( 'WEBGL_compressed_texture_s3tc' ); + + if ( extension !== null ) { + + if ( p === RGB_S3TC_DXT1_Format ) return extension.COMPRESSED_RGB_S3TC_DXT1_EXT; + if ( p === RGBA_S3TC_DXT1_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT1_EXT; + if ( p === RGBA_S3TC_DXT3_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT3_EXT; + if ( p === RGBA_S3TC_DXT5_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT5_EXT; + + } + + } + + if ( p === RGB_PVRTC_4BPPV1_Format || p === RGB_PVRTC_2BPPV1_Format || + p === RGBA_PVRTC_4BPPV1_Format || p === RGBA_PVRTC_2BPPV1_Format ) { + + extension = extensions.get( 'WEBGL_compressed_texture_pvrtc' ); + + if ( extension !== null ) { + + if ( p === RGB_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_4BPPV1_IMG; + if ( p === RGB_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_2BPPV1_IMG; + if ( p === RGBA_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG; + if ( p === RGBA_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG; + + } + + } + + if ( p === RGB_ETC1_Format ) { + + extension = extensions.get( 'WEBGL_compressed_texture_etc1' ); + + if ( extension !== null ) return extension.COMPRESSED_RGB_ETC1_WEBGL; + + } + + if ( p === MinEquation || p === MaxEquation ) { + + extension = extensions.get( 'EXT_blend_minmax' ); + + if ( extension !== null ) { + + if ( p === MinEquation ) return extension.MIN_EXT; + if ( p === MaxEquation ) return extension.MAX_EXT; + + } + + } + + if ( p === UnsignedInt248Type ) { + + extension = extensions.get( 'WEBGL_depth_texture' ); + + if ( extension !== null ) return extension.UNSIGNED_INT_24_8_WEBGL; + + } + + return 0; + + } + + return { convert: convert } + +} + /** * @author supereggbert / http://www.paulbrunt.co.uk/ * @author mrdoob / http://mrdoob.com/ @@ -19927,14 +21016,13 @@ function WebGLRenderer( parameters ) { _premultipliedAlpha = parameters.premultipliedAlpha !== undefined ? parameters.premultipliedAlpha : true, _preserveDrawingBuffer = parameters.preserveDrawingBuffer !== undefined ? parameters.preserveDrawingBuffer : false; - var lights = []; + var lightsArray = []; + var shadowsArray = []; var currentRenderList = null; - var morphInfluences = new Float32Array( 8 ); - - var sprites = []; - var lensFlares = []; + var spritesArray = []; + var flaresArray = []; // public properties @@ -19982,39 +21070,37 @@ function WebGLRenderer( parameters ) { var _this = this, + _isContextLost = false, + // internal state cache - _currentProgram = null, _currentRenderTarget = null, _currentFramebuffer = null, _currentMaterialId = - 1, _currentGeometryProgram = '', + _currentCamera = null, + _currentArrayCamera = null, + _currentViewport = new Vector4(), _currentScissor = new Vector4(), _currentScissorTest = null, - _currentViewport = new Vector4(), - // _usedTextureUnits = 0, // - _clearColor = new Color( 0x000000 ), - _clearAlpha = 0, - _width = _canvas.width, _height = _canvas.height, _pixelRatio = 1, + _viewport = new Vector4( 0, 0, _width, _height ), _scissor = new Vector4( 0, 0, _width, _height ), _scissorTest = false, - _viewport = new Vector4( 0, 0, _width, _height ), - // frustum _frustum = new Frustum(), @@ -20030,31 +21116,6 @@ function WebGLRenderer( parameters ) { _projScreenMatrix = new Matrix4(), _vector3 = new Vector3(), - _matrix4 = new Matrix4(), - _matrix42 = new Matrix4(), - - // light arrays cache - - _lights = { - - hash: '', - - ambient: [ 0, 0, 0 ], - directional: [], - directionalShadowMap: [], - directionalShadowMatrix: [], - spot: [], - spotShadowMap: [], - spotShadowMatrix: [], - rectArea: [], - point: [], - pointShadowMap: [], - pointShadowMatrix: [], - hemi: [], - - shadows: [] - - }, // info @@ -20081,6 +21142,11 @@ function WebGLRenderer( parameters ) { }; + function getTargetPixelRatio() { + + return _currentRenderTarget === null ? _pixelRatio : 1; + + } // initialize @@ -20126,6 +21192,7 @@ function WebGLRenderer( parameters ) { } _canvas.addEventListener( 'webglcontextlost', onContextLost, false ); + _canvas.addEventListener( 'webglcontextrestored', onContextRestore, false ); } catch ( error ) { @@ -20133,95 +21200,82 @@ function WebGLRenderer( parameters ) { } - var extensions = new WebGLExtensions( _gl ); - - extensions.get( 'WEBGL_depth_texture' ); - extensions.get( 'OES_texture_float' ); - extensions.get( 'OES_texture_float_linear' ); - extensions.get( 'OES_texture_half_float' ); - extensions.get( 'OES_texture_half_float_linear' ); - extensions.get( 'OES_standard_derivatives' ); - extensions.get( 'ANGLE_instanced_arrays' ); - - if ( extensions.get( 'OES_element_index_uint' ) ) { - - BufferGeometry.MaxIndex = 4294967296; - - } - - var capabilities = new WebGLCapabilities( _gl, extensions, parameters ); + var extensions, capabilities, state; + var properties, textures, attributes, geometries, objects, lights; + var programCache, renderLists; - var state = new WebGLState( _gl, extensions, paramThreeToGL ); + var background, morphtargets, bufferRenderer, indexedBufferRenderer; + var flareRenderer, spriteRenderer; - var properties = new WebGLProperties(); - var textures = new WebGLTextures( _gl, extensions, state, properties, capabilities, paramThreeToGL, _infoMemory ); - var attributes = new WebGLAttributes( _gl ); - var geometries = new WebGLGeometries( _gl, attributes, _infoMemory ); - var objects = new WebGLObjects( _gl, geometries, _infoRender ); - var programCache = new WebGLPrograms( this, capabilities ); - var lightCache = new WebGLLights(); - var renderLists = new WebGLRenderLists(); + var utils; - this.info.programs = programCache.programs; + function initGLContext() { - var bufferRenderer = new WebGLBufferRenderer( _gl, extensions, _infoRender ); - var indexedBufferRenderer = new WebGLIndexedBufferRenderer( _gl, extensions, _infoRender ); - - // + extensions = new WebGLExtensions( _gl ); + extensions.get( 'WEBGL_depth_texture' ); + extensions.get( 'OES_texture_float' ); + extensions.get( 'OES_texture_float_linear' ); + extensions.get( 'OES_texture_half_float' ); + extensions.get( 'OES_texture_half_float_linear' ); + extensions.get( 'OES_standard_derivatives' ); + extensions.get( 'ANGLE_instanced_arrays' ); - var backgroundPlaneCamera, backgroundPlaneMesh; - var backgroundBoxCamera, backgroundBoxMesh; - - // - - function getTargetPixelRatio() { + if ( extensions.get( 'OES_element_index_uint' ) ) { - return _currentRenderTarget === null ? _pixelRatio : 1; + BufferGeometry.MaxIndex = 4294967296; - } + } - function setDefaultGLState() { + utils = new WebGLUtils( _gl, extensions ); - state.init(); + capabilities = new WebGLCapabilities( _gl, extensions, parameters ); + state = new WebGLState( _gl, extensions, utils ); state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ) ); state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ) ); - state.buffers.color.setClear( _clearColor.r, _clearColor.g, _clearColor.b, _clearAlpha, _premultipliedAlpha ); + properties = new WebGLProperties(); + textures = new WebGLTextures( _gl, extensions, state, properties, capabilities, utils, _infoMemory ); + attributes = new WebGLAttributes( _gl ); + geometries = new WebGLGeometries( _gl, attributes, _infoMemory ); + objects = new WebGLObjects( geometries, _infoRender ); + morphtargets = new WebGLMorphtargets( _gl ); + programCache = new WebGLPrograms( _this, extensions, capabilities ); + lights = new WebGLLights(); + renderLists = new WebGLRenderLists(); - } + background = new WebGLBackground( _this, state, geometries, _premultipliedAlpha ); - function resetGLState() { + bufferRenderer = new WebGLBufferRenderer( _gl, extensions, _infoRender ); + indexedBufferRenderer = new WebGLIndexedBufferRenderer( _gl, extensions, _infoRender ); - _currentProgram = null; - _currentCamera = null; + flareRenderer = new WebGLFlareRenderer( _this, _gl, state, textures, capabilities ); + spriteRenderer = new WebGLSpriteRenderer( _this, _gl, state, textures, capabilities ); - _currentGeometryProgram = ''; - _currentMaterialId = - 1; + _this.info.programs = programCache.programs; - state.reset(); + _this.context = _gl; + _this.capabilities = capabilities; + _this.extensions = extensions; + _this.properties = properties; + _this.renderLists = renderLists; + _this.state = state; } - setDefaultGLState(); - - this.context = _gl; - this.capabilities = capabilities; - this.extensions = extensions; - this.properties = properties; - this.state = state; + initGLContext(); - // shadow map + // vr - var shadowMap = new WebGLShadowMap( this, _lights, objects, capabilities ); + var vr = new WebVRManager( _this ); - this.shadowMap = shadowMap; + this.vr = vr; + // shadow map - // Plugins + var shadowMap = new WebGLShadowMap( _this, objects, capabilities.maxTextureSize ); - var spritePlugin = new SpritePlugin( this, sprites ); - var lensFlarePlugin = new LensFlarePlugin( this, lensFlares ); + this.shadowMap = shadowMap; // API @@ -20244,15 +21298,10 @@ function WebGLRenderer( parameters ) { }; - this.getMaxAnisotropy = function () { - - return capabilities.getMaxAnisotropy(); + this.forceContextRestore = function () { - }; - - this.getPrecision = function () { - - return capabilities.precision; + var extension = extensions.get( 'WEBGL_lose_context' ); + if ( extension ) extension.restoreContext(); }; @@ -20268,7 +21317,7 @@ function WebGLRenderer( parameters ) { _pixelRatio = value; - this.setSize( _viewport.z, _viewport.w, false ); + this.setSize( _width, _height, false ); }; @@ -20283,6 +21332,15 @@ function WebGLRenderer( parameters ) { this.setSize = function ( width, height, updateStyle ) { + var device = vr.getDevice(); + + if ( device && device.isPresenting ) { + + console.warn( 'THREE.WebGLRenderer: Can\'t change size while VR device is presenting.' ); + return; + + } + _width = width; _height = height; @@ -20300,55 +21358,55 @@ function WebGLRenderer( parameters ) { }; - this.setViewport = function ( x, y, width, height ) { + this.getDrawingBufferSize = function () { - state.viewport( _viewport.set( x, y, width, height ) ); + return { + width: _width * _pixelRatio, + height: _height * _pixelRatio + }; }; - this.setScissor = function ( x, y, width, height ) { + this.setDrawingBufferSize = function ( width, height, pixelRatio ) { - state.scissor( _scissor.set( x, y, width, height ) ); + _width = width; + _height = height; - }; + _pixelRatio = pixelRatio; - this.setScissorTest = function ( boolean ) { + _canvas.width = width * pixelRatio; + _canvas.height = height * pixelRatio; - state.setScissorTest( _scissorTest = boolean ); + this.setViewport( 0, 0, width, height ); }; - // Clearing - - this.getClearColor = function () { + this.setViewport = function ( x, y, width, height ) { - return _clearColor; + _viewport.set( x, _height - y - height, width, height ); + state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ) ); }; - this.setClearColor = function ( color, alpha ) { - - _clearColor.set( color ); - - _clearAlpha = alpha !== undefined ? alpha : 1; + this.setScissor = function ( x, y, width, height ) { - state.buffers.color.setClear( _clearColor.r, _clearColor.g, _clearColor.b, _clearAlpha, _premultipliedAlpha ); + _scissor.set( x, _height - y - height, width, height ); + state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ) ); }; - this.getClearAlpha = function () { + this.setScissorTest = function ( boolean ) { - return _clearAlpha; + state.setScissorTest( _scissorTest = boolean ); }; - this.setClearAlpha = function ( alpha ) { - - _clearAlpha = alpha; - - state.buffers.color.setClear( _clearColor.r, _clearColor.g, _clearColor.b, _clearAlpha, _premultipliedAlpha ); + // Clearing - }; + this.getClearColor = background.getClearColor; + this.setClearColor = background.setClearColor; + this.getClearAlpha = background.getClearAlpha; + this.setClearAlpha = background.setClearAlpha; this.clear = function ( color, depth, stencil ) { @@ -20387,16 +21445,17 @@ function WebGLRenderer( parameters ) { }; - // Reset - - this.resetGLState = resetGLState; + // this.dispose = function () { _canvas.removeEventListener( 'webglcontextlost', onContextLost, false ); + _canvas.removeEventListener( 'webglcontextrestored', onContextRestore, false ); renderLists.dispose(); + vr.dispose(); + }; // Events @@ -20405,11 +21464,19 @@ function WebGLRenderer( parameters ) { event.preventDefault(); - resetGLState(); - setDefaultGLState(); + console.log( 'THREE.WebGLRenderer: Context Lost.' ); - properties.clear(); - objects.clear(); + _isContextLost = true; + + } + + function onContextRestore( event ) { + + console.log( 'THREE.WebGLRenderer: Context Restored.' ); + + _isContextLost = false; + + initGLContext(); } @@ -20490,7 +21557,7 @@ function WebGLRenderer( parameters ) { if ( ! material.isMeshPhongMaterial && ! material.isMeshStandardMaterial && ! material.isMeshNormalMaterial && - material.shading === FlatShading ) { + material.flatShading === true ) { for ( var i = 0, l = object.count * 3; i < l; i += 9 ) { @@ -20531,7 +21598,7 @@ function WebGLRenderer( parameters ) { state.enableAttribute( programAttributes.uv ); - _gl.vertexAttribPointer( attributes.uv, 2, _gl.FLOAT, false, 0, 0 ); + _gl.vertexAttribPointer( programAttributes.uv, 2, _gl.FLOAT, false, 0, 0 ); } @@ -20554,12 +21621,6 @@ function WebGLRenderer( parameters ) { }; - function absNumericalSort( a, b ) { - - return Math.abs( b[ 0 ] ) - Math.abs( a[ 0 ] ); - - } - this.renderBufferDirect = function ( camera, fog, geometry, material, object, group ) { state.setMaterial( material ); @@ -20576,61 +21637,9 @@ function WebGLRenderer( parameters ) { } - // morph targets - - var morphTargetInfluences = object.morphTargetInfluences; - - if ( morphTargetInfluences !== undefined ) { - - // TODO Remove allocations - - var activeInfluences = []; - - for ( var i = 0, l = morphTargetInfluences.length; i < l; i ++ ) { - - var influence = morphTargetInfluences[ i ]; - activeInfluences.push( [ influence, i ] ); - - } - - activeInfluences.sort( absNumericalSort ); - - if ( activeInfluences.length > 8 ) { - - activeInfluences.length = 8; - - } - - var morphAttributes = geometry.morphAttributes; - - for ( var i = 0, l = activeInfluences.length; i < l; i ++ ) { - - var influence = activeInfluences[ i ]; - morphInfluences[ i ] = influence[ 0 ]; - - if ( influence[ 0 ] !== 0 ) { - - var index = influence[ 1 ]; - - if ( material.morphTargets === true && morphAttributes.position ) geometry.addAttribute( 'morphTarget' + i, morphAttributes.position[ index ] ); - if ( material.morphNormals === true && morphAttributes.normal ) geometry.addAttribute( 'morphNormal' + i, morphAttributes.normal[ index ] ); - - } else { - - if ( material.morphTargets === true ) geometry.removeAttribute( 'morphTarget' + i ); - if ( material.morphNormals === true ) geometry.removeAttribute( 'morphNormal' + i ); - - } - - } - - for ( var i = activeInfluences.length, il = morphInfluences.length; i < il; i ++ ) { + if ( object.morphTargetInfluences ) { - morphInfluences[ i ] = 0.0; - - } - - program.getUniforms().setValue( _gl, 'morphTargetInfluences', morphInfluences ); + morphtargets.update( object, geometry, material, program ); updateBuffers = true; @@ -20649,12 +21658,15 @@ function WebGLRenderer( parameters ) { } + var attribute; var renderer = bufferRenderer; if ( index !== null ) { + attribute = attributes.get( index ); + renderer = indexedBufferRenderer; - renderer.setIndex( index ); + renderer.setIndex( attribute ); } @@ -20664,7 +21676,7 @@ function WebGLRenderer( parameters ) { if ( index !== null ) { - _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, attributes.get( index ).buffer ); + _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, attribute.buffer ); } @@ -20807,11 +21819,15 @@ function WebGLRenderer( parameters ) { var normalized = geometryAttribute.normalized; var size = geometryAttribute.itemSize; - var attributeProperties = attributes.get( geometryAttribute ); + var attribute = attributes.get( geometryAttribute ); + + // TODO Attribute may not be available on context restore - var buffer = attributeProperties.buffer; - var type = attributeProperties.type; - var bytesPerElement = attributeProperties.bytesPerElement; + if ( attribute === undefined ) continue; + + var buffer = attribute.buffer; + var type = attribute.type; + var bytesPerElement = attribute.bytesPerElement; if ( geometryAttribute.isInterleavedBufferAttribute ) { @@ -20902,19 +21918,26 @@ function WebGLRenderer( parameters ) { this.compile = function ( scene, camera ) { - lights = []; + lightsArray.length = 0; + shadowsArray.length = 0; scene.traverse( function ( object ) { if ( object.isLight ) { - lights.push( object ); + lightsArray.push( object ); + + if ( object.castShadow ) { + + shadowsArray.push( object ); + + } } } ); - setupLights( lights, camera ); + lights.setup( lightsArray, shadowsArray, camera ); scene.traverse( function ( object ) { @@ -20940,17 +21963,46 @@ function WebGLRenderer( parameters ) { }; + // Animation Loop + + var isAnimating = false; + var onAnimationFrame = null; + + function start() { + + if ( isAnimating ) return; + ( vr.getDevice() || window ).requestAnimationFrame( loop ); + isAnimating = true; + + } + + function loop( time ) { + + if ( onAnimationFrame !== null ) onAnimationFrame( time ); + ( vr.getDevice() || window ).requestAnimationFrame( loop ); + + } + + this.animate = function ( callback ) { + + onAnimationFrame = callback; + start(); + + }; + // Rendering this.render = function ( scene, camera, renderTarget, forceClear ) { - if ( camera !== undefined && camera.isCamera !== true ) { + if ( ! ( camera && camera.isCamera ) ) { console.error( 'THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.' ); return; } + if ( _isContextLost ) return; + // reset caching for this frame _currentGeometryProgram = ''; @@ -20963,18 +22015,22 @@ function WebGLRenderer( parameters ) { // update camera matrices and frustum - camera.onBeforeRender( _this ); - if ( camera.parent === null ) camera.updateMatrixWorld(); - camera.matrixWorldInverse.getInverse( camera.matrixWorld ); + if ( vr.enabled ) { + + camera = vr.getCamera( camera ); + + } _projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse ); _frustum.setFromMatrix( _projScreenMatrix ); - lights.length = 0; - sprites.length = 0; - lensFlares.length = 0; + lightsArray.length = 0; + shadowsArray.length = 0; + + spritesArray.length = 0; + flaresArray.length = 0; _localClippingEnabled = this.localClippingEnabled; _clippingEnabled = _clipping.init( this.clippingPlanes, _localClippingEnabled, camera ); @@ -20984,8 +22040,6 @@ function WebGLRenderer( parameters ) { projectObject( scene, camera, _this.sortObjects ); - currentRenderList.finish(); - if ( _this.sortObjects === true ) { currentRenderList.sort(); @@ -20996,11 +22050,9 @@ function WebGLRenderer( parameters ) { if ( _clippingEnabled ) _clipping.beginShadows(); - setupShadows( lights ); + shadowMap.render( shadowsArray, scene, camera ); - shadowMap.render( scene, camera ); - - setupLights( lights, camera ); + lights.setup( lightsArray, shadowsArray, camera ); if ( _clippingEnabled ) _clipping.endShadows(); @@ -21022,81 +22074,9 @@ function WebGLRenderer( parameters ) { // - var background = scene.background; - - if ( background === null ) { - - state.buffers.color.setClear( _clearColor.r, _clearColor.g, _clearColor.b, _clearAlpha, _premultipliedAlpha ); - - } else if ( background && background.isColor ) { - - state.buffers.color.setClear( background.r, background.g, background.b, 1, _premultipliedAlpha ); - forceClear = true; - - } - - if ( this.autoClear || forceClear ) { - - this.clear( this.autoClearColor, this.autoClearDepth, this.autoClearStencil ); - - } - - if ( background && background.isCubeTexture ) { - - if ( backgroundBoxCamera === undefined ) { - - backgroundBoxCamera = new PerspectiveCamera(); - - backgroundBoxMesh = new Mesh( - new BoxBufferGeometry( 5, 5, 5 ), - new ShaderMaterial( { - uniforms: ShaderLib.cube.uniforms, - vertexShader: ShaderLib.cube.vertexShader, - fragmentShader: ShaderLib.cube.fragmentShader, - side: BackSide, - depthTest: false, - depthWrite: false, - fog: false - } ) - ); - - } - - backgroundBoxCamera.projectionMatrix.copy( camera.projectionMatrix ); - - backgroundBoxCamera.matrixWorld.extractRotation( camera.matrixWorld ); - backgroundBoxCamera.matrixWorldInverse.getInverse( backgroundBoxCamera.matrixWorld ); - + background.render( currentRenderList, scene, camera, forceClear ); - backgroundBoxMesh.material.uniforms[ "tCube" ].value = background; - backgroundBoxMesh.modelViewMatrix.multiplyMatrices( backgroundBoxCamera.matrixWorldInverse, backgroundBoxMesh.matrixWorld ); - - objects.update( backgroundBoxMesh ); - - _this.renderBufferDirect( backgroundBoxCamera, null, backgroundBoxMesh.geometry, backgroundBoxMesh.material, backgroundBoxMesh, null ); - - } else if ( background && background.isTexture ) { - - if ( backgroundPlaneCamera === undefined ) { - - backgroundPlaneCamera = new OrthographicCamera( - 1, 1, 1, - 1, 0, 1 ); - - backgroundPlaneMesh = new Mesh( - new PlaneBufferGeometry( 2, 2 ), - new MeshBasicMaterial( { depthTest: false, depthWrite: false, fog: false } ) - ); - - } - - backgroundPlaneMesh.material.map = background; - - objects.update( backgroundPlaneMesh ); - - _this.renderBufferDirect( backgroundPlaneCamera, null, backgroundPlaneMesh.geometry, backgroundPlaneMesh.material, backgroundPlaneMesh, null ); - - } - - // + // render scene var opaqueObjects = currentRenderList.opaque; var transparentObjects = currentRenderList.transparent; @@ -21120,10 +22100,10 @@ function WebGLRenderer( parameters ) { } - // custom render plugins (post pass) + // custom renderers - spritePlugin.render( scene, camera ); - lensFlarePlugin.render( scene, camera, _currentViewport ); + spriteRenderer.render( spritesArray, scene, camera ); + flareRenderer.render( flaresArray, scene, camera, _currentViewport ); // Generate mipmap if we're using any kind of mipmap filtering @@ -21139,13 +22119,13 @@ function WebGLRenderer( parameters ) { state.buffers.depth.setMask( true ); state.buffers.color.setMask( true ); - if ( camera.isArrayCamera && camera.enabled ) { + state.setPolygonOffset( false ); - _this.setScissorTest( false ); + if ( vr.enabled ) { - } + vr.submitFrame(); - camera.onAfterRender( _this ); + } // _gl.finish(); @@ -21208,7 +22188,7 @@ function WebGLRenderer( parameters ) { function projectObject( object, camera, sortObjects ) { - if ( ! object.visible ) return; + if ( object.visible === false ) return; var visible = object.layers.test( camera.layers ); @@ -21216,19 +22196,25 @@ function WebGLRenderer( parameters ) { if ( object.isLight ) { - lights.push( object ); + lightsArray.push( object ); + + if ( object.castShadow ) { + + shadowsArray.push( object ); + + } } else if ( object.isSprite ) { if ( ! object.frustumCulled || _frustum.intersectsSprite( object ) ) { - sprites.push( object ); + spritesArray.push( object ); } } else if ( object.isLensFlare ) { - lensFlares.push( object ); + flaresArray.push( object ); } else if ( object.isImmediateRenderObject ) { @@ -21311,45 +22297,49 @@ function WebGLRenderer( parameters ) { var material = overrideMaterial === undefined ? renderItem.material : overrideMaterial; var group = renderItem.group; - object.onBeforeRender( _this, scene, camera, geometry, material, group ); + if ( camera.isArrayCamera ) { - if ( camera.isArrayCamera && camera.enabled ) { + _currentArrayCamera = camera; var cameras = camera.cameras; for ( var j = 0, jl = cameras.length; j < jl; j ++ ) { var camera2 = cameras[ j ]; - var bounds = camera2.bounds; - _this.setViewport( - bounds.x * _width * _pixelRatio, bounds.y * _height * _pixelRatio, - bounds.z * _width * _pixelRatio, bounds.w * _height * _pixelRatio - ); - _this.setScissor( - bounds.x * _width * _pixelRatio, bounds.y * _height * _pixelRatio, - bounds.z * _width * _pixelRatio, bounds.w * _height * _pixelRatio - ); - _this.setScissorTest( true ); + if ( object.layers.test( camera2.layers ) ) { + + var bounds = camera2.bounds; - renderObject( object, scene, camera2, geometry, material, group ); + var x = bounds.x * _width; + var y = bounds.y * _height; + var width = bounds.z * _width; + var height = bounds.w * _height; + + state.viewport( _currentViewport.set( x, y, width, height ).multiplyScalar( _pixelRatio ) ); + + renderObject( object, scene, camera2, geometry, material, group ); + + } } } else { + _currentArrayCamera = null; + renderObject( object, scene, camera, geometry, material, group ); } - object.onAfterRender( _this, scene, camera, geometry, material, group ); - } } function renderObject( object, scene, camera, geometry, material, group ) { + object.onBeforeRender( _this, scene, camera, geometry, material, group ); + object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld ); object.normalMatrix.getNormalMatrix( object.modelViewMatrix ); @@ -21369,6 +22359,8 @@ function WebGLRenderer( parameters ) { } + object.onAfterRender( _this, scene, camera, geometry, material, group ); + } function initMaterial( material, fog, object ) { @@ -21376,7 +22368,7 @@ function WebGLRenderer( parameters ) { var materialProperties = properties.get( material ); var parameters = programCache.getParameters( - material, _lights, fog, _clipping.numPlanes, _clipping.numIntersection, object ); + material, lights.state, shadowsArray, fog, _clipping.numPlanes, _clipping.numIntersection, object ); var code = programCache.getProgramCode( material, parameters ); @@ -21411,7 +22403,7 @@ function WebGLRenderer( parameters ) { var shader = ShaderLib[ parameters.shaderID ]; - materialProperties.__webglShader = { + materialProperties.shader = { name: material.type, uniforms: UniformsUtils.clone( shader.uniforms ), vertexShader: shader.vertexShader, @@ -21420,7 +22412,7 @@ function WebGLRenderer( parameters ) { } else { - materialProperties.__webglShader = { + materialProperties.shader = { name: material.type, uniforms: material.uniforms, vertexShader: material.vertexShader, @@ -21429,9 +22421,9 @@ function WebGLRenderer( parameters ) { } - material.__webglShader = materialProperties.__webglShader; + material.onBeforeCompile( materialProperties.shader ); - program = programCache.acquireProgram( material, parameters, code ); + program = programCache.acquireProgram( material, materialProperties.shader, parameters, code ); materialProperties.program = program; material.program = program; @@ -21472,7 +22464,7 @@ function WebGLRenderer( parameters ) { } - var uniforms = materialProperties.__webglShader.uniforms; + var uniforms = materialProperties.shader.uniforms; if ( ! material.isShaderMaterial && ! material.isRawShaderMaterial || @@ -21488,25 +22480,25 @@ function WebGLRenderer( parameters ) { // store the light setup it was created for - materialProperties.lightsHash = _lights.hash; + materialProperties.lightsHash = lights.state.hash; if ( material.lights ) { // wire up the material to this renderer's lighting state - uniforms.ambientLightColor.value = _lights.ambient; - uniforms.directionalLights.value = _lights.directional; - uniforms.spotLights.value = _lights.spot; - uniforms.rectAreaLights.value = _lights.rectArea; - uniforms.pointLights.value = _lights.point; - uniforms.hemisphereLights.value = _lights.hemi; - - uniforms.directionalShadowMap.value = _lights.directionalShadowMap; - uniforms.directionalShadowMatrix.value = _lights.directionalShadowMatrix; - uniforms.spotShadowMap.value = _lights.spotShadowMap; - uniforms.spotShadowMatrix.value = _lights.spotShadowMatrix; - uniforms.pointShadowMap.value = _lights.pointShadowMap; - uniforms.pointShadowMatrix.value = _lights.pointShadowMatrix; + uniforms.ambientLightColor.value = lights.state.ambient; + uniforms.directionalLights.value = lights.state.directional; + uniforms.spotLights.value = lights.state.spot; + uniforms.rectAreaLights.value = lights.state.rectArea; + uniforms.pointLights.value = lights.state.point; + uniforms.hemisphereLights.value = lights.state.hemi; + + uniforms.directionalShadowMap.value = lights.state.directionalShadowMap; + uniforms.directionalShadowMatrix.value = lights.state.directionalShadowMatrix; + uniforms.spotShadowMap.value = lights.state.spotShadowMap; + uniforms.spotShadowMatrix.value = lights.state.spotShadowMatrix; + uniforms.pointShadowMap.value = lights.state.pointShadowMap; + uniforms.pointShadowMatrix.value = lights.state.pointShadowMatrix; // TODO (abelnation): add area lights shadow info to uniforms } @@ -21554,7 +22546,7 @@ function WebGLRenderer( parameters ) { material.needsUpdate = true; - } else if ( material.lights && materialProperties.lightsHash !== _lights.hash ) { + } else if ( material.lights && materialProperties.lightsHash !== lights.state.hash ) { material.needsUpdate = true; @@ -21581,12 +22573,9 @@ function WebGLRenderer( parameters ) { var program = materialProperties.program, p_uniforms = program.getUniforms(), - m_uniforms = materialProperties.__webglShader.uniforms; + m_uniforms = materialProperties.shader.uniforms; - if ( program.id !== _currentProgram ) { - - _gl.useProgram( program.program ); - _currentProgram = program.id; + if ( state.useProgram( program.program ) ) { refreshProgram = true; refreshMaterial = true; @@ -21613,10 +22602,11 @@ function WebGLRenderer( parameters ) { } + // Avoid unneeded uniform updates per ArrayCamera's sub-camera - if ( camera !== _currentCamera ) { + if ( _currentCamera !== ( _currentArrayCamera || camera ) ) { - _currentCamera = camera; + _currentCamera = ( _currentArrayCamera || camera ); // lighting uniforms depend on the camera so enforce an update // now, in case this material supports lights - or later, when @@ -21657,9 +22647,6 @@ function WebGLRenderer( parameters ) { } - p_uniforms.setValue( _gl, 'toneMappingExposure', _this.toneMappingExposure ); - p_uniforms.setValue( _gl, 'toneMappingWhitePoint', _this.toneMappingWhitePoint ); - } // skinning uniforms must be set even if material didn't change @@ -21719,6 +22706,9 @@ function WebGLRenderer( parameters ) { if ( refreshMaterial ) { + p_uniforms.setValue( _gl, 'toneMappingExposure', _this.toneMappingExposure ); + p_uniforms.setValue( _gl, 'toneMappingWhitePoint', _this.toneMappingWhitePoint ); + if ( material.lights ) { // the current material requires lighting info @@ -21742,66 +22732,77 @@ function WebGLRenderer( parameters ) { } - if ( material.isMeshBasicMaterial || - material.isMeshLambertMaterial || - material.isMeshPhongMaterial || - material.isMeshStandardMaterial || - material.isMeshNormalMaterial || - material.isMeshDepthMaterial ) { + if ( material.isMeshBasicMaterial ) { refreshUniformsCommon( m_uniforms, material ); - } - - // refresh single material specific uniforms - - if ( material.isLineBasicMaterial ) { + } else if ( material.isMeshLambertMaterial ) { - refreshUniformsLine( m_uniforms, material ); + refreshUniformsCommon( m_uniforms, material ); + refreshUniformsLambert( m_uniforms, material ); - } else if ( material.isLineDashedMaterial ) { + } else if ( material.isMeshPhongMaterial ) { - refreshUniformsLine( m_uniforms, material ); - refreshUniformsDash( m_uniforms, material ); + refreshUniformsCommon( m_uniforms, material ); - } else if ( material.isPointsMaterial ) { + if ( material.isMeshToonMaterial ) { - refreshUniformsPoints( m_uniforms, material ); + refreshUniformsToon( m_uniforms, material ); - } else if ( material.isMeshLambertMaterial ) { + } else { - refreshUniformsLambert( m_uniforms, material ); + refreshUniformsPhong( m_uniforms, material ); - } else if ( material.isMeshToonMaterial ) { + } - refreshUniformsToon( m_uniforms, material ); + } else if ( material.isMeshStandardMaterial ) { - } else if ( material.isMeshPhongMaterial ) { + refreshUniformsCommon( m_uniforms, material ); - refreshUniformsPhong( m_uniforms, material ); + if ( material.isMeshPhysicalMaterial ) { - } else if ( material.isMeshPhysicalMaterial ) { + refreshUniformsPhysical( m_uniforms, material ); - refreshUniformsPhysical( m_uniforms, material ); + } else { - } else if ( material.isMeshStandardMaterial ) { + refreshUniformsStandard( m_uniforms, material ); - refreshUniformsStandard( m_uniforms, material ); + } } else if ( material.isMeshDepthMaterial ) { - if ( material.displacementMap ) { + refreshUniformsCommon( m_uniforms, material ); + refreshUniformsDepth( m_uniforms, material ); - m_uniforms.displacementMap.value = material.displacementMap; - m_uniforms.displacementScale.value = material.displacementScale; - m_uniforms.displacementBias.value = material.displacementBias; + } else if ( material.isMeshDistanceMaterial ) { - } + refreshUniformsCommon( m_uniforms, material ); + refreshUniformsDistance( m_uniforms, material ); } else if ( material.isMeshNormalMaterial ) { + refreshUniformsCommon( m_uniforms, material ); refreshUniformsNormal( m_uniforms, material ); + } else if ( material.isLineBasicMaterial ) { + + refreshUniformsLine( m_uniforms, material ); + + if ( material.isLineDashedMaterial ) { + + refreshUniformsDash( m_uniforms, material ); + + } + + } else if ( material.isPointsMaterial ) { + + refreshUniformsPoints( m_uniforms, material ); + + } else if ( material.isShadowMaterial ) { + + m_uniforms.color.value = material.color; + m_uniforms.opacity.value = material.opacity; + } // RectAreaLight Texture @@ -21832,7 +22833,11 @@ function WebGLRenderer( parameters ) { uniforms.opacity.value = material.opacity; - uniforms.diffuse.value = material.color; + if ( material.color ) { + + uniforms.diffuse.value = material.color; + + } if ( material.emissive ) { @@ -21840,9 +22845,38 @@ function WebGLRenderer( parameters ) { } - uniforms.map.value = material.map; - uniforms.specularMap.value = material.specularMap; - uniforms.alphaMap.value = material.alphaMap; + if ( material.map ) { + + uniforms.map.value = material.map; + + } + + if ( material.alphaMap ) { + + uniforms.alphaMap.value = material.alphaMap; + + } + + if ( material.specularMap ) { + + uniforms.specularMap.value = material.specularMap; + + } + + if ( material.envMap ) { + + uniforms.envMap.value = material.envMap; + + // don't flip CubeTexture envMaps, flip everything else: + // WebGLRenderTargetCube will be flipped for backwards compatibility + // WebGLRenderTargetCube.texture will be flipped because it's a Texture and NOT a CubeTexture + // this check must be handled differently, or removed entirely, if WebGLRenderTargetCube uses a CubeTexture in the future + uniforms.flipEnvMap.value = ( ! ( material.envMap && material.envMap.isCubeTexture ) ) ? 1 : - 1; + + uniforms.reflectivity.value = material.reflectivity; + uniforms.refractionRatio.value = material.refractionRatio; + + } if ( material.lightMap ) { @@ -21915,23 +22949,18 @@ function WebGLRenderer( parameters ) { } - var offset = uvScaleMap.offset; - var repeat = uvScaleMap.repeat; + if ( uvScaleMap.matrixAutoUpdate === true ) { - uniforms.offsetRepeat.value.set( offset.x, offset.y, repeat.x, repeat.y ); + var offset = uvScaleMap.offset; + var repeat = uvScaleMap.repeat; + var rotation = uvScaleMap.rotation; + uvScaleMap.matrix.setUvTransform( offset.x, offset.y, repeat.x, repeat.y, rotation, 0.5, 0.5 ); - } - - uniforms.envMap.value = material.envMap; + } - // don't flip CubeTexture envMaps, flip everything else: - // WebGLRenderTargetCube will be flipped for backwards compatibility - // WebGLRenderTargetCube.texture will be flipped because it's a Texture and NOT a CubeTexture - // this check must be handled differently, or removed entirely, if WebGLRenderTargetCube uses a CubeTexture in the future - uniforms.flipEnvMap.value = ( ! ( material.envMap && material.envMap.isCubeTexture ) ) ? 1 : - 1; + uniforms.uvTransform.value.copy( uvScaleMap.matrix ); - uniforms.reflectivity.value = material.reflectivity; - uniforms.refractionRatio.value = material.refractionRatio; + } } @@ -21961,10 +22990,16 @@ function WebGLRenderer( parameters ) { if ( material.map !== null ) { - var offset = material.map.offset; - var repeat = material.map.repeat; + if ( material.map.matrixAutoUpdate === true ) { - uniforms.offsetRepeat.value.set( offset.x, offset.y, repeat.x, repeat.y ); + var offset = material.map.offset; + var repeat = material.map.repeat; + var rotation = material.map.rotation; + material.map.matrix.setUvTransform( offset.x, offset.y, repeat.x, repeat.y, rotation, 0.5, 0.5 ); + + } + + uniforms.uvTransform.value.copy( material.map.matrix ); } @@ -22107,6 +23142,34 @@ function WebGLRenderer( parameters ) { } + function refreshUniformsDepth( uniforms, material ) { + + if ( material.displacementMap ) { + + uniforms.displacementMap.value = material.displacementMap; + uniforms.displacementScale.value = material.displacementScale; + uniforms.displacementBias.value = material.displacementBias; + + } + + } + + function refreshUniformsDistance( uniforms, material ) { + + if ( material.displacementMap ) { + + uniforms.displacementMap.value = material.displacementMap; + uniforms.displacementScale.value = material.displacementScale; + uniforms.displacementBias.value = material.displacementBias; + + } + + uniforms.referencePosition.value.copy( material.referencePosition ); + uniforms.nearDistance.value = material.nearDistance; + uniforms.farDistance.value = material.farDistance; + + } + function refreshUniformsNormal( uniforms, material ) { if ( material.bumpMap ) { @@ -22147,224 +23210,6 @@ function WebGLRenderer( parameters ) { } - // Lighting - - function setupShadows( lights ) { - - var lightShadowsLength = 0; - - for ( var i = 0, l = lights.length; i < l; i ++ ) { - - var light = lights[ i ]; - - if ( light.castShadow ) { - - _lights.shadows[ lightShadowsLength ] = light; - lightShadowsLength ++; - - } - - } - - _lights.shadows.length = lightShadowsLength; - - } - - function setupLights( lights, camera ) { - - var l, ll, light, shadow, - r = 0, g = 0, b = 0, - color, - intensity, - distance, - shadowMap, - - viewMatrix = camera.matrixWorldInverse, - - directionalLength = 0, - pointLength = 0, - spotLength = 0, - rectAreaLength = 0, - hemiLength = 0; - - for ( l = 0, ll = lights.length; l < ll; l ++ ) { - - light = lights[ l ]; - - color = light.color; - intensity = light.intensity; - distance = light.distance; - - shadowMap = ( light.shadow && light.shadow.map ) ? light.shadow.map.texture : null; - - if ( light.isAmbientLight ) { - - r += color.r * intensity; - g += color.g * intensity; - b += color.b * intensity; - - } else if ( light.isDirectionalLight ) { - - var uniforms = lightCache.get( light ); - - uniforms.color.copy( light.color ).multiplyScalar( light.intensity ); - uniforms.direction.setFromMatrixPosition( light.matrixWorld ); - _vector3.setFromMatrixPosition( light.target.matrixWorld ); - uniforms.direction.sub( _vector3 ); - uniforms.direction.transformDirection( viewMatrix ); - - uniforms.shadow = light.castShadow; - - if ( light.castShadow ) { - - shadow = light.shadow; - - uniforms.shadowBias = shadow.bias; - uniforms.shadowRadius = shadow.radius; - uniforms.shadowMapSize = shadow.mapSize; - - } - - _lights.directionalShadowMap[ directionalLength ] = shadowMap; - _lights.directionalShadowMatrix[ directionalLength ] = light.shadow.matrix; - _lights.directional[ directionalLength ] = uniforms; - - directionalLength ++; - - } else if ( light.isSpotLight ) { - - var uniforms = lightCache.get( light ); - - uniforms.position.setFromMatrixPosition( light.matrixWorld ); - uniforms.position.applyMatrix4( viewMatrix ); - - uniforms.color.copy( color ).multiplyScalar( intensity ); - uniforms.distance = distance; - - uniforms.direction.setFromMatrixPosition( light.matrixWorld ); - _vector3.setFromMatrixPosition( light.target.matrixWorld ); - uniforms.direction.sub( _vector3 ); - uniforms.direction.transformDirection( viewMatrix ); - - uniforms.coneCos = Math.cos( light.angle ); - uniforms.penumbraCos = Math.cos( light.angle * ( 1 - light.penumbra ) ); - uniforms.decay = ( light.distance === 0 ) ? 0.0 : light.decay; - - uniforms.shadow = light.castShadow; - - if ( light.castShadow ) { - - shadow = light.shadow; - - uniforms.shadowBias = shadow.bias; - uniforms.shadowRadius = shadow.radius; - uniforms.shadowMapSize = shadow.mapSize; - - } - - _lights.spotShadowMap[ spotLength ] = shadowMap; - _lights.spotShadowMatrix[ spotLength ] = light.shadow.matrix; - _lights.spot[ spotLength ] = uniforms; - - spotLength ++; - - } else if ( light.isRectAreaLight ) { - - var uniforms = lightCache.get( light ); - - // (a) intensity controls irradiance of entire light - uniforms.color - .copy( color ) - .multiplyScalar( intensity / ( light.width * light.height ) ); - - // (b) intensity controls the radiance per light area - // uniforms.color.copy( color ).multiplyScalar( intensity ); - - uniforms.position.setFromMatrixPosition( light.matrixWorld ); - uniforms.position.applyMatrix4( viewMatrix ); - - // extract local rotation of light to derive width/height half vectors - _matrix42.identity(); - _matrix4.copy( light.matrixWorld ); - _matrix4.premultiply( viewMatrix ); - _matrix42.extractRotation( _matrix4 ); - - uniforms.halfWidth.set( light.width * 0.5, 0.0, 0.0 ); - uniforms.halfHeight.set( 0.0, light.height * 0.5, 0.0 ); - - uniforms.halfWidth.applyMatrix4( _matrix42 ); - uniforms.halfHeight.applyMatrix4( _matrix42 ); - - // TODO (abelnation): RectAreaLight distance? - // uniforms.distance = distance; - - _lights.rectArea[ rectAreaLength ] = uniforms; - - rectAreaLength ++; - - } else if ( light.isPointLight ) { - - var uniforms = lightCache.get( light ); - - uniforms.position.setFromMatrixPosition( light.matrixWorld ); - uniforms.position.applyMatrix4( viewMatrix ); - - uniforms.color.copy( light.color ).multiplyScalar( light.intensity ); - uniforms.distance = light.distance; - uniforms.decay = ( light.distance === 0 ) ? 0.0 : light.decay; - - uniforms.shadow = light.castShadow; - - if ( light.castShadow ) { - - shadow = light.shadow; - - uniforms.shadowBias = shadow.bias; - uniforms.shadowRadius = shadow.radius; - uniforms.shadowMapSize = shadow.mapSize; - - } - - _lights.pointShadowMap[ pointLength ] = shadowMap; - _lights.pointShadowMatrix[ pointLength ] = light.shadow.matrix; - _lights.point[ pointLength ] = uniforms; - - pointLength ++; - - } else if ( light.isHemisphereLight ) { - - var uniforms = lightCache.get( light ); - - uniforms.direction.setFromMatrixPosition( light.matrixWorld ); - uniforms.direction.transformDirection( viewMatrix ); - uniforms.direction.normalize(); - - uniforms.skyColor.copy( light.color ).multiplyScalar( intensity ); - uniforms.groundColor.copy( light.groundColor ).multiplyScalar( intensity ); - - _lights.hemi[ hemiLength ] = uniforms; - - hemiLength ++; - - } - - } - - _lights.ambient[ 0 ] = r; - _lights.ambient[ 1 ] = g; - _lights.ambient[ 2 ] = b; - - _lights.directional.length = directionalLength; - _lights.spot.length = spotLength; - _lights.rectArea.length = rectAreaLength; - _lights.point.length = pointLength; - _lights.hemi.length = hemiLength; - - // TODO (sam-g-steel) why aren't we using join - _lights.hash = directionalLength + ',' + pointLength + ',' + spotLength + ',' + rectAreaLength + ',' + hemiLength + ',' + _lights.shadows.length; - - } - // GL state setting this.setFaceCulling = function ( cullFace, frontFaceDirection ) { @@ -22498,37 +23343,34 @@ function WebGLRenderer( parameters ) { } - var isCube = ( renderTarget && renderTarget.isWebGLRenderTargetCube ); - var framebuffer; + var framebuffer = null; + var isCube = false; if ( renderTarget ) { - var renderTargetProperties = properties.get( renderTarget ); + var __webglFramebuffer = properties.get( renderTarget ).__webglFramebuffer; - if ( isCube ) { + if ( renderTarget.isWebGLRenderTargetCube ) { - framebuffer = renderTargetProperties.__webglFramebuffer[ renderTarget.activeCubeFace ]; + framebuffer = __webglFramebuffer[ renderTarget.activeCubeFace ]; + isCube = true; } else { - framebuffer = renderTargetProperties.__webglFramebuffer; + framebuffer = __webglFramebuffer; } + _currentViewport.copy( renderTarget.viewport ); _currentScissor.copy( renderTarget.scissor ); _currentScissorTest = renderTarget.scissorTest; - _currentViewport.copy( renderTarget.viewport ); - } else { - framebuffer = null; - + _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ); _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ); _currentScissorTest = _scissorTest; - _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ); - } if ( _currentFramebuffer !== framebuffer ) { @@ -22538,11 +23380,10 @@ function WebGLRenderer( parameters ) { } + state.viewport( _currentViewport ); state.scissor( _currentScissor ); state.setScissorTest( _currentScissorTest ); - state.viewport( _currentViewport ); - if ( isCube ) { var textureProperties = properties.get( renderTarget.texture ); @@ -22554,7 +23395,7 @@ function WebGLRenderer( parameters ) { this.readRenderTargetPixels = function ( renderTarget, x, y, width, height, buffer ) { - if ( ( renderTarget && renderTarget.isWebGLRenderTarget ) === false ) { + if ( ! ( renderTarget && renderTarget.isWebGLRenderTarget ) ) { console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.' ); return; @@ -22581,14 +23422,14 @@ function WebGLRenderer( parameters ) { var textureFormat = texture.format; var textureType = texture.type; - if ( textureFormat !== RGBAFormat && paramThreeToGL( textureFormat ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_FORMAT ) ) { + if ( textureFormat !== RGBAFormat && utils.convert( textureFormat ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_FORMAT ) ) { console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.' ); return; } - if ( textureType !== UnsignedByteType && paramThreeToGL( textureType ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_TYPE ) && // IE11, Edge and Chrome Mac < 52 (#9513) + if ( textureType !== UnsignedByteType && utils.convert( textureType ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_TYPE ) && // IE11, Edge and Chrome Mac < 52 (#9513) ! ( textureType === FloatType && ( extensions.get( 'OES_texture_float' ) || extensions.get( 'WEBGL_color_buffer_float' ) ) ) && // Chrome Mac >= 52 and Firefox ! ( textureType === HalfFloatType && extensions.get( 'EXT_color_buffer_half_float' ) ) ) { @@ -22603,7 +23444,7 @@ function WebGLRenderer( parameters ) { if ( ( x >= 0 && x <= ( renderTarget.width - width ) ) && ( y >= 0 && y <= ( renderTarget.height - height ) ) ) { - _gl.readPixels( x, y, width, height, paramThreeToGL( textureFormat ), paramThreeToGL( textureType ), buffer ); + _gl.readPixels( x, y, width, height, utils.convert( textureFormat ), utils.convert( textureType ), buffer ); } @@ -22627,134 +23468,6 @@ function WebGLRenderer( parameters ) { }; - // Map three.js constants to WebGL constants - - function paramThreeToGL( p ) { - - var extension; - - if ( p === RepeatWrapping ) return _gl.REPEAT; - if ( p === ClampToEdgeWrapping ) return _gl.CLAMP_TO_EDGE; - if ( p === MirroredRepeatWrapping ) return _gl.MIRRORED_REPEAT; - - if ( p === NearestFilter ) return _gl.NEAREST; - if ( p === NearestMipMapNearestFilter ) return _gl.NEAREST_MIPMAP_NEAREST; - if ( p === NearestMipMapLinearFilter ) return _gl.NEAREST_MIPMAP_LINEAR; - - if ( p === LinearFilter ) return _gl.LINEAR; - if ( p === LinearMipMapNearestFilter ) return _gl.LINEAR_MIPMAP_NEAREST; - if ( p === LinearMipMapLinearFilter ) return _gl.LINEAR_MIPMAP_LINEAR; - - if ( p === UnsignedByteType ) return _gl.UNSIGNED_BYTE; - if ( p === UnsignedShort4444Type ) return _gl.UNSIGNED_SHORT_4_4_4_4; - if ( p === UnsignedShort5551Type ) return _gl.UNSIGNED_SHORT_5_5_5_1; - if ( p === UnsignedShort565Type ) return _gl.UNSIGNED_SHORT_5_6_5; - - if ( p === ByteType ) return _gl.BYTE; - if ( p === ShortType ) return _gl.SHORT; - if ( p === UnsignedShortType ) return _gl.UNSIGNED_SHORT; - if ( p === IntType ) return _gl.INT; - if ( p === UnsignedIntType ) return _gl.UNSIGNED_INT; - if ( p === FloatType ) return _gl.FLOAT; - - if ( p === HalfFloatType ) { - - extension = extensions.get( 'OES_texture_half_float' ); - - if ( extension !== null ) return extension.HALF_FLOAT_OES; - - } - - if ( p === AlphaFormat ) return _gl.ALPHA; - if ( p === RGBFormat ) return _gl.RGB; - if ( p === RGBAFormat ) return _gl.RGBA; - if ( p === LuminanceFormat ) return _gl.LUMINANCE; - if ( p === LuminanceAlphaFormat ) return _gl.LUMINANCE_ALPHA; - if ( p === DepthFormat ) return _gl.DEPTH_COMPONENT; - if ( p === DepthStencilFormat ) return _gl.DEPTH_STENCIL; - - if ( p === AddEquation ) return _gl.FUNC_ADD; - if ( p === SubtractEquation ) return _gl.FUNC_SUBTRACT; - if ( p === ReverseSubtractEquation ) return _gl.FUNC_REVERSE_SUBTRACT; - - if ( p === ZeroFactor ) return _gl.ZERO; - if ( p === OneFactor ) return _gl.ONE; - if ( p === SrcColorFactor ) return _gl.SRC_COLOR; - if ( p === OneMinusSrcColorFactor ) return _gl.ONE_MINUS_SRC_COLOR; - if ( p === SrcAlphaFactor ) return _gl.SRC_ALPHA; - if ( p === OneMinusSrcAlphaFactor ) return _gl.ONE_MINUS_SRC_ALPHA; - if ( p === DstAlphaFactor ) return _gl.DST_ALPHA; - if ( p === OneMinusDstAlphaFactor ) return _gl.ONE_MINUS_DST_ALPHA; - - if ( p === DstColorFactor ) return _gl.DST_COLOR; - if ( p === OneMinusDstColorFactor ) return _gl.ONE_MINUS_DST_COLOR; - if ( p === SrcAlphaSaturateFactor ) return _gl.SRC_ALPHA_SATURATE; - - if ( p === RGB_S3TC_DXT1_Format || p === RGBA_S3TC_DXT1_Format || - p === RGBA_S3TC_DXT3_Format || p === RGBA_S3TC_DXT5_Format ) { - - extension = extensions.get( 'WEBGL_compressed_texture_s3tc' ); - - if ( extension !== null ) { - - if ( p === RGB_S3TC_DXT1_Format ) return extension.COMPRESSED_RGB_S3TC_DXT1_EXT; - if ( p === RGBA_S3TC_DXT1_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT1_EXT; - if ( p === RGBA_S3TC_DXT3_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT3_EXT; - if ( p === RGBA_S3TC_DXT5_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT5_EXT; - - } - - } - - if ( p === RGB_PVRTC_4BPPV1_Format || p === RGB_PVRTC_2BPPV1_Format || - p === RGBA_PVRTC_4BPPV1_Format || p === RGBA_PVRTC_2BPPV1_Format ) { - - extension = extensions.get( 'WEBGL_compressed_texture_pvrtc' ); - - if ( extension !== null ) { - - if ( p === RGB_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_4BPPV1_IMG; - if ( p === RGB_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_2BPPV1_IMG; - if ( p === RGBA_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG; - if ( p === RGBA_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG; - - } - - } - - if ( p === RGB_ETC1_Format ) { - - extension = extensions.get( 'WEBGL_compressed_texture_etc1' ); - - if ( extension !== null ) return extension.COMPRESSED_RGB_ETC1_WEBGL; - - } - - if ( p === MinEquation || p === MaxEquation ) { - - extension = extensions.get( 'EXT_blend_minmax' ); - - if ( extension !== null ) { - - if ( p === MinEquation ) return extension.MIN_EXT; - if ( p === MaxEquation ) return extension.MAX_EXT; - - } - - } - - if ( p === UnsignedInt248Type ) { - - extension = extensions.get( 'WEBGL_depth_texture' ); - - if ( extension !== null ) return extension.UNSIGNED_INT_24_8_WEBGL; - - } - - return 0; - - } - } /** @@ -24129,17 +24842,17 @@ function VideoTexture( video, mapping, wrapS, wrapT, magFilter, minFilter, forma function update() { - requestAnimationFrame( update ); - if ( video.readyState >= video.HAVE_CURRENT_DATA ) { scope.needsUpdate = true; } + requestAnimationFrame( update ); + } - update(); + requestAnimationFrame( update ); } @@ -24174,21 +24887,6 @@ CompressedTexture.prototype.constructor = CompressedTexture; CompressedTexture.prototype.isCompressedTexture = true; -/** - * @author mrdoob / http://mrdoob.com/ - */ - -function CanvasTexture( canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) { - - Texture.call( this, canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ); - - this.needsUpdate = true; - -} - -CanvasTexture.prototype = Object.create( Texture.prototype ); -CanvasTexture.prototype.constructor = CanvasTexture; - /** * @author Matt DesLauriers / @mattdesl * @author atix / arthursilber.de @@ -24200,7 +24898,7 @@ function DepthTexture( width, height, type, mapping, wrapS, wrapT, magFilter, mi if ( format !== DepthFormat && format !== DepthStencilFormat ) { - throw new Error( 'DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat' ) + throw new Error( 'DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat' ); } @@ -25848,7 +26546,7 @@ var ShapeUtils = { if ( indices ) return vertIndices; return result; - } + }; } )(), @@ -26186,7 +26884,7 @@ var ShapeUtils = { hIdx, nextIdx, intersection; for ( ihIdx = 0; ihIdx < indepHoles.length; ihIdx ++ ) { - chkHole = holes[ indepHoles[ ihIdx ]]; + chkHole = holes[ indepHoles[ ihIdx ] ]; for ( hIdx = 0; hIdx < chkHole.length; hIdx ++ ) { nextIdx = hIdx + 1; nextIdx %= chkHole.length; @@ -26219,7 +26917,7 @@ var ShapeUtils = { counter --; if ( counter < 0 ) { - console.log( "Infinite Loop! Holes left:" + indepHoles.length + ", Probably Hole outside Shape!" ); + console.log( 'THREE.ShapeUtils: Infinite Loop! Holes left:" + indepHoles.length + ", Probably Hole outside Shape!' ); break; } @@ -26237,7 +26935,7 @@ var ShapeUtils = { holeIdx = indepHoles[ h ]; // prevent multiple checks - cutKey = shapePt.x + ":" + shapePt.y + ":" + holeIdx; + cutKey = shapePt.x + ':' + shapePt.y + ':' + holeIdx; if ( failedCuts[ cutKey ] !== undefined ) continue; hole = holes[ holeIdx ]; @@ -26302,11 +27000,11 @@ var ShapeUtils = { for ( i = 0, il = allpoints.length; i < il; i ++ ) { - key = allpoints[ i ].x + ":" + allpoints[ i ].y; + key = allpoints[ i ].x + ':' + allpoints[ i ].y; if ( allPointsMap[ key ] !== undefined ) { - console.warn( "THREE.ShapeUtils: Duplicate point", key, i ); + console.warn( 'THREE.ShapeUtils: Duplicate point', key, i ); } @@ -26328,7 +27026,7 @@ var ShapeUtils = { for ( f = 0; f < 3; f ++ ) { - key = face[ f ].x + ":" + face[ f ].y; + key = face[ f ].x + ':' + face[ f ].y; index = allPointsMap[ key ]; @@ -26405,7 +27103,6 @@ function ExtrudeBufferGeometry( shapes, options ) { if ( typeof ( shapes ) === "undefined" ) { - shapes = []; return; } @@ -26560,8 +27257,6 @@ ExtrudeBufferGeometry.prototype.addShape = function ( shape, options ) { } - reverse = false; // If vertices are in order now, we shouldn't need to worry about them again (hopefully)! - } @@ -26605,7 +27300,7 @@ ExtrudeBufferGeometry.prototype.addShape = function ( shape, options ) { // inPt' is the intersection of the two lines parallel to the two // adjacent edges of inPt at a distance of 1 unit on the left side. - var v_trans_x, v_trans_y, shrink_by = 1; // resulting translation vector for inPt + var v_trans_x, v_trans_y, shrink_by; // resulting translation vector for inPt // good reading for geometry algorithms (here: line-line intersection) // http://geomalgorithms.com/a05-_intersect-1.html @@ -27210,7 +27905,7 @@ function TextBufferGeometry( text, parameters ) { var font = parameters.font; - if ( ( font && font.isFont ) === false ) { + if ( ! ( font && font.isFont ) ) { console.error( 'THREE.TextGeometry: font parameter is not an instance of THREE.Font.' ); return new Geometry(); @@ -28502,43 +29197,28 @@ var Geometries = Object.freeze({ * @author mrdoob / http://mrdoob.com/ * * parameters = { + * color: , * opacity: * } */ function ShadowMaterial( parameters ) { - ShaderMaterial.call( this, { - uniforms: UniformsUtils.merge( [ - UniformsLib.lights, - { - opacity: { value: 1.0 } - } - ] ), - vertexShader: ShaderChunk[ 'shadow_vert' ], - fragmentShader: ShaderChunk[ 'shadow_frag' ] - } ); + Material.call( this ); + + this.type = 'ShadowMaterial'; + + this.color = new Color( 0x000000 ); + this.opacity = 1.0; this.lights = true; this.transparent = true; - Object.defineProperties( this, { - opacity: { - enumerable: true, - get: function () { - return this.uniforms.opacity.value; - }, - set: function ( value ) { - this.uniforms.opacity.value = value; - } - } - } ); - this.setValues( parameters ); } -ShadowMaterial.prototype = Object.create( ShaderMaterial.prototype ); +ShadowMaterial.prototype = Object.create( Material.prototype ); ShadowMaterial.prototype.constructor = ShadowMaterial; ShadowMaterial.prototype.isShadowMaterial = true; @@ -29001,7 +29681,7 @@ MeshToonMaterial.prototype.copy = function ( source ) { function MeshNormalMaterial( parameters ) { - Material.call( this, parameters ); + Material.call( this ); this.type = 'MeshNormalMaterial'; @@ -29201,36 +29881,26 @@ MeshLambertMaterial.prototype.copy = function ( source ) { function LineDashedMaterial( parameters ) { - Material.call( this ); + LineBasicMaterial.call( this ); this.type = 'LineDashedMaterial'; - this.color = new Color( 0xffffff ); - - this.linewidth = 1; - this.scale = 1; this.dashSize = 3; this.gapSize = 1; - this.lights = false; - this.setValues( parameters ); } -LineDashedMaterial.prototype = Object.create( Material.prototype ); +LineDashedMaterial.prototype = Object.create( LineBasicMaterial.prototype ); LineDashedMaterial.prototype.constructor = LineDashedMaterial; LineDashedMaterial.prototype.isLineDashedMaterial = true; LineDashedMaterial.prototype.copy = function ( source ) { - Material.prototype.copy.call( this, source ); - - this.color.copy( source.color ); - - this.linewidth = source.linewidth; + LineBasicMaterial.prototype.copy.call( this, source ); this.scale = source.scale; this.dashSize = source.dashSize; @@ -29255,6 +29925,7 @@ var Materials = Object.freeze({ MeshNormalMaterial: MeshNormalMaterial, MeshLambertMaterial: MeshLambertMaterial, MeshDepthMaterial: MeshDepthMaterial, + MeshDistanceMaterial: MeshDistanceMaterial, MeshBasicMaterial: MeshBasicMaterial, LineDashedMaterial: LineDashedMaterial, LineBasicMaterial: LineBasicMaterial, @@ -29439,9 +30110,8 @@ Object.assign( FileLoader.prototype, { case 'arraybuffer': case 'blob': - response = new ArrayBuffer( data.length ); - - var view = new Uint8Array( response ); + + var view = new Uint8Array( data.length ); for ( var i = 0; i < data.length; i ++ ) { @@ -29451,9 +30121,12 @@ Object.assign( FileLoader.prototype, { if ( responseType === 'blob' ) { - response = new Blob( [ response ], { type: mimeType } ); + response = new Blob( [ view.buffer ], { type: mimeType } ); - } + } else { + + response = view.buffer; + } break; @@ -29478,7 +30151,7 @@ Object.assign( FileLoader.prototype, { } - // Wait for next browser tick + // Wait for next browser tick like standard XMLHttpRequest event dispatching does window.setTimeout( function () { if ( onLoad ) onLoad( response ); @@ -29489,7 +30162,7 @@ Object.assign( FileLoader.prototype, { } catch ( error ) { - // Wait for next browser tick + // Wait for next browser tick like standard XMLHttpRequest event dispatching does window.setTimeout( function () { if ( onError ) onError( error ); @@ -29851,6 +30524,8 @@ function ImageLoader( manager ) { Object.assign( ImageLoader.prototype, { + crossOrigin: 'Anonymous', + load: function ( url, onLoad, onProgress, onError ) { if ( url === undefined ) url = ''; @@ -29948,6 +30623,8 @@ function CubeTextureLoader( manager ) { Object.assign( CubeTextureLoader.prototype, { + crossOrigin: 'Anonymous', + load: function ( urls, onLoad, onProgress, onError ) { var texture = new CubeTexture(); @@ -30016,6 +30693,8 @@ function TextureLoader( manager ) { Object.assign( TextureLoader.prototype, { + crossOrigin: 'Anonymous', + load: function ( url, onLoad, onProgress, onError ) { var loader = new ImageLoader( this.manager ); @@ -31796,7 +32475,7 @@ Object.assign( KeyframeTrack, { } else { - // by default, we asssume a constructor compatible with the base + // by default, we assume a constructor compatible with the base return new trackType( json.name, json.times, json.values, json.interpolation ); @@ -32300,7 +32979,7 @@ Object.assign( MaterialLoader.prototype, { if ( json.fragmentShader !== undefined ) material.fragmentShader = json.fragmentShader; if ( json.vertexColors !== undefined ) material.vertexColors = json.vertexColors; if ( json.fog !== undefined ) material.fog = json.fog; - if ( json.shading !== undefined ) material.shading = json.shading; + if ( json.flatShading !== undefined ) material.flatShading = json.flatShading; if ( json.blending !== undefined ) material.blending = json.blending; if ( json.side !== undefined ) material.side = json.side; if ( json.opacity !== undefined ) material.opacity = json.opacity; @@ -32313,8 +32992,17 @@ Object.assign( MaterialLoader.prototype, { if ( json.wireframeLinewidth !== undefined ) material.wireframeLinewidth = json.wireframeLinewidth; if ( json.wireframeLinecap !== undefined ) material.wireframeLinecap = json.wireframeLinecap; if ( json.wireframeLinejoin !== undefined ) material.wireframeLinejoin = json.wireframeLinejoin; + if ( json.skinning !== undefined ) material.skinning = json.skinning; if ( json.morphTargets !== undefined ) material.morphTargets = json.morphTargets; + if ( json.dithering !== undefined ) material.dithering = json.dithering; + + if ( json.visible !== undefined ) material.visible = json.visible; + if ( json.userData !== undefined ) material.userData = json.userData; + + // Deprecated + + if ( json.shading !== undefined ) material.flatShading = json.shading === 1; // THREE.FlatShading // for PointsMaterial @@ -32470,7 +33158,8 @@ Object.assign( BufferGeometryLoader.prototype, { var TYPED_ARRAYS = { Int8Array: Int8Array, Uint8Array: Uint8Array, - Uint8ClampedArray: Uint8ClampedArray, + // Workaround for IE11 pre KB2929437. See #11440 + Uint8ClampedArray: typeof Uint8ClampedArray !== 'undefined' ? Uint8ClampedArray : Uint8Array, Int16Array: Int16Array, Uint16Array: Uint16Array, Int32Array: Int32Array, @@ -33816,6 +34505,8 @@ Object.assign( ObjectLoader.prototype, { if ( data.offset !== undefined ) texture.offset.fromArray( data.offset ); if ( data.repeat !== undefined ) texture.repeat.fromArray( data.repeat ); + if ( data.rotation !== undefined ) texture.rotation = data.rotation; + if ( data.wrap !== undefined ) { texture.wrapS = parseConstant( data.wrap[ 0 ], TEXTURE_WRAPPING ); @@ -34085,9 +34776,11 @@ Object.assign( ObjectLoader.prototype, { if ( data.children !== undefined ) { - for ( var child in data.children ) { + var children = data.children; - object.add( this.parseObject( data.children[ child ], geometries, materials ) ); + for ( var i = 0; i < children.length; i ++ ) { + + object.add( this.parseObject( children[ i ], geometries, materials ) ); } @@ -35721,6 +36414,7 @@ Object.assign( FontLoader.prototype, { var scope = this; var loader = new FileLoader( this.manager ); + loader.setPath( this.path ); loader.load( url, function ( text ) { var json; @@ -35748,6 +36442,13 @@ Object.assign( FontLoader.prototype, { return new Font( json ); + }, + + setPath: function ( value ) { + + this.path = value; + return this; + } } ); @@ -35950,7 +36651,7 @@ function CubeCamera( near, far, cubeResolution ) { this.renderTarget = new WebGLRenderTargetCube( cubeResolution, cubeResolution, options ); this.renderTarget.texture.name = "CubeCamera"; - this.updateCubeMap = function ( renderer, scene ) { + this.update = function ( renderer, scene ) { if ( this.parent === null ) this.updateMatrixWorld(); @@ -35983,31 +36684,27 @@ function CubeCamera( near, far, cubeResolution ) { }; -} - -CubeCamera.prototype = Object.create( Object3D.prototype ); -CubeCamera.prototype.constructor = CubeCamera; + this.clear = function ( renderer, color, depth, stencil ) { -/** - * @author mrdoob / http://mrdoob.com/ - */ + var renderTarget = this.renderTarget; -function ArrayCamera( array ) { + for ( var i = 0; i < 6; i ++ ) { - PerspectiveCamera.call( this ); + renderTarget.activeCubeFace = i; + renderer.setRenderTarget( renderTarget ); - this.enabled = false; - this.cameras = array || []; + renderer.clear( color, depth, stencil ); -} + } -ArrayCamera.prototype = Object.assign( Object.create( PerspectiveCamera.prototype ), { + renderer.setRenderTarget( null ); - constructor: ArrayCamera, + }; - isArrayCamera: true +} -} ); +CubeCamera.prototype = Object.create( Object3D.prototype ); +CubeCamera.prototype.constructor = CubeCamera; /** * @author mrdoob / http://mrdoob.com/ @@ -36418,7 +37115,7 @@ Audio.prototype = Object.assign( Object.create( Object3D.prototype ), { return this.gain.gain.value; }, - + setVolume: function ( value ) { this.gain.gain.value = value; @@ -36869,6 +37566,19 @@ Object.assign( PropertyBinding, { }, + /** + * Replaces spaces with underscores and removes unsupported characters from + * node names, to ensure compatibility with parseTrackName(). + * + * @param {string} name Node name to be sanitized. + * @return {string} + */ + sanitizeNodeName: function ( name ) { + + return name.replace( /\s/g, '_' ).replace( /[^\w-]/g, '' ); + + }, + parseTrackName: function () { // Parent directories, delimited by '/' or ':'. Currently unused, but must @@ -39790,6 +40500,7 @@ Object.assign( Clock.prototype, { this.getElapsedTime(); this.running = false; + this.autoStart = false; }, @@ -39965,322 +40676,6 @@ Object.assign( Cylindrical.prototype, { } ); -/** - * @author alteredq / http://alteredqualia.com/ - */ - -function MorphBlendMesh( geometry, material ) { - - Mesh.call( this, geometry, material ); - - this.animationsMap = {}; - this.animationsList = []; - - // prepare default animation - // (all frames played together in 1 second) - - var numFrames = this.geometry.morphTargets.length; - - var name = "__default"; - - var startFrame = 0; - var endFrame = numFrames - 1; - - var fps = numFrames / 1; - - this.createAnimation( name, startFrame, endFrame, fps ); - this.setAnimationWeight( name, 1 ); - -} - -MorphBlendMesh.prototype = Object.create( Mesh.prototype ); -MorphBlendMesh.prototype.constructor = MorphBlendMesh; - -MorphBlendMesh.prototype.createAnimation = function ( name, start, end, fps ) { - - var animation = { - - start: start, - end: end, - - length: end - start + 1, - - fps: fps, - duration: ( end - start ) / fps, - - lastFrame: 0, - currentFrame: 0, - - active: false, - - time: 0, - direction: 1, - weight: 1, - - directionBackwards: false, - mirroredLoop: false - - }; - - this.animationsMap[ name ] = animation; - this.animationsList.push( animation ); - -}; - -MorphBlendMesh.prototype.autoCreateAnimations = function ( fps ) { - - var pattern = /([a-z]+)_?(\d+)/i; - - var firstAnimation, frameRanges = {}; - - var geometry = this.geometry; - - for ( var i = 0, il = geometry.morphTargets.length; i < il; i ++ ) { - - var morph = geometry.morphTargets[ i ]; - var chunks = morph.name.match( pattern ); - - if ( chunks && chunks.length > 1 ) { - - var name = chunks[ 1 ]; - - if ( ! frameRanges[ name ] ) frameRanges[ name ] = { start: Infinity, end: - Infinity }; - - var range = frameRanges[ name ]; - - if ( i < range.start ) range.start = i; - if ( i > range.end ) range.end = i; - - if ( ! firstAnimation ) firstAnimation = name; - - } - - } - - for ( var name in frameRanges ) { - - var range = frameRanges[ name ]; - this.createAnimation( name, range.start, range.end, fps ); - - } - - this.firstAnimation = firstAnimation; - -}; - -MorphBlendMesh.prototype.setAnimationDirectionForward = function ( name ) { - - var animation = this.animationsMap[ name ]; - - if ( animation ) { - - animation.direction = 1; - animation.directionBackwards = false; - - } - -}; - -MorphBlendMesh.prototype.setAnimationDirectionBackward = function ( name ) { - - var animation = this.animationsMap[ name ]; - - if ( animation ) { - - animation.direction = - 1; - animation.directionBackwards = true; - - } - -}; - -MorphBlendMesh.prototype.setAnimationFPS = function ( name, fps ) { - - var animation = this.animationsMap[ name ]; - - if ( animation ) { - - animation.fps = fps; - animation.duration = ( animation.end - animation.start ) / animation.fps; - - } - -}; - -MorphBlendMesh.prototype.setAnimationDuration = function ( name, duration ) { - - var animation = this.animationsMap[ name ]; - - if ( animation ) { - - animation.duration = duration; - animation.fps = ( animation.end - animation.start ) / animation.duration; - - } - -}; - -MorphBlendMesh.prototype.setAnimationWeight = function ( name, weight ) { - - var animation = this.animationsMap[ name ]; - - if ( animation ) { - - animation.weight = weight; - - } - -}; - -MorphBlendMesh.prototype.setAnimationTime = function ( name, time ) { - - var animation = this.animationsMap[ name ]; - - if ( animation ) { - - animation.time = time; - - } - -}; - -MorphBlendMesh.prototype.getAnimationTime = function ( name ) { - - var time = 0; - - var animation = this.animationsMap[ name ]; - - if ( animation ) { - - time = animation.time; - - } - - return time; - -}; - -MorphBlendMesh.prototype.getAnimationDuration = function ( name ) { - - var duration = - 1; - - var animation = this.animationsMap[ name ]; - - if ( animation ) { - - duration = animation.duration; - - } - - return duration; - -}; - -MorphBlendMesh.prototype.playAnimation = function ( name ) { - - var animation = this.animationsMap[ name ]; - - if ( animation ) { - - animation.time = 0; - animation.active = true; - - } else { - - console.warn( "THREE.MorphBlendMesh: animation[" + name + "] undefined in .playAnimation()" ); - - } - -}; - -MorphBlendMesh.prototype.stopAnimation = function ( name ) { - - var animation = this.animationsMap[ name ]; - - if ( animation ) { - - animation.active = false; - - } - -}; - -MorphBlendMesh.prototype.update = function ( delta ) { - - for ( var i = 0, il = this.animationsList.length; i < il; i ++ ) { - - var animation = this.animationsList[ i ]; - - if ( ! animation.active ) continue; - - var frameTime = animation.duration / animation.length; - - animation.time += animation.direction * delta; - - if ( animation.mirroredLoop ) { - - if ( animation.time > animation.duration || animation.time < 0 ) { - - animation.direction *= - 1; - - if ( animation.time > animation.duration ) { - - animation.time = animation.duration; - animation.directionBackwards = true; - - } - - if ( animation.time < 0 ) { - - animation.time = 0; - animation.directionBackwards = false; - - } - - } - - } else { - - animation.time = animation.time % animation.duration; - - if ( animation.time < 0 ) animation.time += animation.duration; - - } - - var keyframe = animation.start + _Math.clamp( Math.floor( animation.time / frameTime ), 0, animation.length - 1 ); - var weight = animation.weight; - - if ( keyframe !== animation.currentFrame ) { - - this.morphTargetInfluences[ animation.lastFrame ] = 0; - this.morphTargetInfluences[ animation.currentFrame ] = 1 * weight; - - this.morphTargetInfluences[ keyframe ] = 0; - - animation.lastFrame = animation.currentFrame; - animation.currentFrame = keyframe; - - } - - var mix = ( animation.time % frameTime ) / frameTime; - - if ( animation.directionBackwards ) mix = 1 - mix; - - if ( animation.currentFrame !== animation.lastFrame ) { - - this.morphTargetInfluences[ animation.currentFrame ] = mix * weight; - this.morphTargetInfluences[ animation.lastFrame ] = ( 1 - mix ) * weight; - - } else { - - this.morphTargetInfluences[ animation.currentFrame ] = weight; - - } - - } - -}; - /** * @author alteredq / http://alteredqualia.com/ */ @@ -40302,7 +40697,7 @@ ImmediateRenderObject.prototype.isImmediateRenderObject = true; /** * @author mrdoob / http://mrdoob.com/ * @author WestLangley / http://github.com/WestLangley -*/ + */ function VertexNormalsHelper( object, size, hex, linewidth ) { @@ -40447,9 +40842,9 @@ VertexNormalsHelper.prototype.update = ( function () { * @author alteredq / http://alteredqualia.com/ * @author mrdoob / http://mrdoob.com/ * @author WestLangley / http://github.com/WestLangley -*/ + */ -function SpotLightHelper( light ) { +function SpotLightHelper( light, color ) { Object3D.call( this ); @@ -40459,6 +40854,8 @@ function SpotLightHelper( light ) { this.matrix = light.matrixWorld; this.matrixAutoUpdate = false; + this.color = color; + var geometry = new BufferGeometry(); var positions = [ @@ -40509,6 +40906,8 @@ SpotLightHelper.prototype.update = function () { return function update() { + this.light.updateMatrixWorld(); + var coneLength = this.light.distance ? this.light.distance : 1000; var coneWidth = coneLength * Math.tan( this.light.angle ); @@ -40519,7 +40918,15 @@ SpotLightHelper.prototype.update = function () { this.cone.lookAt( vector2.sub( vector ) ); - this.cone.material.color.copy( this.light.color ); + if ( this.color !== undefined ) { + + this.cone.material.color.set( this.color ); + + } else { + + this.cone.material.color.copy( this.light.color ); + + } }; @@ -40533,9 +40940,29 @@ SpotLightHelper.prototype.update = function () { * @author Mugen87 / https://github.com/Mugen87 */ +function getBoneList( object ) { + + var boneList = []; + + if ( object && object.isBone ) { + + boneList.push( object ); + + } + + for ( var i = 0; i < object.children.length; i ++ ) { + + boneList.push.apply( boneList, getBoneList( object.children[ i ] ) ); + + } + + return boneList; + +} + function SkeletonHelper( object ) { - this.bones = this.getBoneList( object ); + var bones = getBoneList( object ); var geometry = new BufferGeometry(); @@ -40545,9 +40972,9 @@ function SkeletonHelper( object ) { var color1 = new Color( 0, 0, 1 ); var color2 = new Color( 0, 1, 0 ); - for ( var i = 0; i < this.bones.length; i ++ ) { + for ( var i = 0; i < bones.length; i ++ ) { - var bone = this.bones[ i ]; + var bone = bones[ i ]; if ( bone.parent && bone.parent.isBone ) { @@ -40568,55 +40995,35 @@ function SkeletonHelper( object ) { LineSegments.call( this, geometry, material ); this.root = object; + this.bones = bones; this.matrix = object.matrixWorld; this.matrixAutoUpdate = false; - this.update(); - } - SkeletonHelper.prototype = Object.create( LineSegments.prototype ); SkeletonHelper.prototype.constructor = SkeletonHelper; -SkeletonHelper.prototype.getBoneList = function( object ) { - - var boneList = []; - - if ( object && object.isBone ) { - - boneList.push( object ); - - } - - for ( var i = 0; i < object.children.length; i ++ ) { - - boneList.push.apply( boneList, this.getBoneList( object.children[ i ] ) ); - - } - - return boneList; - -}; - -SkeletonHelper.prototype.update = function () { +SkeletonHelper.prototype.updateMatrixWorld = function () { var vector = new Vector3(); var boneMatrix = new Matrix4(); var matrixWorldInv = new Matrix4(); - return function update() { + return function updateMatrixWorld( force ) { + + var bones = this.bones; var geometry = this.geometry; var position = geometry.getAttribute( 'position' ); matrixWorldInv.getInverse( this.root.matrixWorld ); - for ( var i = 0, j = 0; i < this.bones.length; i ++ ) { + for ( var i = 0, j = 0; i < bones.length; i ++ ) { - var bone = this.bones[ i ]; + var bone = bones[ i ]; if ( bone.parent && bone.parent.isBone ) { @@ -40636,6 +41043,8 @@ SkeletonHelper.prototype.update = function () { geometry.getAttribute( 'position' ).needsUpdate = true; + Object3D.prototype.updateMatrixWorld.call( this, force ); + }; }(); @@ -40645,20 +41054,24 @@ SkeletonHelper.prototype.update = function () { * @author mrdoob / http://mrdoob.com/ */ -function PointLightHelper( light, sphereSize ) { +function PointLightHelper( light, sphereSize, color ) { this.light = light; this.light.updateMatrixWorld(); + this.color = color; + var geometry = new SphereBufferGeometry( sphereSize, 4, 2 ); var material = new MeshBasicMaterial( { wireframe: true, fog: false } ); - material.color.copy( this.light.color ); Mesh.call( this, geometry, material ); this.matrix = this.light.matrixWorld; this.matrixAutoUpdate = false; + this.update(); + + /* var distanceGeometry = new THREE.IcosahedronGeometry( 1, 2 ); var distanceMaterial = new THREE.MeshBasicMaterial( { color: hexColor, fog: false, wireframe: true, opacity: 0.1, transparent: true } ); @@ -40695,7 +41108,15 @@ PointLightHelper.prototype.dispose = function () { PointLightHelper.prototype.update = function () { - this.material.color.copy( this.light.color ); + if ( this.color !== undefined ) { + + this.material.color.set( this.color ); + + } else { + + this.material.color.copy( this.light.color ); + + } /* var d = this.light.distance; @@ -40720,7 +41141,7 @@ PointLightHelper.prototype.update = function () { * @author WestLangley / http://github.com/WestLangley */ -function RectAreaLightHelper( light ) { +function RectAreaLightHelper( light, color ) { Object3D.call( this ); @@ -40730,13 +41151,17 @@ function RectAreaLightHelper( light ) { this.matrix = light.matrixWorld; this.matrixAutoUpdate = false; - var material = new LineBasicMaterial( { color: light.color } ); + this.color = color; + + var material = new LineBasicMaterial( { fog: false } ); var geometry = new BufferGeometry(); geometry.addAttribute( 'position', new BufferAttribute( new Float32Array( 5 * 3 ), 3 ) ); - this.add( new Line( geometry, material ) ); + this.line = new Line( geometry, material ); + this.add( this.line ); + this.update(); @@ -40754,18 +41179,12 @@ RectAreaLightHelper.prototype.dispose = function () { RectAreaLightHelper.prototype.update = function () { - var line = this.children[ 0 ]; - - // update material - - line.material.color.copy( this.light.color ); - // calculate new dimensions of the helper var hx = this.light.width * 0.5; var hy = this.light.height * 0.5; - var position = line.geometry.attributes.position; + var position = this.line.geometry.attributes.position; var array = position.array; // update vertices @@ -40778,6 +41197,16 @@ RectAreaLightHelper.prototype.update = function () { position.needsUpdate = true; + if ( this.color !== undefined ) { + + this.line.material.color.set( this.color ); + + } else { + + this.line.material.color.copy( this.light.color ); + + } + }; /** @@ -40786,7 +41215,7 @@ RectAreaLightHelper.prototype.update = function () { * @author Mugen87 / https://github.com/Mugen87 */ -function HemisphereLightHelper( light, size ) { +function HemisphereLightHelper( light, size, color ) { Object3D.call( this ); @@ -40796,17 +41225,20 @@ function HemisphereLightHelper( light, size ) { this.matrix = light.matrixWorld; this.matrixAutoUpdate = false; + this.color = color; + var geometry = new OctahedronBufferGeometry( size ); geometry.rotateY( Math.PI * 0.5 ); - var material = new MeshBasicMaterial( { vertexColors: VertexColors, wireframe: true } ); + this.material = new MeshBasicMaterial( { wireframe: true, fog: false } ); + if ( this.color === undefined ) this.material.vertexColors = VertexColors; var position = geometry.getAttribute( 'position' ); var colors = new Float32Array( position.count * 3 ); geometry.addAttribute( 'color', new BufferAttribute( colors, 3 ) ); - this.add( new Mesh( geometry, material ) ); + this.add( new Mesh( geometry, this.material ) ); this.update(); @@ -40833,23 +41265,31 @@ HemisphereLightHelper.prototype.update = function () { var mesh = this.children[ 0 ]; - var colors = mesh.geometry.getAttribute( 'color' ); + if ( this.color !== undefined ) { - color1.copy( this.light.color ); - color2.copy( this.light.groundColor ); + this.material.color.set( this.color ); + + } else { - for ( var i = 0, l = colors.count; i < l; i ++ ) { + var colors = mesh.geometry.getAttribute( 'color' ); - var color = ( i < ( l / 2 ) ) ? color1 : color2; + color1.copy( this.light.color ); + color2.copy( this.light.groundColor ); - colors.setXYZ( i, color.r, color.g, color.b ); + for ( var i = 0, l = colors.count; i < l; i ++ ) { + + var color = ( i < ( l / 2 ) ) ? color1 : color2; + + colors.setXYZ( i, color.r, color.g, color.b ); + + } + + colors.needsUpdate = true; } mesh.lookAt( vector.setFromMatrixPosition( this.light.matrixWorld ).negate() ); - colors.needsUpdate = true; - }; }(); @@ -40988,7 +41428,7 @@ PolarGridHelper.prototype.constructor = PolarGridHelper; /** * @author mrdoob / http://mrdoob.com/ * @author WestLangley / http://github.com/WestLangley -*/ + */ function FaceNormalsHelper( object, size, hex, linewidth ) { @@ -41100,7 +41540,7 @@ FaceNormalsHelper.prototype.update = ( function () { * @author WestLangley / http://github.com/WestLangley */ -function DirectionalLightHelper( light, size ) { +function DirectionalLightHelper( light, size, color ) { Object3D.call( this ); @@ -41110,6 +41550,8 @@ function DirectionalLightHelper( light, size ) { this.matrix = light.matrixWorld; this.matrixAutoUpdate = false; + this.color = color; + if ( size === undefined ) size = 1; var geometry = new BufferGeometry(); @@ -41123,12 +41565,14 @@ function DirectionalLightHelper( light, size ) { var material = new LineBasicMaterial( { fog: false } ); - this.add( new Line( geometry, material ) ); + this.lightPlane = new Line( geometry, material ); + this.add( this.lightPlane ); geometry = new BufferGeometry(); geometry.addAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 0, 1 ], 3 ) ); - this.add( new Line( geometry, material )); + this.targetLine = new Line( geometry, material ); + this.add( this.targetLine ); this.update(); @@ -41139,13 +41583,10 @@ DirectionalLightHelper.prototype.constructor = DirectionalLightHelper; DirectionalLightHelper.prototype.dispose = function () { - var lightPlane = this.children[ 0 ]; - var targetLine = this.children[ 1 ]; - - lightPlane.geometry.dispose(); - lightPlane.material.dispose(); - targetLine.geometry.dispose(); - targetLine.material.dispose(); + this.lightPlane.geometry.dispose(); + this.lightPlane.material.dispose(); + this.targetLine.geometry.dispose(); + this.targetLine.material.dispose(); }; @@ -41161,14 +41602,22 @@ DirectionalLightHelper.prototype.update = function () { v2.setFromMatrixPosition( this.light.target.matrixWorld ); v3.subVectors( v2, v1 ); - var lightPlane = this.children[ 0 ]; - var targetLine = this.children[ 1 ]; + this.lightPlane.lookAt( v3 ); + + if ( this.color !== undefined ) { + + this.lightPlane.material.color.set( this.color ); + this.targetLine.material.color.set( this.color ); - lightPlane.lookAt( v3 ); - lightPlane.material.color.copy( this.light.color ); + } else { + + this.lightPlane.material.color.copy( this.light.color ); + this.targetLine.material.color.copy( this.light.color ); + + } - targetLine.lookAt( v3 ); - targetLine.scale.z = v3.length(); + this.targetLine.lookAt( v3 ); + this.targetLine.scale.z = v3.length(); }; @@ -41470,6 +41919,104 @@ BoxHelper.prototype.setFromObject = function ( object ) { }; +/** + * @author WestLangley / http://github.com/WestLangley + */ + +function Box3Helper( box, hex ) { + + this.type = 'Box3Helper'; + + this.box = box; + + var color = ( hex !== undefined ) ? hex : 0xffff00; + + var indices = new Uint16Array( [ 0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7 ] ); + + var positions = [ 1, 1, 1, - 1, 1, 1, - 1, - 1, 1, 1, - 1, 1, 1, 1, - 1, - 1, 1, - 1, - 1, - 1, - 1, 1, - 1, - 1 ]; + + var geometry = new BufferGeometry(); + + geometry.setIndex( new BufferAttribute( indices, 1 ) ); + + geometry.addAttribute( 'position', new Float32BufferAttribute( positions, 3 ) ); + + LineSegments.call( this, geometry, new LineBasicMaterial( { color: color } ) ); + + this.geometry.computeBoundingSphere(); + +} + +Box3Helper.prototype = Object.create( LineSegments.prototype ); +Box3Helper.prototype.constructor = Box3Helper; + +Box3Helper.prototype.updateMatrixWorld = function ( force ) { + + var box = this.box; + + if ( box.isEmpty() ) return; + + box.getCenter( this.position ); + + box.getSize( this.scale ); + + this.scale.multiplyScalar( 0.5 ); + + Object3D.prototype.updateMatrixWorld.call( this, force ); + +}; + +/** + * @author WestLangley / http://github.com/WestLangley + */ + +function PlaneHelper( plane, size, hex ) { + + this.type = 'PlaneHelper'; + + this.plane = plane; + + this.size = ( size === undefined ) ? 1 : size; + + var color = ( hex !== undefined ) ? hex : 0xffff00; + + var positions = [ 1, - 1, 1, - 1, 1, 1, - 1, - 1, 1, 1, 1, 1, - 1, 1, 1, - 1, - 1, 1, 1, - 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0 ]; + + var geometry = new BufferGeometry(); + geometry.addAttribute( 'position', new Float32BufferAttribute( positions, 3 ) ); + geometry.computeBoundingSphere(); + + Line.call( this, geometry, new LineBasicMaterial( { color: color } ) ); + + // + + var positions2 = [ 1, 1, 1, - 1, 1, 1, - 1, - 1, 1, 1, 1, 1, - 1, - 1, 1, 1, - 1, 1 ]; + + var geometry2 = new BufferGeometry(); + geometry2.addAttribute( 'position', new Float32BufferAttribute( positions2, 3 ) ); + geometry2.computeBoundingSphere(); + + this.add( new Mesh( geometry2, new MeshBasicMaterial( { color: color, opacity: 0.2, transparent: true, depthWrite: false } ) ) ); + +} + +PlaneHelper.prototype = Object.create( Line.prototype ); +PlaneHelper.prototype.constructor = PlaneHelper; + +PlaneHelper.prototype.updateMatrixWorld = function ( force ) { + + var scale = - this.plane.constant; + + if ( Math.abs( scale ) < 1e-8 ) scale = 1e-8; // sign does not matter + + this.scale.set( 0.5 * this.size, 0.5 * this.size, scale ); + + this.lookAt( this.plane.normal ); + + Object3D.prototype.updateMatrixWorld.call( this, force ); + +}; + /** * @author WestLangley / http://github.com/WestLangley * @author zz85 / http://github.com/zz85 @@ -41911,9 +42458,7 @@ var SceneUtils = { attach: function ( child, scene, parent ) { - var matrixWorldInverse = new Matrix4(); - matrixWorldInverse.getInverse( parent.matrixWorld ); - child.applyMatrix( matrixWorldInverse ); + child.applyMatrix( new Matrix4().getInverse( parent.matrixWorld ) ); scene.remove( child ); parent.add( child ); @@ -42176,6 +42721,12 @@ GridHelper.prototype.setColors = function () { }; +SkeletonHelper.prototype.update = function () { + + console.error( 'THREE.SkeletonHelper: update() no longer needs to be called.' ); + +}; + function WireframeHelper( object, hex ) { console.warn( 'THREE.WireframeHelper has been removed. Use THREE.WireframeGeometry instead.' ); @@ -42293,8 +42844,7 @@ Object.assign( Matrix3.prototype, { }, multiplyVector3Array: function ( a ) { - console.warn( 'THREE.Matrix3: .multiplyVector3Array() has been renamed. Use matrix.applyToVector3Array( array ) instead.' ); - return this.applyToVector3Array( a ); + console.error( 'THREE.Matrix3: .multiplyVector3Array() has been removed.' ); }, applyToBuffer: function( buffer, offset, length ) { @@ -42363,8 +42913,7 @@ Object.assign( Matrix4.prototype, { }, multiplyVector3Array: function ( a ) { - console.warn( 'THREE.Matrix4: .multiplyVector3Array() has been renamed. Use matrix.applyToVector3Array( array ) instead.' ); - return this.applyToVector3Array( a ); + console.error( 'THREE.Matrix4: .multiplyVector3Array() has been removed.' ); }, rotateAxis: function ( v ) { @@ -42887,6 +43436,20 @@ Object.defineProperties( Material.prototype, { console.warn( 'THREE.Material: .wrapRGB has been removed.' ); return new Color(); + } + }, + + shading: { + get: function () { + + console.error( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' ); + + }, + set: function ( value ) { + + console.warn( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' ); + this.flatShading = ( value === FlatShading ); + } } @@ -42940,6 +43503,27 @@ Object.assign( WebGLRenderer.prototype, { }, + getMaxAnisotropy: function () { + + console.warn( 'THREE.WebGLRenderer: .getMaxAnisotropy() is now .capabilities.getMaxAnisotropy().' ); + return this.capabilities.getMaxAnisotropy(); + + }, + + getPrecision: function () { + + console.warn( 'THREE.WebGLRenderer: .getPrecision() is now .capabilities.precision.' ); + return this.capabilities.precision; + + }, + + resetGLState: function () { + + console.warn( 'THREE.WebGLRenderer: .resetGLState() is now .state.reset().' ); + return this.state.reset(); + + }, + supportsFloatTextures: function () { console.warn( 'THREE.WebGLRenderer: .supportsFloatTextures() is now .extensions.get( \'OES_texture_float\' ).' ); @@ -43251,6 +43835,15 @@ AudioAnalyser.prototype.getData = function () { // +CubeCamera.prototype.updateCubeMap = function ( renderer, scene ) { + + console.warn( 'THREE.CubeCamera: .updateCubeMap() is now .update().' ); + return this.update( renderer, scene ); + +}; + +// + var GeometryUtils = { merge: function ( geometry1, geometry2, materialIndexOffset ) { @@ -43370,4 +43963,4 @@ function CanvasRenderer() { } -export { WebGLRenderTargetCube, WebGLRenderTarget, WebGLRenderer, ShaderLib, UniformsLib, UniformsUtils, ShaderChunk, FogExp2, Fog, Scene, LensFlare, Sprite, LOD, SkinnedMesh, Skeleton, Bone, Mesh, LineSegments, LineLoop, Line, Points, Group, VideoTexture, DataTexture, CompressedTexture, CubeTexture, CanvasTexture, DepthTexture, Texture, CompressedTextureLoader, DataTextureLoader, CubeTextureLoader, TextureLoader, ObjectLoader, MaterialLoader, BufferGeometryLoader, DefaultLoadingManager, LoadingManager, JSONLoader, ImageLoader, FontLoader, FileLoader, Loader, Cache, AudioLoader, SpotLightShadow, SpotLight, PointLight, RectAreaLight, HemisphereLight, DirectionalLightShadow, DirectionalLight, AmbientLight, LightShadow, Light, StereoCamera, PerspectiveCamera, OrthographicCamera, CubeCamera, ArrayCamera, Camera, AudioListener, PositionalAudio, AudioContext, AudioAnalyser, Audio, VectorKeyframeTrack, StringKeyframeTrack, QuaternionKeyframeTrack, NumberKeyframeTrack, ColorKeyframeTrack, BooleanKeyframeTrack, PropertyMixer, PropertyBinding, KeyframeTrack, AnimationUtils, AnimationObjectGroup, AnimationMixer, AnimationClip, Uniform, InstancedBufferGeometry, BufferGeometry, GeometryIdCount, Geometry, InterleavedBufferAttribute, InstancedInterleavedBuffer, InterleavedBuffer, InstancedBufferAttribute, Face3, Object3D, Raycaster, Layers, EventDispatcher, Clock, QuaternionLinearInterpolant, LinearInterpolant, DiscreteInterpolant, CubicInterpolant, Interpolant, Triangle, _Math as Math, Spherical, Cylindrical, Plane, Frustum, Sphere, Ray, Matrix4, Matrix3, Box3, Box2, Line3, Euler, Vector4, Vector3, Vector2, Quaternion, Color, MorphBlendMesh, ImmediateRenderObject, VertexNormalsHelper, SpotLightHelper, SkeletonHelper, PointLightHelper, RectAreaLightHelper, HemisphereLightHelper, GridHelper, PolarGridHelper, FaceNormalsHelper, DirectionalLightHelper, CameraHelper, BoxHelper, ArrowHelper, AxisHelper, CatmullRomCurve3, CubicBezierCurve3, QuadraticBezierCurve3, LineCurve3, ArcCurve, EllipseCurve, SplineCurve, CubicBezierCurve, QuadraticBezierCurve, LineCurve, Shape, Path, ShapePath, Font, CurvePath, Curve, ShapeUtils, SceneUtils, WireframeGeometry, ParametricGeometry, ParametricBufferGeometry, TetrahedronGeometry, TetrahedronBufferGeometry, OctahedronGeometry, OctahedronBufferGeometry, IcosahedronGeometry, IcosahedronBufferGeometry, DodecahedronGeometry, DodecahedronBufferGeometry, PolyhedronGeometry, PolyhedronBufferGeometry, TubeGeometry, TubeBufferGeometry, TorusKnotGeometry, TorusKnotBufferGeometry, TorusGeometry, TorusBufferGeometry, TextGeometry, TextBufferGeometry, SphereGeometry, SphereBufferGeometry, RingGeometry, RingBufferGeometry, PlaneGeometry, PlaneBufferGeometry, LatheGeometry, LatheBufferGeometry, ShapeGeometry, ShapeBufferGeometry, ExtrudeGeometry, ExtrudeBufferGeometry, EdgesGeometry, ConeGeometry, ConeBufferGeometry, CylinderGeometry, CylinderBufferGeometry, CircleGeometry, CircleBufferGeometry, BoxGeometry, BoxBufferGeometry, ShadowMaterial, SpriteMaterial, RawShaderMaterial, ShaderMaterial, PointsMaterial, MeshPhysicalMaterial, MeshStandardMaterial, MeshPhongMaterial, MeshToonMaterial, MeshNormalMaterial, MeshLambertMaterial, MeshDepthMaterial, MeshBasicMaterial, LineDashedMaterial, LineBasicMaterial, Material, Float64BufferAttribute, Float32BufferAttribute, Uint32BufferAttribute, Int32BufferAttribute, Uint16BufferAttribute, Int16BufferAttribute, Uint8ClampedBufferAttribute, Uint8BufferAttribute, Int8BufferAttribute, BufferAttribute, REVISION, MOUSE, CullFaceNone, CullFaceBack, CullFaceFront, CullFaceFrontBack, FrontFaceDirectionCW, FrontFaceDirectionCCW, BasicShadowMap, PCFShadowMap, PCFSoftShadowMap, FrontSide, BackSide, DoubleSide, FlatShading, SmoothShading, NoColors, FaceColors, VertexColors, NoBlending, NormalBlending, AdditiveBlending, SubtractiveBlending, MultiplyBlending, CustomBlending, AddEquation, SubtractEquation, ReverseSubtractEquation, MinEquation, MaxEquation, ZeroFactor, OneFactor, SrcColorFactor, OneMinusSrcColorFactor, SrcAlphaFactor, OneMinusSrcAlphaFactor, DstAlphaFactor, OneMinusDstAlphaFactor, DstColorFactor, OneMinusDstColorFactor, SrcAlphaSaturateFactor, NeverDepth, AlwaysDepth, LessDepth, LessEqualDepth, EqualDepth, GreaterEqualDepth, GreaterDepth, NotEqualDepth, MultiplyOperation, MixOperation, AddOperation, NoToneMapping, LinearToneMapping, ReinhardToneMapping, Uncharted2ToneMapping, CineonToneMapping, UVMapping, CubeReflectionMapping, CubeRefractionMapping, EquirectangularReflectionMapping, EquirectangularRefractionMapping, SphericalReflectionMapping, CubeUVReflectionMapping, CubeUVRefractionMapping, RepeatWrapping, ClampToEdgeWrapping, MirroredRepeatWrapping, NearestFilter, NearestMipMapNearestFilter, NearestMipMapLinearFilter, LinearFilter, LinearMipMapNearestFilter, LinearMipMapLinearFilter, UnsignedByteType, ByteType, ShortType, UnsignedShortType, IntType, UnsignedIntType, FloatType, HalfFloatType, UnsignedShort4444Type, UnsignedShort5551Type, UnsignedShort565Type, UnsignedInt248Type, AlphaFormat, RGBFormat, RGBAFormat, LuminanceFormat, LuminanceAlphaFormat, RGBEFormat, DepthFormat, DepthStencilFormat, RGB_S3TC_DXT1_Format, RGBA_S3TC_DXT1_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT5_Format, RGB_PVRTC_4BPPV1_Format, RGB_PVRTC_2BPPV1_Format, RGBA_PVRTC_4BPPV1_Format, RGBA_PVRTC_2BPPV1_Format, RGB_ETC1_Format, LoopOnce, LoopRepeat, LoopPingPong, InterpolateDiscrete, InterpolateLinear, InterpolateSmooth, ZeroCurvatureEnding, ZeroSlopeEnding, WrapAroundEnding, TrianglesDrawMode, TriangleStripDrawMode, TriangleFanDrawMode, LinearEncoding, sRGBEncoding, GammaEncoding, RGBEEncoding, LogLuvEncoding, RGBM7Encoding, RGBM16Encoding, RGBDEncoding, BasicDepthPacking, RGBADepthPacking, BoxGeometry as CubeGeometry, Face4, LineStrip, LinePieces, MeshFaceMaterial, MultiMaterial, PointCloud, Particle, ParticleSystem, PointCloudMaterial, ParticleBasicMaterial, ParticleSystemMaterial, Vertex, DynamicBufferAttribute, Int8Attribute, Uint8Attribute, Uint8ClampedAttribute, Int16Attribute, Uint16Attribute, Int32Attribute, Uint32Attribute, Float32Attribute, Float64Attribute, ClosedSplineCurve3, SplineCurve3, Spline, BoundingBoxHelper, EdgesHelper, WireframeHelper, XHRLoader, BinaryTextureLoader, GeometryUtils, ImageUtils, Projector, CanvasRenderer }; +export { WebGLRenderTargetCube, WebGLRenderTarget, WebGLRenderer, ShaderLib, UniformsLib, UniformsUtils, ShaderChunk, FogExp2, Fog, Scene, LensFlare, Sprite, LOD, SkinnedMesh, Skeleton, Bone, Mesh, LineSegments, LineLoop, Line, Points, Group, VideoTexture, DataTexture, CompressedTexture, CubeTexture, CanvasTexture, DepthTexture, Texture, CompressedTextureLoader, DataTextureLoader, CubeTextureLoader, TextureLoader, ObjectLoader, MaterialLoader, BufferGeometryLoader, DefaultLoadingManager, LoadingManager, JSONLoader, ImageLoader, FontLoader, FileLoader, Loader, Cache, AudioLoader, SpotLightShadow, SpotLight, PointLight, RectAreaLight, HemisphereLight, DirectionalLightShadow, DirectionalLight, AmbientLight, LightShadow, Light, StereoCamera, PerspectiveCamera, OrthographicCamera, CubeCamera, ArrayCamera, Camera, AudioListener, PositionalAudio, AudioContext, AudioAnalyser, Audio, VectorKeyframeTrack, StringKeyframeTrack, QuaternionKeyframeTrack, NumberKeyframeTrack, ColorKeyframeTrack, BooleanKeyframeTrack, PropertyMixer, PropertyBinding, KeyframeTrack, AnimationUtils, AnimationObjectGroup, AnimationMixer, AnimationClip, Uniform, InstancedBufferGeometry, BufferGeometry, GeometryIdCount, Geometry, InterleavedBufferAttribute, InstancedInterleavedBuffer, InterleavedBuffer, InstancedBufferAttribute, Face3, Object3D, Raycaster, Layers, EventDispatcher, Clock, QuaternionLinearInterpolant, LinearInterpolant, DiscreteInterpolant, CubicInterpolant, Interpolant, Triangle, _Math as Math, Spherical, Cylindrical, Plane, Frustum, Sphere, Ray, Matrix4, Matrix3, Box3, Box2, Line3, Euler, Vector4, Vector3, Vector2, Quaternion, Color, ImmediateRenderObject, VertexNormalsHelper, SpotLightHelper, SkeletonHelper, PointLightHelper, RectAreaLightHelper, HemisphereLightHelper, GridHelper, PolarGridHelper, FaceNormalsHelper, DirectionalLightHelper, CameraHelper, BoxHelper, Box3Helper, PlaneHelper, ArrowHelper, AxisHelper, CatmullRomCurve3, CubicBezierCurve3, QuadraticBezierCurve3, LineCurve3, ArcCurve, EllipseCurve, SplineCurve, CubicBezierCurve, QuadraticBezierCurve, LineCurve, Shape, Path, ShapePath, Font, CurvePath, Curve, ShapeUtils, SceneUtils, WebGLUtils, WireframeGeometry, ParametricGeometry, ParametricBufferGeometry, TetrahedronGeometry, TetrahedronBufferGeometry, OctahedronGeometry, OctahedronBufferGeometry, IcosahedronGeometry, IcosahedronBufferGeometry, DodecahedronGeometry, DodecahedronBufferGeometry, PolyhedronGeometry, PolyhedronBufferGeometry, TubeGeometry, TubeBufferGeometry, TorusKnotGeometry, TorusKnotBufferGeometry, TorusGeometry, TorusBufferGeometry, TextGeometry, TextBufferGeometry, SphereGeometry, SphereBufferGeometry, RingGeometry, RingBufferGeometry, PlaneGeometry, PlaneBufferGeometry, LatheGeometry, LatheBufferGeometry, ShapeGeometry, ShapeBufferGeometry, ExtrudeGeometry, ExtrudeBufferGeometry, EdgesGeometry, ConeGeometry, ConeBufferGeometry, CylinderGeometry, CylinderBufferGeometry, CircleGeometry, CircleBufferGeometry, BoxGeometry, BoxBufferGeometry, ShadowMaterial, SpriteMaterial, RawShaderMaterial, ShaderMaterial, PointsMaterial, MeshPhysicalMaterial, MeshStandardMaterial, MeshPhongMaterial, MeshToonMaterial, MeshNormalMaterial, MeshLambertMaterial, MeshDepthMaterial, MeshDistanceMaterial, MeshBasicMaterial, LineDashedMaterial, LineBasicMaterial, Material, Float64BufferAttribute, Float32BufferAttribute, Uint32BufferAttribute, Int32BufferAttribute, Uint16BufferAttribute, Int16BufferAttribute, Uint8ClampedBufferAttribute, Uint8BufferAttribute, Int8BufferAttribute, BufferAttribute, REVISION, MOUSE, CullFaceNone, CullFaceBack, CullFaceFront, CullFaceFrontBack, FrontFaceDirectionCW, FrontFaceDirectionCCW, BasicShadowMap, PCFShadowMap, PCFSoftShadowMap, FrontSide, BackSide, DoubleSide, FlatShading, SmoothShading, NoColors, FaceColors, VertexColors, NoBlending, NormalBlending, AdditiveBlending, SubtractiveBlending, MultiplyBlending, CustomBlending, AddEquation, SubtractEquation, ReverseSubtractEquation, MinEquation, MaxEquation, ZeroFactor, OneFactor, SrcColorFactor, OneMinusSrcColorFactor, SrcAlphaFactor, OneMinusSrcAlphaFactor, DstAlphaFactor, OneMinusDstAlphaFactor, DstColorFactor, OneMinusDstColorFactor, SrcAlphaSaturateFactor, NeverDepth, AlwaysDepth, LessDepth, LessEqualDepth, EqualDepth, GreaterEqualDepth, GreaterDepth, NotEqualDepth, MultiplyOperation, MixOperation, AddOperation, NoToneMapping, LinearToneMapping, ReinhardToneMapping, Uncharted2ToneMapping, CineonToneMapping, UVMapping, CubeReflectionMapping, CubeRefractionMapping, EquirectangularReflectionMapping, EquirectangularRefractionMapping, SphericalReflectionMapping, CubeUVReflectionMapping, CubeUVRefractionMapping, RepeatWrapping, ClampToEdgeWrapping, MirroredRepeatWrapping, NearestFilter, NearestMipMapNearestFilter, NearestMipMapLinearFilter, LinearFilter, LinearMipMapNearestFilter, LinearMipMapLinearFilter, UnsignedByteType, ByteType, ShortType, UnsignedShortType, IntType, UnsignedIntType, FloatType, HalfFloatType, UnsignedShort4444Type, UnsignedShort5551Type, UnsignedShort565Type, UnsignedInt248Type, AlphaFormat, RGBFormat, RGBAFormat, LuminanceFormat, LuminanceAlphaFormat, RGBEFormat, DepthFormat, DepthStencilFormat, RGB_S3TC_DXT1_Format, RGBA_S3TC_DXT1_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT5_Format, RGB_PVRTC_4BPPV1_Format, RGB_PVRTC_2BPPV1_Format, RGBA_PVRTC_4BPPV1_Format, RGBA_PVRTC_2BPPV1_Format, RGB_ETC1_Format, LoopOnce, LoopRepeat, LoopPingPong, InterpolateDiscrete, InterpolateLinear, InterpolateSmooth, ZeroCurvatureEnding, ZeroSlopeEnding, WrapAroundEnding, TrianglesDrawMode, TriangleStripDrawMode, TriangleFanDrawMode, LinearEncoding, sRGBEncoding, GammaEncoding, RGBEEncoding, LogLuvEncoding, RGBM7Encoding, RGBM16Encoding, RGBDEncoding, BasicDepthPacking, RGBADepthPacking, BoxGeometry as CubeGeometry, Face4, LineStrip, LinePieces, MeshFaceMaterial, MultiMaterial, PointCloud, Particle, ParticleSystem, PointCloudMaterial, ParticleBasicMaterial, ParticleSystemMaterial, Vertex, DynamicBufferAttribute, Int8Attribute, Uint8Attribute, Uint8ClampedAttribute, Int16Attribute, Uint16Attribute, Int32Attribute, Uint32Attribute, Float32Attribute, Float64Attribute, ClosedSplineCurve3, SplineCurve3, Spline, BoundingBoxHelper, EdgesHelper, WireframeHelper, XHRLoader, BinaryTextureLoader, GeometryUtils, ImageUtils, Projector, CanvasRenderer }; diff --git a/docs/api/cameras/Camera.html b/docs/api/cameras/Camera.html index a669574278ee86..31b046f76bfadd 100644 --- a/docs/api/cameras/Camera.html +++ b/docs/api/cameras/Camera.html @@ -80,14 +80,6 @@

[method:Vector3 getWorldDirection]( [page:Vector3 optionalTarget] )

(which can be reused in this way), otherwise a new vector will be created. -

[method:null lookAt]( [page:Vector3 target] )

-
- target — position in 3D space for the camera to point towards

- - This makes the camera look at the vector position in the global space as long as - the parent of this camera is the scene or at position (0,0,0). -
-

Source

[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] diff --git a/docs/api/cameras/CubeCamera.html b/docs/api/cameras/CubeCamera.html index bcf8713810ccd1..773d1047f31922 100644 --- a/docs/api/cameras/CubeCamera.html +++ b/docs/api/cameras/CubeCamera.html @@ -20,21 +20,21 @@

Examples

[example:webgl_materials_cubemap_dynamic2 materials / cubemap / dynamic2 ]
[example:webgl_shading_physical shading / physical ]
- //Create cube camera + // Create cube camera var cubeCamera = new THREE.CubeCamera( 1, 100000, 128 ); scene.add( cubeCamera ); - //Create car + // Create car var chromeMaterial = new THREE.MeshLambertMaterial( { color: 0xffffff, envMap: cubeCamera.renderTarget } ); var car = new Mesh( carGeometry, chromeMaterial ); scene.add( car ); - //Update the render target cube + // Update the render target cube car.setVisible( false ); cubeCamera.position.copy( car.position ); - cubeCamera.updateCubeMap( renderer, scene ); + cubeCamera.update( renderer, scene ); - //Render the scene + // Render the scene car.setVisible( true ); renderer.render( scene, camera ); @@ -67,7 +67,7 @@

Methods

See the base [page:Object3D] class for common methods.
-

[method:null updateCubeMap]( [page:WebGLRenderer renderer], [page:Scene scene] )

+

[method:null update]( [page:WebGLRenderer renderer], [page:Scene scene] )

renderer -- The current WebGL renderer
scene -- The current scene @@ -76,6 +76,12 @@

[method:null updateCubeMap]( [page:WebGLRenderer renderer], [page:Scene scen Call this to update the [page:CubeCamera.renderTarget renderTarget].

+

[method:null clear]( [page:WebGLRenderer renderer], [page:Boolean color], [page:Boolean depth], [page:Boolean stencil] )

+
+ Call this to clear the [page:CubeCamera.renderTarget renderTarget] color, depth, and/or stencil buffers. + The color buffer is set to the renderer's current clear color. Arguments default to *true*. +
+

Source

[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] diff --git a/docs/api/cameras/OrthographicCamera.html b/docs/api/cameras/OrthographicCamera.html index 0cfff9dfdf0bc2..eee68a2f9bb48e 100644 --- a/docs/api/cameras/OrthographicCamera.html +++ b/docs/api/cameras/OrthographicCamera.html @@ -58,7 +58,11 @@

[name]( [page:Number left], [page:Number right], [page:Number top], [page:Nu

Properties

-
See the base [page:Camera] class for common properties.
+
+ See the base [page:Camera] class for common properties.
+ Note that after making changes to most of these poperties you will have to call + [page:OrthographicCamera.updateProjectionMatrix .updateProjectionMatrix] for the changes to take effect. +

[property:Float bottom]

Camera frustum bottom plane.
diff --git a/docs/api/cameras/PerspectiveCamera.html b/docs/api/cameras/PerspectiveCamera.html index 2132f229f37158..3f6a2665fa6256 100644 --- a/docs/api/cameras/PerspectiveCamera.html +++ b/docs/api/cameras/PerspectiveCamera.html @@ -48,7 +48,11 @@

[name]( [page:Number fov], [page:Number aspect], [page:Number near], [page:N

Properties

-
See the base [page:Camera] class for common properties.
+
+ See the base [page:Camera] class for common properties.
+ Note that after making changes to most of these poperties you will have to call + [page:PerspectiveCamera.updateProjectionMatrix .updateProjectionMatrix] for the changes to take effect. +

[property:Float aspect]

Camera frustum aspect ratio, usually the canvas width / canvas height. Default is *1* (square canvas).
@@ -103,9 +107,6 @@

[property:number zoom]

Gets or sets the zoom factor of the camera. Default is *1*.
- - -

Methods

See the base [page:Camera] class for common methods.
diff --git a/docs/api/constants/CustomBlendingEquations.html b/docs/api/constants/CustomBlendingEquations.html index 31e035f45ea3f5..0e2aca2117da1c 100644 --- a/docs/api/constants/CustomBlendingEquations.html +++ b/docs/api/constants/CustomBlendingEquations.html @@ -22,7 +22,7 @@

Usage

material.blending = THREE.CustomBlending; material.blendEquation = THREE.AddEquation; //default material.blendSrc = THREE.SrcAlphaFactor; //default - material.blendDst = THREE.OneMinusDstAlphaFactor; //default + material.blendDst = THREE.OneMinusSrcAlphaFactor; //default

Blending Equations

diff --git a/docs/api/constants/Materials.html b/docs/api/constants/Materials.html index 8c6f418036e688..15ffac93220d8a 100644 --- a/docs/api/constants/Materials.html +++ b/docs/api/constants/Materials.html @@ -28,16 +28,6 @@

Side

-

Shading

- - THREE.SmoothShading - THREE.FlatShading - -
- [page:Constant SmoothShading] is the default and linearly interpolates color between vertices.
- [page:Constant FlatShading] uses the color of the first vertex for every pixel in a face. -
-

Colors

THREE.NoColors diff --git a/docs/api/constants/Renderer.html b/docs/api/constants/Renderer.html index 01aa3c9bda7ba7..fd951c70e1911b 100644 --- a/docs/api/constants/Renderer.html +++ b/docs/api/constants/Renderer.html @@ -33,7 +33,7 @@

Front Face Direction

These are used by the WebGLRenderer's [page:WebGLRenderer.setFaceCulling setFaceCulling] method.

[page:constant FrontFaceDirectionCW] sets the winding order for polygons to clockwise.
- [page:constant FrontFaceDirectionCW] sets the winding order for polygons to counter-clockwise (default). + [page:constant FrontFaceDirectionCCW] sets the winding order for polygons to counter-clockwise (default).

Shadow Types

diff --git a/docs/api/constants/Textures.html b/docs/api/constants/Textures.html index aad5df7d737486..32de717397c40c 100644 --- a/docs/api/constants/Textures.html +++ b/docs/api/constants/Textures.html @@ -33,9 +33,14 @@

Mapping Modes

[page:Constant CubeReflectionMapping] is the default for a [page:CubeTexture CubeTexture].

[page:Constant EquirectangularReflectionMapping] and [page:Constant EquirectangularRefractionMapping] - are for use with an equirectangular environment map.

- - [page:Constant SphericalReflectionMapping] is for use with a spherical reflection map.

+ are for use with an equirectangular environment map. Also called a lat-long map, an equirectangular + texture represents a 360-degree view along the horizontal centerline, and a 180-degree view along the + vertical axis, with the top and bottom edges of the image corresponding to the north and south poles + of a mapped sphere.

+ + [page:Constant SphericalReflectionMapping] is for use with a spherical reflection map such as may be obtained + by cropping a photograph of a mirrored ball. Sphere maps will be rendered "facing" the camera, irrespective + of the position of the camera relative to the cubemapped object or surface.

See the [example:webgl_materials_envmaps materials / envmaps] example. diff --git a/docs/api/core/Face3.html b/docs/api/core/Face3.html index a24163b320a4fc..b78660b905b9c1 100644 --- a/docs/api/core/Face3.html +++ b/docs/api/core/Face3.html @@ -21,7 +21,7 @@

Examples

[example:misc_ubiquity_test ubiquity / test ]
[example:svg_sandbox svg / sandbox ]
-
[example:webgl_exporter_obj WebGL / exporter / obj ]
+
[example:misc_exporter_obj exporter / obj ]
[example:webgl_shaders_vector WebGL / shaders / vector ]
diff --git a/docs/api/core/InterleavedBufferAttribute.html b/docs/api/core/InterleavedBufferAttribute.html index 88f398b9966aac..e5dfb35e9bd7e0 100644 --- a/docs/api/core/InterleavedBufferAttribute.html +++ b/docs/api/core/InterleavedBufferAttribute.html @@ -27,6 +27,19 @@

[property:InterleavedBuffer data]

The [page:InterleavedBuffer InterleavedBuffer] instance passed in the constructor. +

[property:TypedArray array]

+
+ The value of [page:InterleavedBufferAttribute.data data].array. +
+ +

[property:Integer count]

+
+ The value of [page:InterleavedBufferAttribute.data data].count. + + If the buffer is storing a 3-component vector (such as a position, normal, or color), + then this will count the number of such vectors stored. +
+

[property:Integer itemSize]

@@ -47,16 +60,6 @@

[property:Boolean isInterleavedBufferAttribute]

Methods

-

[method:Integer count]()

-
- The value of [page:InterleavedBufferAttribute.data data].count. -
- -

[method:Array array]()

-
- The value of [page:InterleavedBufferAttribute.data data].array. -
-

[method:null getX]( index )

diff --git a/docs/api/core/Layers.html b/docs/api/core/Layers.html index 9b73b9b6213dc4..c44e606ab755ff 100644 --- a/docs/api/core/Layers.html +++ b/docs/api/core/Layers.html @@ -11,15 +11,14 @@

[name]

- An object providing a [link:https://en.wikipedia.org/wiki/Mask_(computing) bit mask] and accessor methods - used to control an [page:Object3D]'s visibility. - A [page:Layers] object assigns an [page:Object3D] to 0 or more of 32 layers numbered 0 to 31.

+ A [page:Layers] object assigns an [page:Object3D] to 1 or more of 32 layers numbered 0 to 31 + - internally the layers are stored as a [link:https://en.wikipedia.org/wiki/Mask_(computing) bit mask], and by default all + Object3Ds are a member of layer 0.

- This is used to control visibility - an object must share a layer with a [page:Camera camera] - to be visible when that camera's view is renderered.

+ This can be used to control visibility - an object must share a layer with a [page:Camera camera] to be visible when that camera's + view is renderered.

- All classes that inherit from [page:Object3D] have a [property:layers] property which is an instance - of this class. + All classes that inherit from [page:Object3D] have an [page:Object3D.layers] property which is an instance of this class.
@@ -28,14 +27,14 @@

Constructor

[name]()

- Create a new Layers object, with an initial mask set to layer 1. + Create a new Layers object, with membership initially set to layer 0.

Properties

[property:Integer mask]

- Internal layer mask. + A bit mask storing which of the 32 layers this layers object is currently a member of.
@@ -43,37 +42,37 @@

Methods

[method:null disable]( [page:Integer layer] )

- layer - an integer from 0 to 31.

+ layer - an integer from 0 to 31.

- Remove *layer* from the mask. + Remove membership of this *layer*.

[method:null enable]( [page:Integer layer] )

- layer - an integer from 0 to 31.

+ layer - an integer from 0 to 31.

- Add *layer* to the mask. + Add membership of this *layer*.

[method:null set]( [page:Integer layer] )

- layer - an integer from 0 to 31.

+ layer - an integer from 0 to 31.

- Set the layer mask to the value *layer*. + Set membership to *layer*, and remove membership all other layers.

[method:Boolean test]( [page:Integer layers] )

- layers - a 32bit bit mask of layer numbers.

+ layers - a Layers object

- Returns true if *layers* and [page:.mask] have any bits set in common. + Returns true if this and the passed *layers* object are members of the same set of layers.

[method:null toggle]( [page:Integer layer] )

- layer - an integer from 0 to 31.

+ layer - an integer from 0 to 31.

- Toggle the *layer* value in the mask. + Toggle membership of *layer*.

Source

diff --git a/docs/api/core/Object3D.html b/docs/api/core/Object3D.html index 4ad28094c9bbe3..814a95c7df6800 100644 --- a/docs/api/core/Object3D.html +++ b/docs/api/core/Object3D.html @@ -112,7 +112,7 @@

[property:Object3D parent]

Object's parent in the [link:https://en.wikipedia.org/wiki/Scene_graph scene graph].

[property:Vector3 position]

-
The object's local position.
+
A [page:Vector3] representing the object's local position. Default is (0, 0, 0).

[property:Quaternion quaternion]

Object's local rotation as a [page:Quaternion Quaternion].
@@ -287,11 +287,17 @@

[method:Vector3 localToWorld]( [page:Vector3 vector] )

Converts the vector from local space to world space.
-

[method:null lookAt]( [page:Vector3 vector] )

+

[method:null lookAt]( [page:Vector3 vector] )
+ [method:null lookAt]( [page:Float x], [page:Float y], [page:Float z] )

vector - A vector representing a position in world space.

+ Optionally, the [page:.x x], [page:.y y] and [page:.z z] components of the world space position.

+ + Rotates the object to face a point in world space.

+ + This method does not support objects with rotated and/or translated parent(s). +
- Rotates the object to face a point in world space.

[method:Array raycast]( [page:Raycaster raycaster], [page:Array intersects] )

diff --git a/docs/api/extras/CurveUtils.html b/docs/api/extras/CurveUtils.html deleted file mode 100644 index 2d1ee29da8e6d9..00000000000000 --- a/docs/api/extras/CurveUtils.html +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - - - - - -

[name]

- -
- A class containing utility functions for curves.

- - Note that these are all linear functions so it is neccessary to calculate separately for - x, y (and z, w if present) components of a curve. -
- - -

Methods

- -

[method:Number interpolate]( p0, p1, p2, p3, t )

-
- t -- interpolation weight.
- p0, p1, p2, p4 -- the points defining the spline curve.

- - Used internally by [page:SplineCurve SplineCurve]. -
- -

[method:Number tangentQuadraticBezier]( t, p0, p1, p2 )

-
- t -- the point at which to calculate the tangent.
- p0, p1, p2 -- the three points defining the quadratic Bézier curve.

- - Calculate the tangent at the point t on a quadratic Bézier curve given by the three points.

- - Used internally by [page:QuadraticBezierCurve QuadraticBezierCurve]. -
- -

[method:Number tangentCubicBezier]( t, p0, p1, p2, p3 )

-
- t -- the point at which to calculate the tangent.
- p0, p1, p2, p3 -- the points defining the cubic Bézier curve.

- - Calculate the tangent at the point t on a cubic Bézier curve given by the four points.

- - Used internally by [page:CubicBezierCurve CubicBezierCurve]. -
- -

[method:Number tangentSpline]( t, p0, p1, p2, p3 )

-
- t -- the point at which to calculate the tangent.
- p0, p1, p2, p3 -- the points defining the spline curve.

- - Calculate the tangent at the point t on a spline curve given by the four points. -
- -

Source

- - [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] - - diff --git a/docs/api/extras/core/Font.html b/docs/api/extras/core/Font.html index 69f1f31778ef02..8acbee33b35349 100644 --- a/docs/api/extras/core/Font.html +++ b/docs/api/extras/core/Font.html @@ -50,7 +50,7 @@

[method:null generateShapes]( [page:String text], [page:Float size], [page:I
[page:String text] -- string of text.
[page:Float size] -- (optional) scale for the [page:Shape Shapes]. Default is *100*.
- [page:Integer divisions] -- (optional) fineness of the [page:Shape Shapes]. Default is *5*.
+ [page:Integer divisions] -- (optional) fineness of the [page:Shape Shapes]. Default is *4*.
Creates an array of [page:Shape Shapes] representing the text in the font.
diff --git a/docs/api/extras/core/Interpolations.html b/docs/api/extras/core/Interpolations.html new file mode 100644 index 00000000000000..89c48d85109877 --- /dev/null +++ b/docs/api/extras/core/Interpolations.html @@ -0,0 +1,47 @@ + + + + + + + + + + +

[name]

+ +
+ TODO +
+ +

Methods

+ +

[method:Float CatmullRom]( [page:Float t], [page:Float p0], [page:Float p1], [page:Float p2], [page:Float p3] )

+
+ t -- interpolation weight.
+ p0, p1, p2, p3 -- the points defining the spline curve.

+ + Used internally by [page:SplineCurve SplineCurve]. +
+ +

[method:Float QuadraticBezier]( [page:Float t], [page:Float p0], [page:Float p1], [page:Float p2] )

+
+ t -- interpolation weight.
+ p0, p1, p2 -- the starting, control and end points defining the curve.

+ + Used internally by [page:QuadraticBezierCurve3 QuadraticBezierCurve3], [page:QuadraticBezierCurve QuadraticBezierCurve] and [page:Font Font]. +
+ +

[method:Float CubicBezier]( [page:Float t], [page:Float p0], [page:Float p1], [page:Float p2], [page:Float p3] )

+
+ t -- interpolation weight.
+ p0, p1, p2, p3 -- the starting, control(twice) and end points defining the curve.

+ + Used internally by [page:CubicBezierCurve3 CubicBezierCurve3], [page:CubicBezierCurve CubicBezierCurve] and [page:Font Font]. +
+ +

Source

+ + [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] + + diff --git a/docs/api/extras/core/Shape.html b/docs/api/extras/core/Shape.html index f067ebe87b4b8f..e535b7a5f9baa6 100644 --- a/docs/api/extras/core/Shape.html +++ b/docs/api/extras/core/Shape.html @@ -41,7 +41,6 @@

Examples

[example:webgl_geometry_shapes geometry / shapes ]
[example:webgl_geometry_extrude_shapes geometry / extrude / shapes ]
[example:webgl_geometry_extrude_shapes2 geometry / extrude / shapes2 ]
- [example:webgl_particles_shapes particles / shapes ] diff --git a/docs/api/extras/curves/SplineCurve.html b/docs/api/extras/curves/SplineCurve.html index 63371dd03c6624..e06f836e44d658 100644 --- a/docs/api/extras/curves/SplineCurve.html +++ b/docs/api/extras/curves/SplineCurve.html @@ -14,7 +14,7 @@

[name]

Create a smooth 2d spline curve from a series of points. Internally this uses - [page:CurveUtils.interpolate] to create the curve. + [page:Interpolations.CatmullRom] to create the curve.

Example

diff --git a/docs/api/extras/objects/MorphBlendMesh.html b/docs/api/extras/objects/MorphBlendMesh.html deleted file mode 100644 index 1b1cd148628ef6..00000000000000 --- a/docs/api/extras/objects/MorphBlendMesh.html +++ /dev/null @@ -1,179 +0,0 @@ - - - - - - - - - - - [page:Mesh] → - -

[name]

- -
A mesh that can blend together multiple animated morph targets.
- -

Example

- [example:webgl_morphtargets_md2_control morphtargets / md2 / controll] - - -

Constructor

- - -

[name]([page:Geometry geometry], [page:Material material])

-
- geometry — An instance of [page:Geometry].
- material — An instance of [page:Material] (optional). -
- -

Properties

- - -

[property:object animationsMap]

-
- An object of named animations as added by [page:MorphBlendMesh.createAnimation]. -
- -

[property:array animationsList]

-
- The list of animations as added by [page:MorphBlendMesh.createAnimation]. -
- -

Methods

- - - -

[method:null setAnimationWeight]([page:String name], [page:Float weight])

-
- name -- The name of the animation
- weight -- Weight of the animation, typically 0-1 -
-
- Set the weight of how much this animation will apply to the overall morph. 0 is off, 1 is full weight. -
- -

[method:null setAnimationFPS]([page:String name], [page:Float fps])

-
- name -- The name of the animation
- fps -- The number of frames (morphTargets) per second -
-
- A frame is typically 1 morph target. -
- -

[method:null createAnimation]([page:String name], [page:Integer start], [page:Integer end], [page:Float fps])

-
- name -- The name of the animation
- start -- The starting frame (morph)
- end -- The ending frame (morph)
- fps -- How many frames (morphs) to play per second -
-
- Creates an animation object that gets added to both the [page:MorphBlendMesh.animationsMap animationsMap] and - [page:MorphBlendMesh.animationsList animationsList].

- - Animation object:

- startFrame -- Starting frame
- endFrame -- Ending frame
- length -- The number of frames
- fps -- The frames per second
- duration -- The length of the animation in seconds
- lastFrame -- The previous frame that was played
- currentFrame -- The current frame
- active -- Whether or not the animation is being played
- time -- The time in seconds of the animation
- direction -- Which way to play the animation
- weight -- The weight of the animation
- directionBackwards -- Is playing backwards
- mirroredLoop -- Loop back and forth -
- -

[method:null playAnimation]([page:String name])

-
- name -- The name of the animation -
-
- Sets the animation to active and animation time to 0 -
- -

[method:null update]([page:Float delta])

-
- delta -- Time in seconds -
-
- Updates and plays the animation -
- -

[method:null autoCreateAnimations]([page:Float fps])

-
- fps -- Frames per second -
-
- Goes through the geometry's morphTargets and generates animations based on the morphTargets' names. Names - are of the form "walk_01", "walk_02", "walk_03", etc or "run001", "run002", "run003". -
- -

[method:null setAnimationDuration]([page:String name], [page:Float duration])

-
- name -- The name of the animation
- duration -- How long in seconds to play the animation -
-
- Updates the animation object with proper values to update the duration. -
- -

[method:null setAnimationDirectionForward]([page:String name])

-
- name -- The name of the animation -
-
- Sets the animation to play forwards -
- -

[method:null setAnimationDirectionBackward]([page:String name])

-
- name -- The name of the animation -
-
- Sets the animation to play backwards -
- -

[method:Float getAnimationDuration]([page:String name])

-
- name -- The name of the animation -
-
- Returns the duration in seconds of the animation. Returns -1 if it can't be found. -
- -

[method:Float getAnimationTime]([page:String name])

-
- name -- The name of the animation -
-
- Returns the current time position of the animation. -
- -

[method:null setAnimationTime]([page:String name], [page:Float time])

-
- name -- The name of the animation
- time -- The time in seconds -
-
- Sets the current time position of the animation -
- -

[method:null stopAnimation]([page:String name])

-
- name -- The name of the animation -
-
- Stops the playback of the animation -
- -

Source

- - [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] - - diff --git a/docs/api/geometries/RingBufferGeometry.html b/docs/api/geometries/RingBufferGeometry.html index 7e2dd26718df67..25dc8748662696 100644 --- a/docs/api/geometries/RingBufferGeometry.html +++ b/docs/api/geometries/RingBufferGeometry.html @@ -44,7 +44,7 @@

Constructor

[name]([page:Float innerRadius], [page:Float outerRadius], [page:Integer thetaSegments], [page:Integer phiSegments], [page:Float thetaStart], [page:Float thetaLength])

- innerRadius — Default is 0, but it doesn't work right when innerRadius is set to 0.
+ innerRadius — Default is 20.
outerRadius — Default is 50.
thetaSegments — Number of segments. A higher number means the ring will be more round. Minimum is 3. Default is 8.
phiSegments — Minimum is 1. Default is 8.
diff --git a/docs/api/geometries/RingGeometry.html b/docs/api/geometries/RingGeometry.html index 2dc05b190c0065..de992cd450de68 100644 --- a/docs/api/geometries/RingGeometry.html +++ b/docs/api/geometries/RingGeometry.html @@ -44,7 +44,7 @@

Constructor

[name]([page:Float innerRadius], [page:Float outerRadius], [page:Integer thetaSegments], [page:Integer phiSegments], [page:Float thetaStart], [page:Float thetaLength])

- innerRadius — Default is 0, but it doesn't work right when innerRadius is set to 0.
+ innerRadius — Default is 20.
outerRadius — Default is 50.
thetaSegments — Number of segments. A higher number means the ring will be more round. Minimum is 3. Default is 8.
phiSegments — Minimum is 1. Default is 8.
diff --git a/docs/api/geometries/TextBufferGeometry.html b/docs/api/geometries/TextBufferGeometry.html new file mode 100644 index 00000000000000..01fc1db4102c14 --- /dev/null +++ b/docs/api/geometries/TextBufferGeometry.html @@ -0,0 +1,161 @@ + + + + + + + + + + + [page:ExtrudeBufferGeometry] → + +

[name]

+ +
+ A class for generating text as a single geometry. It is constructed by providing a string of text, and a hash of + parameters consisting of a loaded [page:Font] and settings for the geometry's parent [page:ExtrudeBufferGeometry]. + See the [page:Font], [page:FontLoader] and [page:Creating_Text] pages for additional details. +
+ + + + + +

Examples

+ +
+ [example:webgl_geometry_text geometry / text ]
+ [example:webgl_geometry_text_pnltri geometry / text2 ] +
+ + + var loader = new THREE.FontLoader(); + + loader.load( 'fonts/helvetiker_regular.typeface.json', function ( font ) { + + var geometry = new THREE.TextBufferGeometry( 'Hello three.js!', { + font: font, + size: 80, + height: 5, + curveSegments: 12, + bevelEnabled: true, + bevelThickness: 10, + bevelSize: 8, + bevelSegments: 5 + } ); + } ); + + +

Constructor

+ +

[name]([page:String text], [page:Object parameters])

+
+ text — The text that needs to be shown.
+ parameters — Object that can contains the following parameters. +
    +
  • font — an instance of THREE.Font.
  • +
  • size — Float. Size of the text. Default is 100.
  • +
  • height — Float. Thickness to extrude text. Default is 50.
  • +
  • curveSegments — Integer. Number of points on the curves. Default is 12.
  • +
  • bevelEnabled — Boolean. Turn on bevel. Default is False.
  • +
  • bevelThickness — Float. How deep into text bevel goes. Default is 10.
  • +
  • bevelSize — Float. How far from text outline is bevel. Default is 8.
  • +
  • bevelSegments — Integer. Number of bevel segments. Default is 3.
  • +
+
+ +

Available Fonts

+ +
+ TextGeometry uses typeface.json generated fonts. + Some existing fonts can be found located in /examples/fonts and must be included in the page. +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FontWeightStyleFile Path
helvetikernormalnormal/examples/fonts/helvetiker_regular.typeface.json
helvetikerboldnormal/examples/fonts/helvetiker_bold.typeface.json
optimernormalnormal/examples/fonts/optimer_regular.typeface.json
optimerboldnormal/examples/fonts/optimer_bold.typeface.json
gentilisnormalnormal/examples/fonts/gentilis_regular.typeface.json
gentilisboldnormal/examples/fonts/gentilis_bold.typeface.json
droid sansnormalnormal/examples/fonts/droid/droid_sans_regular.typeface.json
droid sansboldnormal/examples/fonts/droid/droid_sans_bold.typeface.json
droid serifnormalnormal/examples/fonts/droid/droid_serif_regular.typeface.json
droid serifboldnormal/examples/fonts/droid/droid_serif_bold.typeface.json
+ +

Source

+ + [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] + + diff --git a/docs/api/helpers/DirectionalLightHelper.html b/docs/api/helpers/DirectionalLightHelper.html index 6b193d201de0b9..b9ebc566924e07 100644 --- a/docs/api/helpers/DirectionalLightHelper.html +++ b/docs/api/helpers/DirectionalLightHelper.html @@ -1,7 +1,7 @@ - + @@ -32,10 +32,13 @@

Example

Constructor

-

[name]( [page:DirectionalLight light], [page:Number size] )

+

[name]( [page:DirectionalLight light], [page:Number size], [page:Hex color] )

- [page:DirectionalLight light]-- The light to be visualized.
- [page:Number size] -- (optional) dimensions of the plane. Default is *1*.

+ [page:DirectionalLight light]-- The light to be visualized.

+ + [page:Number size] -- (optional) dimensions of the plane. Default is *1*.

+ + [page:Hex color] -- (optional) if this is not the set the helper will take the color of the light.
@@ -58,6 +61,11 @@

[property:object matrixAutoUpdate]

light's [page:Object3D.matrixWorld matrixWorld].
+

[property:hex color]

+
+ The color parameter passed in the constructor. Default is *undefined*. If this is changed, + the helper's color will update the next time [page:.update update] is called. +

Methods

diff --git a/docs/api/helpers/HemisphereLightHelper.html b/docs/api/helpers/HemisphereLightHelper.html index 1c0aefd2742dc8..06b7421107948a 100644 --- a/docs/api/helpers/HemisphereLightHelper.html +++ b/docs/api/helpers/HemisphereLightHelper.html @@ -1,7 +1,7 @@ - + @@ -29,10 +29,13 @@

Example

Constructor

-

[name]([page:HemisphereLight light], [page:Number sphereSize])

+

[name]( [page:HemisphereLight light], [page:Number sphereSize], [page:Hex color] )

- [page:HemisphereLight light] -- The light being visualized.
- [page:Number size] -- The size of the mesh used to visualize the light. + [page:HemisphereLight light] -- The light being visualized.

+ + [page:Number size] -- The size of the mesh used to visualize the light.

+ + [page:Hex color] -- (optional) if this is not the set the helper will take the color of the light.
@@ -51,6 +54,12 @@

[property:object matrixAutoUpdate]

hemisphereLight's [page:Object3D.matrixWorld matrixWorld].
+

[property:hex color]

+
+ The color parameter passed in the constructor. Default is *undefined*. If this is changed, the helper's color will update + the next time [page:.update update] is called. +
+

Methods

See the base [page:Object3D] class for common methods.
diff --git a/docs/api/helpers/PointLightHelper.html b/docs/api/helpers/PointLightHelper.html index 721545c6900d6b..60f0a7a8c3d45e 100644 --- a/docs/api/helpers/PointLightHelper.html +++ b/docs/api/helpers/PointLightHelper.html @@ -1,7 +1,7 @@ - + @@ -37,12 +37,14 @@

Example

Constructor

-

[name]( [page:PointLight light], [page:Float sphereSize] )

+

[name]( [page:PointLight light], [page:Float sphereSize], [page:Hex color] )

- [page:PointLight light] -- The light to be visualized.
- [page:Float sphereSize] -- (optional) The size of the sphere helper. Default is *1*. -
+ [page:PointLight light] -- The light to be visualized.

+ + [page:Float sphereSize] -- (optional) The size of the sphere helper. Default is *1*.

+ [page:Hex color] -- (optional) if this is not the set the helper will take the color of the light. +

Properties

See the base [page:Mesh] class for common properties.
@@ -59,7 +61,12 @@

[property:object matrixAutoUpdate]

pointLight's [page:Object3D.matrixWorld matrixWorld]. - +

[property:hex color]

+
+ The color parameter passed in the constructor. Default is *undefined*. If this is changed, the helper's color will update + the next time [page:.update update] is called. +
+

Methods

See the base [page:Mesh] class for common methods.
diff --git a/docs/api/helpers/RectAreaLightHelper.html b/docs/api/helpers/RectAreaLightHelper.html index 3ea1c2cbcc367c..fcdd10ffef2a8c 100644 --- a/docs/api/helpers/RectAreaLightHelper.html +++ b/docs/api/helpers/RectAreaLightHelper.html @@ -29,8 +29,12 @@

Example

Constructor

-

[name]( [page:RectAreaLight light] )

-
[page:RectAreaLight light] -- The light being visualized.
+

[name]( [page:RectAreaLight light], [page:Hex color] )

+
+ [page:RectAreaLight light] -- The light being visualized.

+ + [page:Hex color] -- (optional) if this is not the set the helper will take the color of the light. +

Properties

@@ -39,6 +43,12 @@

Properties

[property:RectAreaLight light]

Reference to the RectAreaLight being visualized.
+

[property:hex color]

+
+ The color parameter passed in the constructor. Default is *undefined*. If this is changed, the helper's color will update + the next time [page:.update update] is called. +
+

Methods

See the base [page:Object3D] class for common methods.
diff --git a/docs/api/helpers/SkeletonHelper.html b/docs/api/helpers/SkeletonHelper.html index f7a8ab74a74ace..284228a4db70d6 100644 --- a/docs/api/helpers/SkeletonHelper.html +++ b/docs/api/helpers/SkeletonHelper.html @@ -53,20 +53,7 @@

[property:Object root]

The object passed in the constructor.
- -

Methods

- -

[method:Array getBoneList]( object )

-
- getBoneList -- the object used in the constructor.

- - This is called automatically to generate a list of bones from the object passed in the constructor. -
- -

[method:null update]()

-
- Update the helper. Call in the render loop if animating the model. -
+

Source

diff --git a/docs/api/helpers/SpotLightHelper.html b/docs/api/helpers/SpotLightHelper.html index a51d93a0d16886..c0e8e5234857f6 100644 --- a/docs/api/helpers/SpotLightHelper.html +++ b/docs/api/helpers/SpotLightHelper.html @@ -35,8 +35,12 @@

Code Example

Constructor

-

[name]([page:SpotLight light])

-
light -- The [page:SpotLight] to be visualized.
+

[name]( [page:SpotLight light], [page:Hex color] )

+
+ [page:SpotLight light] -- The [page:SpotLight] to be visualized.

+ + [page:Hex color] -- (optional) if this is not the set the helper will take the color of the light. +

Properties

@@ -45,7 +49,6 @@

Properties

[property:LineSegments cone]

[page:LineSegments] used to visualize the light.
-

[property:SpotLight light]

Reference to the [page:SpotLight] being visualized.
@@ -58,6 +61,11 @@

[property:object matrixAutoUpdate]

spotLight's [page:Object3D.matrixWorld matrixWorld]. +

[property:hex color]

+
+ The color parameter passed in the constructor. Default is *undefined*. If this is changed, the helper's color will update + the next time [page:.update update] is called. +

Methods

See the base [page:Object3D] class for common methods.
diff --git a/docs/api/lights/DirectionalLight.html b/docs/api/lights/DirectionalLight.html index fb65890f7d5460..b157cf84e3339a 100644 --- a/docs/api/lights/DirectionalLight.html +++ b/docs/api/lights/DirectionalLight.html @@ -43,7 +43,7 @@

Example

[example:canvas_morphtargets_horse morphtargets / horse ]
[example:misc_controls_fly controls / fly ]
[example:misc_lights_test lights / test ]
- [example:vr_cubes cubes ]
+ [example:webvr_cubes cubes ]
[example:webgl_effects_parallaxbarrier effects / parallaxbarrier ]
[example:webgl_effects_stereo effects / stereo ]
[example:webgl_geometry_extrude_splines geometry / extrude / splines ]
diff --git a/docs/api/lights/PointLight.html b/docs/api/lights/PointLight.html index df4ed7ffdda04a..191ae24de850ba 100644 --- a/docs/api/lights/PointLight.html +++ b/docs/api/lights/PointLight.html @@ -27,9 +27,7 @@

Example

[example:webgl_lights_pointlights lights / pointlights ]
[example:webgl_lights_pointlights2 lights / pointlights2 ]
[example:webgldeferred_animation animation ]
- [example:webgldeferred_pointlights pointlights ]
[example:webgl_effects_anaglyph effects / anaglyph ]
- [example:webgl_geometry_large_mesh geometry / large / mesh ]
[example:webgl_geometry_text geometry / text ]
[example:webgl_lensflares lensflares ] diff --git a/docs/api/lights/RectAreaLight.html b/docs/api/lights/RectAreaLight.html index 14737c357ddb44..0e3e223e910a60 100644 --- a/docs/api/lights/RectAreaLight.html +++ b/docs/api/lights/RectAreaLight.html @@ -28,7 +28,6 @@

[name]

Examples

- [example:webgl_lights_arealight WebGL / arealight ]
[example:webgl_lights_rectarealight WebGL / rectarealight ] diff --git a/docs/api/lights/SpotLight.html b/docs/api/lights/SpotLight.html index 16d7818458a3d7..35b8fd441325be 100644 --- a/docs/api/lights/SpotLight.html +++ b/docs/api/lights/SpotLight.html @@ -36,7 +36,7 @@

Other Examples

[example:webgl_interactive_draggablecubes interactive / draggablecubes ]
[example:webgl_materials_bumpmap_skin materials / bumpmap / skin ]
[example:webgl_materials_cubemap_dynamic materials / cubemap / dynamic ]
- [example:webgl_morphtargets_md2 morphtargets / md2 ]
+ [example:webgl_loader_md2 loader / md2 ]
[example:webgl_shading_physical shading / physical ]
[example:webgl_materials_bumpmap materials / bumpmap]
[example:webgl_shading_physical shading / physical]
diff --git a/docs/api/loaders/AnimationLoader.html b/docs/api/loaders/AnimationLoader.html index c216aafbfd3751..4fb699433375fa 100644 --- a/docs/api/loaders/AnimationLoader.html +++ b/docs/api/loaders/AnimationLoader.html @@ -11,7 +11,7 @@

[name]

- Class for loading an animation in JSON format. + Class for loading [page:AnimationClip AnimationClips] in JSON format. This uses the [page:FileLoader] internally for loading files.
@@ -26,8 +26,8 @@

Example

// resource URL 'animations/animation.js', // Function when resource is loaded - function ( animation ) { - // do something with the animation + function ( animations ) { + // animations is an array of AnimationClips }, // Function called when download progresses function ( xhr ) { diff --git a/docs/api/loaders/FontLoader.html b/docs/api/loaders/FontLoader.html index 852e898f3ae17c..58f99a7c1da668 100644 --- a/docs/api/loaders/FontLoader.html +++ b/docs/api/loaders/FontLoader.html @@ -63,6 +63,8 @@

[property:LoadingManager manager]

The [page:LoadingManager loadingManager] the loader is using. Default is [page:DefaultLoadingManager].
+

[property:String path]

+
The base path from which fonts will be loaded. See [page:.setPath]. Default is *undefined*.

Methods

@@ -83,6 +85,12 @@

[method:Font parse]( [page:Object json] )

Parse a JSON structure and return a [page:Font]. +

[method:FontLoader setPath]( [page:String path] )

+
+ Set the base path or URL from which to load fonts. This can be useful if + you are loading many fonts from the same directory. +
+

Source

[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] diff --git a/docs/api/loaders/TextureLoader.html b/docs/api/loaders/TextureLoader.html index 983b482859245b..bcf19e178f29bd 100644 --- a/docs/api/loaders/TextureLoader.html +++ b/docs/api/loaders/TextureLoader.html @@ -17,6 +17,17 @@

[name]

Example

+ + var texture = new THREE.TextureLoader().load( 'textures/land_ocean_ice_cloud_2048.jpg' ); + + // immediately use the texture for material creation + var material = new THREE.MeshBasicMaterial( { map: texture } ); + + + [example:webgl_geometry_cube geometry / cube] + +

Example with Callbacks

+ // instantiate a loader var loader = new THREE.TextureLoader(); @@ -27,24 +38,22 @@

Example

'textures/land_ocean_ice_cloud_2048.jpg', // Function when resource is loaded function ( texture ) { - // do something with the texture + // in this example we create the material when the texture is loaded var material = new THREE.MeshBasicMaterial( { map: texture } ); }, // Function called when download progresses function ( xhr ) { - console.log( (xhr.loaded / xhr.total * 100) + '% loaded' ); + console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' ); }, // Function called when download errors function ( xhr ) { - console.log( 'An error happened' ); + console.error( 'An error happened' ); } );
- [example:canvas_geometry_earth] -

Constructor

[name]( [page:LoadingManager manager] )

@@ -81,7 +90,7 @@

[property:String withCredentials]

Methods

-

[method:null load]( [page:String url], [page:Function onLoad], [page:Function onProgress], [page:Function onError] )

+

[method:Texture load]( [page:String url], [page:Function onLoad], [page:Function onProgress], [page:Function onError] )

[page:String url] — the path or URL to the file. This can also be a [link:https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs Data URI].
@@ -89,7 +98,8 @@

[method:null load]( [page:String url], [page:Function onLoad], [page:Functio [page:Function onProgress] — Will be called while load progresses. The argument will be the XMLHttpRequest instance, which contains .[page:Integer total] and .[page:Integer loaded] bytes.
[page:Function onError] — Will be called when load errors.

- Begin loading from url and pass the loaded [page:Texture texture] to onLoad. + Begin loading from the given URL and pass the fully loaded [page:Texture texture] to onLoad. The method also returns a new texture object which can directly be used for material creation. + If you do it this way, the texture may pop up in your scene once the respective loading process is finished.

[method:null setCrossOrigin]( [page:String value] )

diff --git a/docs/api/loaders/managers/LoadingManager.html b/docs/api/loaders/managers/LoadingManager.html index 3d03bde7a149fc..9f992000ca1bae 100644 --- a/docs/api/loaders/managers/LoadingManager.html +++ b/docs/api/loaders/managers/LoadingManager.html @@ -130,14 +130,14 @@

[method:null itemStart]( [page:String url] )

[page:String url] — the url to load

- This should be called by any loader used by the manager when the loader starts loading an url. + This should be called by any loader using the manager when the loader starts loading an url.

[method:null itemEnd]( [page:String url] )

[page:String url] — the loaded url

- This should be called by any loader used by the manager when the loader ended loading an url. + This should be called by any loader using the manager when the loader ended loading an url.
@@ -145,7 +145,7 @@

[method:null itemError]( [page:String url] )

[page:String url] — the loaded url

- This should be called by any loader used by the manager when the loader errors loading an url. + This should be called by any loader using the manager when the loader errors loading an url.

Source

diff --git a/docs/api/materials/Material.html b/docs/api/materials/Material.html index c61aa6c56897b9..91270a04e1d6f6 100644 --- a/docs/api/materials/Material.html +++ b/docs/api/materials/Material.html @@ -84,7 +84,7 @@

[property:Array clippingPlanes]

User-defined clipping planes specified as THREE.Plane objects in world space. These planes apply to the objects this material is attached to. - Points in space whose dot product with the plane is negative are cut away. + Points in space whose signed distance to the plane is negative are clipped (not rendered). See the [example:webgl_clipping_intersection WebGL / clipping /intersection] example. Default is *null*.
@@ -102,12 +102,15 @@

[property:Boolean colorWrite]

[property:Material customDepthMaterial]

- Custom depth material to be used by this material in depth based computation. If a material uses any custom logic to position the vertices (animation, displacement other than the default texture based, instancing...) the depth material should also include that logic in order to make effects like shadows and SSAO work. Defining this property allows the WebGLRenderer to use this instance of the material instead of the internal cache. Default is *undefined*. + Custom depth material to be used by this material when rendering to the depth map. + When shadow-casting with a [page:DirectionalLight] or [page:SpotLight], if you are (a) modifying vertex positions in the vertex shader, + (b) using a displacement map, (c) using an alpha map with alphaTest, or (d) using a transparent texture with alphaTest, + you must specify a customDepthMaterial for proper shadows. Default is *undefined*.

[property:Material customDistanceMaterial]

- Same as customDepthMaterial but used for specific computation (point lights for example). Default is *undefined* + Same as customDepthMaterial, but used with [page:PointLight]. Default is *undefined*.

[property:Object defines]

@@ -204,10 +207,9 @@

[property:Boolean dithering]

Default is *false*. -

[property:Integer shading]

+

[property:Boolean flatShading]

- Defines how the material is shaded. - This can be either [page:Materials THREE.SmoothShading] (default) or [page:Materials THREE.FlatShading]. + Define whether the material is rendered with flat shading. Default is false.

[property:Integer side]

@@ -250,7 +252,12 @@

[property:Boolean visible]

Defines whether this material is visible. Default is *true*.
- + +

[property:object userData]

+
+ An object that can be used to store custom data about the Material. It should not hold + references to functions as these will not be cloned. +

Methods

diff --git a/docs/api/materials/MeshBasicMaterial.html b/docs/api/materials/MeshBasicMaterial.html index cdebb8ca6a17d2..681b1a3d72bbe2 100644 --- a/docs/api/materials/MeshBasicMaterial.html +++ b/docs/api/materials/MeshBasicMaterial.html @@ -63,7 +63,9 @@

[property:Texture alphaMap]

[property:Texture aoMap]

-
The red channel of this texture is used as the ambient occlusion map. Default is null. The aoMap requires a second set of UVs.
+
The red channel of this texture is used as the ambient occlusion map. Default is null. + The aoMap requires a second set of UVs, and consequently will ignore the [page:Texture repeat] + and [page:Texture offset] Texture properties.

[property:Float aoMapIntensity]

Intensity of the ambient occlusion effect. Default is 1. Zero is no occlusion effect.
@@ -91,7 +93,9 @@

[property:TextureCube envMap]

The environment map. Default is null.

[property:Texture lightMap]

-
The light map. Default is null. The lightMap requires a second set of UVs.
+
The light map. Default is null. The lightMap requires a second set of UVs, + and consequently will ignore the [page:Texture repeat] and [page:Texture offset] + Texture properties.

[property:Float lightMapIntensity]

Intensity of the baked light. Default is 1.
@@ -107,10 +111,17 @@

[property:Boolean morphTargets]

[property:Float reflectivity]

-
How much the environment map affects the surface; also see [page:.combine].
+
+ How much the environment map affects the surface; also see [page:.combine]. + The default value is 1 and the valid range is between 0 (no reflections) and 1 (full reflections). +

[property:Float refractionRatio]

-
The index of refraction for an environment map using [page:Textures THREE.CubeRefractionMapping]. Default is *0.98*.
+
+ The index of refraction (IOR) of air (approximately 1) divided by the index of refraction of the material. + It is used with environment mapping modes [page:Textures THREE.CubeRefractionMapping] and [page:Textures THREE.EquirectangularRefractionMapping]. + The refraction ratio should not exceed 1. Default is *0.98*. +

[property:Boolean skinning]

Define whether the material uses skinning. Default is false.
diff --git a/docs/api/materials/MeshLambertMaterial.html b/docs/api/materials/MeshLambertMaterial.html index 3187ea49dc628b..e0a984c2bea97b 100644 --- a/docs/api/materials/MeshLambertMaterial.html +++ b/docs/api/materials/MeshLambertMaterial.html @@ -15,8 +15,8 @@

[name]

A material for non-shiny surfaces, without specular highlights.

- The uses a non-physically based [link:https://en.wikipedia.org/wiki/Lambertian_reflectance Lambertian] - model for calculating reflectance. This can simulate some surfaces (such as untreated wood or stone) well, + The material uses a non-physically based [link:https://en.wikipedia.org/wiki/Lambertian_reflectance Lambertian] + model for calculating reflectance. This can simulate some surfaces (such as untreated wood or stone) well, but cannot simulate shiny surfaces with specular highlights (such as varnished wood).

@@ -74,7 +74,9 @@

[property:Texture alphaMap]

[property:Texture aoMap]

-
The red channel of this texture is used as the ambient occlusion map. Default is null. The aoMap requires a second set of UVs.
+
The red channel of this texture is used as the ambient occlusion map. Default is null. + The aoMap requires a second set of UVs, and consequently will ignore the [page:Texture repeat] + and [page:Texture offset] Texture properties.

[property:Float aoMapIntensity]

Intensity of the ambient occlusion effect. Default is 1. Zero is no occlusion effect.
@@ -118,7 +120,9 @@

[property:Boolean isMeshLambertMaterial]

[property:Texture lightMap]

-
The light map. Default is null. The lightMap requires a second set of UVs.
+
The light map. Default is null. The lightMap requires a second set of UVs, + and consequently will ignore the [page:Texture repeat] and [page:Texture offset] + Texture properties.

[property:Float lightMapIntensity]

Intensity of the baked light. Default is 1.
@@ -139,7 +143,11 @@

[property:Float reflectivity]

How much the environment map affects the surface; also see [page:.combine].

[property:Float refractionRatio]

-
The index of refraction for an environment map using [page:Textures THREE.CubeRefractionMapping]. Default is *0.98*.
+
+ The index of refraction (IOR) of air (approximately 1) divided by the index of refraction of the material. + It is used with environment mapping modes [page:Textures THREE.CubeRefractionMapping] and [page:Textures THREE.EquirectangularRefractionMapping]. + The refraction ratio should not exceed 1. Default is *0.98*. +

[property:Boolean skinning]

Define whether the material uses skinning. Default is false.
diff --git a/docs/api/materials/MeshPhongMaterial.html b/docs/api/materials/MeshPhongMaterial.html index 4912d3ff4214d9..d2806816830789 100644 --- a/docs/api/materials/MeshPhongMaterial.html +++ b/docs/api/materials/MeshPhongMaterial.html @@ -15,8 +15,8 @@

[name]

A material for shiny surfaces with specular highlights.

- The uses a non-physically based [link:https://en.wikipedia.org/wiki/Blinn-Phong_shading_model Blinn-Phong] - model for calculating reflectance. Unlike the Lambertian model used in the [page:MeshLambertMaterial] + The material uses a non-physically based [link:https://en.wikipedia.org/wiki/Blinn-Phong_shading_model Blinn-Phong] + model for calculating reflectance. Unlike the Lambertian model used in the [page:MeshLambertMaterial] this can simulate shiny surfaces with specular highlights (such as varnished wood).

Shading is calculated using a [link:https://en.wikipedia.org/wiki/Phong_shading Phong] shading model. @@ -73,7 +73,9 @@

[property:Texture alphaMap]

[property:Texture aoMap]

-
The red channel of this texture is used as the ambient occlusion map. Default is null. The aoMap requires a second set of UVs.
+
The red channel of this texture is used as the ambient occlusion map. Default is null. + The aoMap requires a second set of UVs, and consequently will ignore the [page:Texture repeat] + and [page:Texture offset] Texture properties.

[property:Float aoMapIntensity]

Intensity of the ambient occlusion effect. Default is 1. Zero is no occlusion effect.
@@ -151,7 +153,9 @@

[property:Boolean isMeshPhongMaterial]

[property:Texture lightMap]

-
The light map. Default is null. The lightMap requires a second set of UVs.
+
The light map. Default is null. The lightMap requires a second set of UVs, + and consequently will ignore the [page:Texture repeat] and [page:Texture offset] + Texture properties.

[property:Float lightMapIntensity]

Intensity of the baked light. Default is 1.
@@ -182,10 +186,17 @@

[property:Vector2 normalScale]

[property:Float reflectivity]

-
How much the environment map affects the surface; also see [page:.combine].
+
+ How much the environment map affects the surface; also see [page:.combine]. + The default value is 1 and the valid range is between 0 (no reflections) and 1 (full reflections). +

[property:Float refractionRatio]

-
The index of refraction for an environment map using [page:Textures THREE.CubeRefractionMapping]. Default is *0.98*.
+
+ The index of refraction (IOR) of air (approximately 1) divided by the index of refraction of the material. + It is used with environment mapping modes [page:Textures THREE.CubeRefractionMapping] and [page:Textures THREE.EquirectangularRefractionMapping]. + The refraction ratio should not exceed 1. Default is *0.98*. +

[property:Float shininess]

How shiny the [page:.specular] highlight is; a higher value gives a sharper highlight. Default is *30*.
diff --git a/docs/api/materials/MeshStandardMaterial.html b/docs/api/materials/MeshStandardMaterial.html index 5c7fadafe01633..d32e47e7f81260 100644 --- a/docs/api/materials/MeshStandardMaterial.html +++ b/docs/api/materials/MeshStandardMaterial.html @@ -97,7 +97,9 @@

[property:Texture alphaMap]

[property:Texture aoMap]

-
The red channel of this texture is used as the ambient occlusion map. Default is null. The aoMap requires a second set of UVs.
+
The red channel of this texture is used as the ambient occlusion map. Default is null. + The aoMap requires a second set of UVs, and consequently will ignore the [page:Texture repeat] + and [page:Texture offset] Texture properties.

[property:Float aoMapIntensity]

Intensity of the ambient occlusion effect. Default is 1. Zero is no occlusion effect.
@@ -164,7 +166,11 @@

[property:Float emissiveIntensity]

Intensity of the emissive light. Modulates the emissive color. Default is 1.

[property:TextureCube envMap]

-
The environment map. Default is null.
+
The environment map. Default is null. Note that in order for the material roughness + property to correctly blur out the environment map, the shader must have access to mipmaps + of the env texture. TextureCubes created with default settings are correctly configured; + if adjusting texture parameters manually, ensure minFilter is set to one of the MipMap options, + and that mip maps have not been otherwise forcibly disabled.

[property:Float envMapIntensity]

Scales the effect of the environment map by multiplying its color.
@@ -178,7 +184,9 @@

[property:Boolean isMeshStandardMaterial]

[property:Texture lightMap]

-
The light map. Default is null. The lightMap requires a second set of UVs.
+
The light map. Default is null. The lightMap requires a second set of UVs, + and consequently will ignore the [page:Texture repeat] and [page:Texture offset] + Texture properties.

[property:Float lightMapIntensity]

Intensity of the baked light. Default is 1.
@@ -218,7 +226,11 @@

[property:Vector2 normalScale]

[property:Float refractionRatio]

-
The index of refraction for an environment map using [page:Textures THREE.CubeRefractionMapping]. Default is *0.98*.
+
+ The index of refraction (IOR) of air (approximately 1) divided by the index of refraction of the material. + It is used with environment mapping modes [page:Textures THREE.CubeRefractionMapping] and [page:Textures THREE.EquirectangularRefractionMapping]. + The refraction ratio should not exceed 1. Default is *0.98*. +

[property:Float roughness]

diff --git a/docs/api/materials/PointsMaterial.html b/docs/api/materials/PointsMaterial.html index 466270de7444f3..089d2f813dc1e6 100644 --- a/docs/api/materials/PointsMaterial.html +++ b/docs/api/materials/PointsMaterial.html @@ -44,11 +44,11 @@

Examples

star.y = THREE.Math.randFloatSpread( 2000 ); star.z = THREE.Math.randFloatSpread( 2000 ); - starsGeometry.vertices.push( star ) + starsGeometry.vertices.push( star ); } -var starsMaterial = new THREE.PointsMaterial( { color: 0x888888 } ) +var starsMaterial = new THREE.PointsMaterial( { color: 0x888888 } ); var starField = new THREE.Points( starsGeometry, starsMaterial ); diff --git a/docs/api/materials/ShaderMaterial.html b/docs/api/materials/ShaderMaterial.html index 1718117407cac3..58ada31e0bc135 100644 --- a/docs/api/materials/ShaderMaterial.html +++ b/docs/api/materials/ShaderMaterial.html @@ -14,7 +14,7 @@

[name]

A material rendered with custom shaders. A shader is a small program written in - [link:https://www.khronos.org/files/opengles_shading_language.pdf_ES GLSL] that runs on the GPU. + [link:https://www.khronos.org/files/opengles_shading_language.pdf GLSL] that runs on the GPU. You may want to use a custom shader if you need to:
  • implement an effect not included with any of the built-in [page:Material materials]
  • @@ -40,7 +40,7 @@

    [name]

    must be used instead.
  • - Built in attributes an uniforms are passed to the shaders along with your code. + Built in attributes and uniforms are passed to the shaders along with your code. If you don't want the [page:WebGLProgram] to add anything to your shader code, you can use [page:RawShaderMaterial] instead of this class.
  • @@ -296,7 +296,7 @@

    [property:Object defines]

    [property:Object extensions]

    - An object with the folowing properties: + An object with the following properties: this.extensions = { derivatives: false, // set to use derivatives @@ -371,10 +371,9 @@

    [property:WebGLProgram program]

    You should not need to access this property.
    -

    [property:Number shading]

    +

    [property:Boolean flatShading]

    - Define shading type, which determines whether normals are smoothed between vertices; - possible values are [page:Materials THREE.SmoothShading] or [page:Materials THREE.FlatShading]. Default is THREE.SmoothShading. + Define whether the material is rendered with flat shading. Default is false.
    diff --git a/docs/api/math/Euler.html b/docs/api/math/Euler.html index cd48e70b4593fc..9c01c3fed5f23e 100644 --- a/docs/api/math/Euler.html +++ b/docs/api/math/Euler.html @@ -54,19 +54,10 @@

    [property:String order]

    rotated around its X axis, then its Y axis and finally its Z axis. Other possibilities are: 'YZX', 'ZXY', 'XZY', 'YXZ' and 'ZYX'. These must be in upper case.

    - Three.js uses intrinsic (Tait-Bryan) ordering, also known as yaw, pitch - and roll. This means that rotations are performed with respect to the local - coordinate system. That is, for order 'XYZ', the rotation is first around world-X, then around - local-Y (which may now be different from the world Y-axis), then local-Z (which may be different - from the world Z-axis).

    - - Some implementations may use extrinsic (proper) ordering, in which case rotations are performed - with respect to the world coordinate system, so that for order 'XYZ', the rotations - are around world-X, world-Y, and world-Z.

    - - Converting between the two types is relatively straightforward, you just need to reverse the order - and the rotation, so that an intrinsic (three.js) Euler rotation of angles a, b, c about XYZ - will be equivalent to to an extrinsic Euler rotation of angles c, b, a about ZYX.

    + Three.js uses intrinsic Tait-Bryan angles. This means that rotations are performed with respect + to the local coordinate system. That is, for order 'XYZ', the rotation is first around the local-X + axis (which is the same as the world-X axis), then around local-Y (which may now be different from the + world Y-axis), then local-Z (which may be different from the world Z-axis).

    If the order is changed, [page:.onChangeCallback onChangeCallback] will be called.
diff --git a/docs/api/math/Matrix3.html b/docs/api/math/Matrix3.html index bc61e89ac034d5..161fe209e2e10d 100644 --- a/docs/api/math/Matrix3.html +++ b/docs/api/math/Matrix3.html @@ -169,6 +169,23 @@

[method:Matrix3 premultiply]( [page:Matrix3 m] )

[method:Matrix3 setFromMatrix4]( [page:Matrix4 m] )

Set this matrx to the upper 3x3 matrix of the Matrix4 [page:Matrix4 m].
+

+ [method:Matrix3 setUvTransform]( + [page:Float tx], [page:Float ty], [page:Float sx], [page:Float sy], + [page:Float rotation], [page:Float cx], [page:Float cy] ) +

+
+ [page:Float tx] - offset x
+ [page:Float ty] - offset y
+ [page:Float sx] - repeat x
+ [page:Float sy] - repeat y
+ [page:Float rotation] - rotation (in radians)
+ [page:Float cx] - center x of rotation
+ [page:Float cy] - center y of rotation

+ + Sets the UV transform matrix from offset, repeat, rotation, and center. +
+

[method:Array toArray]( [page:Array array], [page:Integer offset] )

[page:Array array] - (optional) array to store the resulting vector in. If not given a new array will be created.
diff --git a/docs/api/math/Matrix4.html b/docs/api/math/Matrix4.html index e6eb0cfca8e686..d0a733a8d450b5 100644 --- a/docs/api/math/Matrix4.html +++ b/docs/api/math/Matrix4.html @@ -75,7 +75,7 @@

A Note on Row-Major and Column-Major Ordering

and internally all calculations are performed using column-major ordering. However, as the actual ordering makes no difference mathematically and most people are used to thinking about matrices in row-major order, the three.js documentation shows matrices in row-major order. Just bear in mind that if you are reading the source - code, you'll have to take the [link: https://en.wikipedia.org/wiki/Transpose transpose] of any matrices outlined here to make sense of the calculations. + code, you'll have to take the [link:https://en.wikipedia.org/wiki/Transpose transpose] of any matrices outlined here to make sense of the calculations.
@@ -260,7 +260,7 @@

[method:Matrix4 makeRotationFromQuaternion]( [page:Quaternion q] )

[link:https://en.wikipedia.org/wiki/Rotation_matrix#Quaternion here]. The rest of the matrix is set to the identity. So, given [page:Quaternion q] = w + xi + yj + zk, the resulting matrix will be: -1-2y²-2z² 2xy-2zw 2xz-2yw 0 +1-2y²-2z² 2xy-2zw 2xz+2yw 0 2xy+2zw 1-2x²-2z² 2yz-2xw 0 2xz-2yw 2yz+2xw 1-2x²-2y² 0 0 0 0 1 diff --git a/docs/api/math/Plane.html b/docs/api/math/Plane.html index c697cfed885cfa..51c1aa689ba011 100644 --- a/docs/api/math/Plane.html +++ b/docs/api/math/Plane.html @@ -11,9 +11,8 @@

[name]

- A two dimensional surface that extends infinitely in 3d space, defined by - a [link:https://en.wikipedia.org/wiki/Normal_(geometry) normal vector], and a - distance from the origin along the normal. + A two dimensional surface that extends infinitely in 3d space, represented in [link:http://mathworld.wolfram.com/HessianNormalForm.html Hessian normal form] + by a unit length normal vector and a constant.
@@ -22,10 +21,8 @@

Constructor

[name]( [page:Vector3 normal], [page:Float constant] )

- [page:Vector3 normal] - (optional) a [page:Vector3] defining the direction of the - plane. Default is *(1, 0, 0)*.
- [page:Float constant] - (optional) the negative distance from the origin to the plane along - the [page:Vector3 normal] vector. Default is *0*. + [page:Vector3 normal] - (optional) a unit length [page:Vector3] defining the normal of the plane. Default is *(1, 0, 0)*.
+ [page:Float constant] - (optional) the signed distance from the origin to the plane. Default is *0*.
@@ -68,10 +65,10 @@

[method:Plane copy]( [page:Plane plane] )

[method:Float distanceToPoint]( [page:Vector3 point] )

-
Returns the smallest distance from the [page:Vector3 point] to the plane.
+
Returns the signed distance from the [page:Vector3 point] to the plane.

[method:Float distanceToSphere]( [page:Sphere sphere] )

-
Returns the smallest distance from the [page:Sphere sphere] to the plane.
+
Returns the signed distance from the [page:Sphere sphere] to the plane.

[method:Boolean equals]( [page:Plane plane] )

@@ -113,8 +110,7 @@

[method:Boolean intersectsSphere]( [page:Sphere sphere] )

[method:Plane negate]()

- Negates both the normal vector and constant, effectively mirroring the plane across - the origin. + Negates both the normal vector and the constant.

[method:Plane normalize]()

@@ -123,44 +119,31 @@

[method:Plane normalize]()

value accordingly.
-

[method:Vector3 orthoPoint]( [page:Vector3 point], [page:Vector3 optionalTarget] )

-
- [page:Vector3 point] - [page:Vector3]
- [page:Vector3 optionalTarget] - (optional) if specified, the result will be copied - into this [page:Vector3], otherwise a new [page:Vector3] will be created.

- - Returns a vector in the same direction as the Plane's normal, but with magnitude - equal to the passed point's original distance to the plane. -
-

[method:Vector3 projectPoint]( [page:Vector3 point], [page:Vector3 optionalTarget] )

[page:Vector3 point] - the [page:Vector3] to project onto the plane.
[page:Vector3 optionalTarget] - (optional) if specified, the result will be copied into this [page:Vector3], otherwise a new [page:Vector3] will be created.

- Projects a [page:Vector3 point] onto the plane. The projected point is the closest - point on the plane to the passed point, so a line drawn from the projected point - and the passed point would be orthogonal to the plane. + Projects a [page:Vector3 point] onto the plane.

[method:Plane set]( [page:Vector3 normal], [page:Float constant] )

- [page:Vector3 normal] - a [page:Vector3] defining the direction of the plane.
- [page:Float constant] - (optional) the negative distance from the origin to the plane along - the [page:Vector3 normal] vector. Default is *0*.

+ [page:Vector3 normal] - a unit length [page:Vector3] defining the normal of the plane.
+ [page:Float constant] - the signed distance from the origin to the plane. Default is *0*.

Sets the plane's [page:.normal normal] and [page:.constant constant] properties.

[method:Plane setComponents]( [page:Float x], [page:Float y], [page:Float z], [page:Float w] )

- [page:Float x] - x value of the normal vector.
- [page:Float y] - y value of the normal vector.
- [page:Float z] - z value of the normal vector.
+ [page:Float x] - x value of the unit length normal vector.
+ [page:Float y] - y value of the unit length normal vector.
+ [page:Float z] - z value of the unit length normal vector.
[page:Float w] - the value of the plane's [page:.constant constant] property.

- Set the individual components that make up the plane. + Set the individual components that define the plane.

[method:Plane setFromCoplanarPoints]( [page:Vector3 a], [page:Vector3 b], [page:Vector3 c] )

@@ -169,13 +152,13 @@

[method:Plane setFromCoplanarPoints]( [page:Vector3 a], [page:Vector3 b], [p [page:Vector3 a] - second point on the plane.
[page:Vector3 a] - third point on the plane.

- Defines the plane based on the 3 provided points. The winding order is counter - clockwise, and determines which direction the [page:.normal normal] will point. + Defines the plane based on the 3 provided points. The winding order is assumed to be counter-clockwise, + and determines the direction of the [page:.normal normal].

[method:Plane setFromNormalAndCoplanarPoint]( [page:Vector3 normal], [page:Vector3 point] ) [page:Vector3 this]

- [page:Vector3 normal] - a [page:Vector3] defining the direction of the plane.
+ [page:Vector3 normal] - a unit length [page:Vector3] defining the normal of the plane.
[page:Vector3 point] - [page:Vector3]

Sets the plane's properties as defined by a [page:Vector3 normal] and an arbitrary coplanar [page:Vector3 point]. @@ -185,9 +168,8 @@

[method:Plane translate]( [page:Vector3 offset] )

[page:Vector3 offset] - the amount to move the plane by.

- Translates the plane the distance defined by the [page:Vector3 offset] vector. - Note that this only affects the constant (distance from origin) and will not affect - the normal vector. + Translates the plane by the distance defined by the [page:Vector3 offset] vector. + Note that this only affects the plane constant and will not affect the normal vector.

Source

diff --git a/docs/api/math/Vector2.html b/docs/api/math/Vector2.html index 96ec0486646728..76d3e05a740cce 100644 --- a/docs/api/math/Vector2.html +++ b/docs/api/math/Vector2.html @@ -97,6 +97,11 @@

[method:Float angle]()

Computes the angle in radians of this vector with respect to the positive x-axis.
+

[method:Vector2 applyMatrix3]( [page:Matrix3 m] )

+
+ Multiplies this vector (with an implicit 1 as the 3rd component) by m. +
+

[method:Vector2 ceil]()

The [page:.x x] and [page:.y y] components of the vector are rounded up to the nearest integer value. diff --git a/docs/api/math/Vector4.html b/docs/api/math/Vector4.html index 83e562dc852285..98bbc7d9a870bc 100644 --- a/docs/api/math/Vector4.html +++ b/docs/api/math/Vector4.html @@ -110,6 +110,15 @@

[method:Vector4 clamp]( [page:Vector4 min], [page:Vector4 max] )

If this vector's x, y, z or w value is less than the min vector's x, y, z or w value, it is replaced by the corresponding value.
+

[method:Vector4 clampLength]( [page:Float min], [page:Float max] )

+
+ [page:Float min] - the minimum value the length will be clamped to
+ [page:Float max] - the maximum value the length will be clamped to

+ + If this vector's length is greater than the max value, it is replaced by the max value.

+ If this vector's length is less than the min value, it is replaced by the min value. +
+

[method:Vector4 clampScalar]( [page:Float min], [page:Float max] )

[page:Float min] - the minimum value the components will be clamped to
diff --git a/docs/api/objects/Group.html b/docs/api/objects/Group.html index 66ef2215fa08a5..d80b4067eed9cd 100644 --- a/docs/api/objects/Group.html +++ b/docs/api/objects/Group.html @@ -13,7 +13,7 @@

[name]

- This is almost identical to an [page:Object3D Object3D]. It's purpose is to make working + This is almost identical to an [page:Object3D Object3D]. Its purpose is to make working with groups of objects syntactically clearer.
@@ -28,7 +28,7 @@

Example

cubeA.position.set( 100, 100, 0 ); var cubeB = new THREE.Mesh( geometry, material ); - cubeA.position.set( -100, -100, 0 ); + cubeB.position.set( -100, -100, 0 ); //create a group and add the two cubes //These cubes can now be rotated / scaled etc as a group diff --git a/docs/api/objects/Mesh.html b/docs/api/objects/Mesh.html index fffe69cb2faab7..4251ac88d84a87 100644 --- a/docs/api/objects/Mesh.html +++ b/docs/api/objects/Mesh.html @@ -14,7 +14,7 @@

[name]

Class representing triangular [link:https://en.wikipedia.org/wiki/Polygon_mesh polygon mesh] based objects. - Also serves as a base for other classes such as [page:MorphBlendMesh] and [page:SkinnedMesh]. + Also serves as a base for other classes such as [page:SkinnedMesh].
diff --git a/docs/api/renderers/WebGLRenderTarget.html b/docs/api/renderers/WebGLRenderTarget.html index 7dfc002cbfccdf..c66a392d64f525 100644 --- a/docs/api/renderers/WebGLRenderTarget.html +++ b/docs/api/renderers/WebGLRenderTarget.html @@ -1,134 +1,134 @@ - - - + + + - - - - - - -

[name]

- -
- A [link:https://msdn.microsoft.com/en-us/library/bb976073.aspx render target] is a buffer - where the video card draws pixels for a scene that is being rendered in the background. - It is used in different effects, such as applying postprocessing to a rendered image - before displaying it on the screen. -
- - -

Constructor

- - -

[name]([page:Number width], [page:Number height], [page:Object options])

- -
- [page:Float width] - The width of the renderTarget.
- [page:Float height] - The height of the renderTarget.
- options - (optional0 object that holds texture parameters for an auto-generated target - texture and depthBuffer/stencilBuffer booleans. - - For an explanation of the texture parameters see [page:Texture Texture]. The following are - valid options:

- - [page:Constant wrapS] - default is [page:Textures ClampToEdgeWrapping].
- [page:Constant wrapT] - default is [page:Textures ClampToEdgeWrapping].
- [page:Constant magFilter] - default is [page:Textures .LinearFilter].
- [page:Constant minFilter] - default is [page:Textures LinearFilter].
- [page:Constant format] - default is [page:Textures RGBAFormat].
- [page:Constant type] - default is [page:Textures UnsignedByteType].
- [page:Number anisotropy] - default is *1*. See [page:Texture.anistropy]
- [page:Constant encoding] - default is [page:Textures LinearEncoding].
- [page:Boolean depthBuffer] - default is *true*. Set this to false if you don't need it.
- [page:Boolean stencilBuffer] - default is *true*. Set this to false if you don't need it.

- - Creates a new [name]] -
- -

Properties

- -

[property:number uuid]

-
- A unique number for this render target instance. -
- -

[property:number width]

-
- The width of the render target. -
- -

[property:number height]

-
- The height of the render target. -
- -

[property:Vector4 scissor]

-
- A rectangular area inside the render target's viewport. Fragments that are outside the area will be discarded. -
- -

[property:boolean scissorTest]

-
- Indicates whether the scissor test is active or not. -
- -

[property:Vector4 viewport]

-
- The viewport of this render target. -
- -

[property:Texture texture]

-
- This texture instance holds the rendered pixels. Use it as input for further processing. -
- -

[property:boolean depthBuffer]

-
- Renders to the depth buffer. Default is true. -
- -

[property:boolean stencilBuffer]

-
- Renders to the stencil buffer. Default is true. -
- -

[property:DepthTexture depthTexture]

-
- If set, the scene depth will be rendered to this texture. Default is null. -
- - -

Methods

- -

[method:null setSize]( [page:Number width], [page:Number height] )

-
- Sets the size of the render target. -
- -

[method:WebGLRenderTarget clone]()

-
- Creates a copy of this render target. -
- -

[method:WebGLRenderTarget copy]( [page:WebGLRenderTarget source] )

-
- Adopts the settings of the given render target. -
- -

[method:null dispose]()

-
- Dispatches a dispose event. -
- - - - - -

[page:EventDispatcher EventDispatcher] methods are available on this class.

- -

Source

- - [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] - - + + + + + + +

[name]

+ +
+ A [link:https://msdn.microsoft.com/en-us/library/bb976073.aspx render target] is a buffer + where the video card draws pixels for a scene that is being rendered in the background. + It is used in different effects, such as applying postprocessing to a rendered image + before displaying it on the screen. +
+ + +

Constructor

+ + +

[name]([page:Number width], [page:Number height], [page:Object options])

+ +
+ [page:Float width] - The width of the renderTarget.
+ [page:Float height] - The height of the renderTarget.
+ options - (optional object that holds texture parameters for an auto-generated target + texture and depthBuffer/stencilBuffer booleans. + + For an explanation of the texture parameters see [page:Texture Texture]. The following are + valid options:

+ + [page:Constant wrapS] - default is [page:Textures ClampToEdgeWrapping].
+ [page:Constant wrapT] - default is [page:Textures ClampToEdgeWrapping].
+ [page:Constant magFilter] - default is [page:Textures .LinearFilter].
+ [page:Constant minFilter] - default is [page:Textures LinearFilter].
+ [page:Constant format] - default is [page:Textures RGBAFormat].
+ [page:Constant type] - default is [page:Textures UnsignedByteType].
+ [page:Number anisotropy] - default is *1*. See [page:Texture.anistropy]
+ [page:Constant encoding] - default is [page:Textures LinearEncoding].
+ [page:Boolean depthBuffer] - default is *true*. Set this to false if you don't need it.
+ [page:Boolean stencilBuffer] - default is *true*. Set this to false if you don't need it.

+ + Creates a new [name] +
+ +

Properties

+ +

[property:number uuid]

+
+ A unique number for this render target instance. +
+ +

[property:number width]

+
+ The width of the render target. +
+ +

[property:number height]

+
+ The height of the render target. +
+ +

[property:Vector4 scissor]

+
+ A rectangular area inside the render target's viewport. Fragments that are outside the area will be discarded. +
+ +

[property:boolean scissorTest]

+
+ Indicates whether the scissor test is active or not. +
+ +

[property:Vector4 viewport]

+
+ The viewport of this render target. +
+ +

[property:Texture texture]

+
+ This texture instance holds the rendered pixels. Use it as input for further processing. +
+ +

[property:boolean depthBuffer]

+
+ Renders to the depth buffer. Default is true. +
+ +

[property:boolean stencilBuffer]

+
+ Renders to the stencil buffer. Default is true. +
+ +

[property:DepthTexture depthTexture]

+
+ If set, the scene depth will be rendered to this texture. Default is null. +
+ + +

Methods

+ +

[method:null setSize]( [page:Number width], [page:Number height] )

+
+ Sets the size of the render target. +
+ +

[method:WebGLRenderTarget clone]()

+
+ Creates a copy of this render target. +
+ +

[method:WebGLRenderTarget copy]( [page:WebGLRenderTarget source] )

+
+ Adopts the settings of the given render target. +
+ +

[method:null dispose]()

+
+ Dispatches a dispose event. +
+ + + + + +

[page:EventDispatcher EventDispatcher] methods are available on this class.

+ +

Source

+ + [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] + + diff --git a/docs/api/renderers/WebGLRenderer.html b/docs/api/renderers/WebGLRenderer.html index 9e984fd3f684ed..2fcb41e4db2c0a 100644 --- a/docs/api/renderers/WebGLRenderer.html +++ b/docs/api/renderers/WebGLRenderer.html @@ -152,7 +152,7 @@

[property:Object extensions]

various WebGL extensions are supported.
-

[property:Boolean gammaFactor]

+

[property:Float gammaFactor]

Default is *2*.
@@ -212,6 +212,11 @@

[property:Object properties]

Used internally by the renderer to keep track of various sub object properties. +

[property:WebGLRenderLists renderLists]

+
+ Used internally to handle ordering of scene object rendering. +
+

[property:WebGLShadowMap shadowMap]

This contains the reference to the shadow map, if used. @@ -307,7 +312,7 @@

[method:null clearTarget]([page:WebGLRenderTarget renderTarget], [page:boole

[method:null compile]( [page:Scene scene], [page:Camera camera] )

Compiles all materials in the scene with the camera. This is useful to precompile shaders before the first rendering.
- +

[method:null dispose]( )

Dispose of the current rendering context.
@@ -348,6 +353,9 @@

[method:RenderTarget getCurrentRenderTarget]( )

[method:Number getMaxAnisotropy]()

This returns the anisotropy level of the textures.
+

[method:Object getDrawingBufferSize]()

+
Returns an object containing the width and height of the renderer's drawing buffer, in pixels.
+

[method:number getPixelRatio]()

Returns current device pixel ratio used.
@@ -421,12 +429,8 @@

[method:null setScissor]( [page:Integer x], [page:Integer y], [page:Integer

[method:null setScissorTest]( [page:Boolean boolean] )

- Enable or disable the scissor test. When this is enabled, only the pixels within - the defined scissor area will be affected by further renderer actions..

- - NOTE: The point (x, y) is the lower left corner of the area to be set for both of these methods. - The area is defined from left to right in width but bottom to top in height. - The sense of the vertical definition is opposite to the fill direction of an HTML canvas element. + Enable or disable the scissor test. When this is enabled, only the pixels within the defined + scissor area will be affected by further renderer actions.

[method:Boolean supportsVertexTextures]()

diff --git a/docs/api/textures/Texture.html b/docs/api/textures/Texture.html index 38f1139918c2df..0303259f009a80 100644 --- a/docs/api/textures/Texture.html +++ b/docs/api/textures/Texture.html @@ -130,12 +130,41 @@

[property:number type]

[property:Vector2 offset]

How much a single repetition of the texture is offset from the beginning, in each direction U and V. - Typical range is *0.0* to *1.0*. + Typical range is *0.0* to *1.0*. _Note:_ The offset property is a convenience modifier and only affects + the Texture's application to the first set of UVs on a model. If the Texture is used as a map requiring + additional UV sets (e.g. the aoMap or lightMap of most stock materials), those UVs must be manually + assigned to achieve the desired offset.

[property:Vector2 repeat]

- How many times the texture is repeated across the surface, in each direction U and V. + How many times the texture is repeated across the surface, in each direction U and V. If repeat is set + greater than 1 in either direction, the corresponding Wrap parameter should also be set to + [page:Textures THREE.RepeatWrapping] or [page:Textures THREE.MirroredRepeatWrapping] to achieve the desired + tiling effect. _Note:_ The repeat property is a convenience modifier and only affects + the Texture's application to the first set of UVs on a model. If the Texture is used as a map requiring + additional UV sets (e.g. the aoMap or lightMap of most stock materials), those UVs must be manually + assigned to achieve the desired repetiton. +
+ +

[property:number rotation]

+
+ How much the texture is rotated around the center point ( 0.5, 0.5 ), in radians. Postive values are counter-clockwise. Default is *0*. +
+ +

[property:boolean matrixAutoUpdate]

+
+ Whether to update the texture's uv-transform [property:Matrix3 matrix] based on the [property:Vector2 offset], + [property:Vector2 repeat], and [property:number rotation] settings. True by default. + Set this to false if you are specifying the uv-transform matrix directly. +
+ +

[property:Matrix3 matrix]

+
+ The uv-transform matrix for the texture. Updated by the renderer from the texture properties [property:Vector2 offset], [property:Vector2 repeat], + and [property:number rotation] when the texture's [property:boolean matrixAutoUpdate] property is true. + When [property:boolean matrixAutoUpdate] property is false, this matrix may be set manually. + Default is the indentity matrix.

[property:boolean generateMipmaps]

diff --git a/docs/examples/controls/OrbitControls.html b/docs/examples/controls/OrbitControls.html new file mode 100644 index 00000000000000..7e7032f3d105a4 --- /dev/null +++ b/docs/examples/controls/OrbitControls.html @@ -0,0 +1,274 @@ + + + + + + + + + + +

[name]

+ +
+ Orbit controls allow the camera to orbit around a target.
+ + To use this, as with all files in the /examples directory, you will have to + include the file seperately in your HTML. + +
+ + +

Example

+ +
[example:misc_controls_orbit misc / controls / orbit ]
+ + +var renderer = new THREE.WebGLRenderer(); +renderer.setSize( window.innerWidth, window.innerHeight ); +document.body.appendChild( renderer.domElement ); + +var scene = new THREE.Scene(); + +var camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 10000 ); + +var controls = new THREE.OrbitControls( camera ); + +//controls.update() must be called after any manual changes to the camera's transform +camera.position.set( 0, 20, 100 ); +controls.update(); + +function animate() { + + requestAnimationFrame( animate ); + + // required if controls.enableDamping or controls.autoRotate are set to true + controls.update(); + + renderer.render( scene, camera ); + +} + + +

Constructor

+ +

[name]( [page:Camera object], [page:HTMLDOMElement domElement] )

+
+ [page:Camera object]: (required) The camera to be controlled.

+ + [page:HTMLDOMElement domElement]: (optional) The HTML element used for event listeners. By default this is the whole document, + however if you only want to the controls to work over a specific element (e.g. the canvas) you can specify that here. +
+ + +

Properties

+ +

[property:Boolean autoRotate]

+
+ Set to true to automatically rotate around the target.
Note that if this is enabled, you must call [page:.update] + () in your animation loop. +
+ +

[property:Float autoRotateSpeed]

+
+ How fast to rotate around the target if [property:Boolean autoRotate] is true. Default is 2.0, which equates to 30 seconds + per rotation at 60fps.
Note that if [property:Boolean autoRotate] is enabled, you must call [page:.update] + () in your animation loop. +
+ +

+ [property:Float dampingFactor]

+
+ The damping inertia used if [property:Boolean enableDamping] is set to true.
Note that for this to work, you must + call [page:.update] () in your animation loop. +
+ +

[property:HTMLDOMElement domElement]

+
+ The HTMLDOMElement used to listen for mouse / touch events. This must be passed in the constructor; changing it here will + not set up new event listeners. Default is the whole document. +
+ +

[property:Boolean enabled]

+
+ Whether or not the controls are enabled. +
+ +

[property:Boolean enableDamping]

+
+ Set to true to enable damping (inertia), which can be used to give a sense of weight to the controls. Default is false.
Note that if this is enabled, you must call [page:.update] () in your animation loop. +
+ +

[property:Boolean enableKeys]

+
+ Enable or disable the use of keyboard controls. +
+ +

[property:Boolean enablePan]

+
+ Enable or disable camera panning. Default is true. +
+ +

[property:Boolean enableRotate]

+
+ Enable or disable horizontal and vertical rotation of the camera. Default is true.
+ Note that it is possible to disable a single axis by setting the min and max of the + [page:.minPolarAngle polar angle] or [page:.minAzimuthAngle azimuth angle] to the same value, + which will cause the vertical or horizontal rotation to be fixed at that value. +
+ +

[property:Boolean enableZoom]

+
+ Enable or disable zooming (dollying) of the camera. +
+ +

[property:Float keyPanSpeed]

+
+ How fast to pan the camera when the keyboard is used. Default is 7.0 pixels per keypress. +
+ +

[property:Object keys]

+
+ This object contains references to the keycodes for controlling camera panning. Default is the 4 arrow keys. + +controls.keys = { + LEFT: 37, //left arrow + UP: 38, // up arrow + RIGHT: 39, // right arrow + BOTTOM: 40 // down arrow +} + See [link:https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode this page] for a full + list of keycodes. +
+ +

[property:Float maxAzimuthAngle]

+
+ How far you can orbit horizontally, upper limit. Range is - Math.PI to Math.PI ( or Infinity for no limit ) and default is + Infinity; +
+ +

[property:Float maxDistance]

+
+ How far you can dolly out ( [page:PerspectiveCamera] only ). Default is Infinity. +
+ +

[property:Float maxPolarAngle]

+
+ How far you can orbit vertically, upper limit. Range is 0 to Math.PI radians, and default is Math.PI. +
+ +

[property:Float maxZoom]

+
+ How far you can zoom out ( [page:OrthographicCamera] only ). Default is Infinity. +
+ +

[property:Float minAzimuthAngle]

+
+ How far you can orbit horizontally, lower limit. Range is - Math.PI to Math.PI ( or - Infinity for no limit ) and default + is - Infinity; +
+ +

[property:Float minDistance]

+
+ How far you can dolly in ( [page:PerspectiveCamera] only ). Default is 0. +
+ +

[property:Float minPolarAngle]

+
+ How far you can orbit vertically, lower limit. Range is 0 to Math.PI radians, and default is 0. +
+ +

[property:Float minZoom]

+
+ How far you can zoom in ( [page:OrthographicCamera] only ). Default is 0. +
+ +

+ [property:Object mouseButtons]

+
+ This object contains references to the mouse buttons used for the controls. + +controls.mouseButtons = { + ORBIT: THREE.MOUSE.LEFT, + ZOOM: THREE.MOUSE.MIDDLE, + PAN: THREE.MOUSE.RIGHT +} + +
+ +

[property:Camera object]

+
+ The camera ( or other object ) that is being controlled. +
+ +

[property:Vector3 position0]

+
+ Used internally by the [method:saveState] and [method:reset] methods. +
+ +

[property:Float rotateSpeed]

+
+ Speed of rotation. Default is 1. +
+ +

[property:Vector3 target0]

+
+ Used internally by the [method:saveState] and [method:reset] methods. +
+ +

[property:Vector3 target]

+
+ The focus point of the controls, the [page:.object] orbits around this. It can be updated manually at any point to change + the focus of the controls. +
+ +

[property:Float zoom0]

+
+ Used internally by the [method:saveState] and [method:reset] methods. +
+ +

[property:Float zoomSpeed]

+
+ Speed of zooming / dollying. Default is 1. +
+ + + +

Methods

+ +

[method:null dispose] ()

+
+ Remove all the event listeners. +
+ +

[method:radians getAzimuthalAngle] ()

+
+ Get the current horizontal rotation, in radians. +
+ +

[method:radians getPolarAngle] ()

+
+ Get the current vertical rotation, in radians. +
+ +

[method:null reset] ()

+
+ Reset the controls to their state from either the last time the [page:.saveState] was called, or the initial state. +
+ +

[method:null saveState] ()

+
+ Save the current state of the controls. This can later be recovered with [page:.reset]. +
+ +

[method:false update] ()

+
+ Update the controls. Must be called after any manual changes to the camera's transform, + or in the update loop if [page:.autoRotate] or [page:.enableDamping] are set. +
+ +

Source

+ + [link:https://github.com/mrdoob/three.js/blob/master/examples/js/[path].js examples/js/[path].js] + + diff --git a/docs/examples/exporters/GLTFExporter.html b/docs/examples/exporters/GLTFExporter.html new file mode 100644 index 00000000000000..00958bc47f6807 --- /dev/null +++ b/docs/examples/exporters/GLTFExporter.html @@ -0,0 +1,91 @@ + + + + + + + + + + +

[name]

+ +
+ An exporter for *glTF* 2.0. +

+ glTF (GL Transmission Format) is an + open format specification + for efficient delivery and loading of 3D content. Assets may be provided either in JSON (.gltf) + or binary (.glb) format. External files store textures (.jpg, .png, ...) and additional binary + data (.bin). A glTF asset may deliver one or more scenes, including meshes, materials, + textures, skins, skeletons, morph targets, animations, lights, and/or cameras. +
+ +

Example

+ + + // Instantiate a exporter + var exporter = new THREE.GLTFExporter( defaultOptions ); + + // Parse the input and generate the glTF output + exporter.parse( scene, function ( gltf ) { + console.log( gltf ); + downloadJSON( gltf ); + }, options ); + + + [example:misc_exporter_gltf] + +

Constructor

+ +

[name]( )

+
+
+
+ Creates a new [name]. +
+ +

Methods

+ +

[method:null parse]( [page:Object input], [page:Function onCompleted], [page:Object options] )

+
+ [page:Object input] — Scenes or objects to export. Valid options:
+
    +
  • + Export scenes + + exporter.parse( scene1, ...) +exporter.parse( [ scene1, scene2 ], ...) + +
  • +
  • + Export objects (It will create a new Scene to hold all the objects) + + exporter.parse( object1, ...) +exporter.parse( [ object1, object2 ], ...) + +
  • +
  • + Mix scenes and objects (It will export the scenes as usual but it will create a new scene to hold all the single objects). + +exporter.parse( [ scene1, object1, object2, scene2 ], ...) + +
+ + [page:Function onCompleted] — Will be called when the export completes. The argument will be the generated glTF JSON.
+ [page:Options options] - Export options
+
    +
  • trs - bool. Export position, rotation and scale instead of matrix per node. Default is false
  • +
  • onlyVisible - bool. Export only visible objects. Default is true.
  • +
  • truncateDrawRange - bool. Export just the attributes within the drawRange, if defined, instead of exporting the whole array. Default is true.
  • +
+
+
+ Generates a glTF output (JSON) with from the input (Scene or Objects) +
+ +

Source

+ + [link:https://github.com/mrdoob/three.js/blob/master/examples/js/exporters/GLTFExporter.js examples/js/exporters/GLTFExporter.js] + + diff --git a/docs/examples/geometries/ConvexBufferGeometry.html b/docs/examples/geometries/ConvexBufferGeometry.html index 77b255b719d7e7..d78f1b2b4c4412 100644 --- a/docs/examples/geometries/ConvexBufferGeometry.html +++ b/docs/examples/geometries/ConvexBufferGeometry.html @@ -34,6 +34,8 @@

[name]

Example

+
[example:webgl_geometry_convex geometry / convex ]
+ var geometry = new THREE.ConvexBufferGeometry( points ); var material = new THREE.MeshBasicMaterial( {color: 0x00ff00} ); var mesh = new THREE.Mesh( geometry, material ); diff --git a/docs/examples/geometries/ConvexGeometry.html b/docs/examples/geometries/ConvexGeometry.html index 667136acb44318..31db226d56b36b 100644 --- a/docs/examples/geometries/ConvexGeometry.html +++ b/docs/examples/geometries/ConvexGeometry.html @@ -33,6 +33,8 @@

[name]

Example

+
[example:webgl_geometry_convex geometry / convex ]
+ var geometry = new THREE.ConvexGeometry( points ); var material = new THREE.MeshBasicMaterial( {color: 0x00ff00} ); var mesh = new THREE.Mesh( geometry, material ); diff --git a/docs/examples/geometries/DecalGeometry.html b/docs/examples/geometries/DecalGeometry.html new file mode 100644 index 00000000000000..2155d0b63aa4dc --- /dev/null +++ b/docs/examples/geometries/DecalGeometry.html @@ -0,0 +1,57 @@ + + + + + + + + + + + [page:BufferGeometry] → + +

[name]

+ +
[name] can be used to create a decal mesh that serves different kinds of purposes e.g. adding unique details to models, performing dynamic visual environmental changes or covering seams.
+ + + +

Example

+ +
[example:webgl_decals decals ]
+ + var geometry = new THREE.DecalGeometry( mesh, position, orientation, size ); + var material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } ); + var mesh = new THREE.Mesh( geometry, material ); + scene.add( mesh ); + + +

Constructor

+ +

[name]( [page:Mesh mesh], [page:Vector3 position], [page:Euler orientation], [page:Vector3 size] )

+
+ mesh — Any mesh object.
+ position — Position of the decal projector.
+ orientation — Orientation of the decal projector.
+ size — Size of the decal projector. +
+ +

Source

+ + [link:https://github.com/mrdoob/three.js/blob/master/examples/js/geometries/DecalGeometry.js examples/js/geometries/DecalGeometry.js] + + diff --git a/docs/examples/loaders/ColladaLoader.html b/docs/examples/loaders/ColladaLoader.html index 41d2f570920093..10d075a7f68b58 100644 --- a/docs/examples/loaders/ColladaLoader.html +++ b/docs/examples/loaders/ColladaLoader.html @@ -34,7 +34,6 @@

Example

[example:webgl_loader_collada]
- [example:webgl_loader_collada_keyframe]
[example:webgl_loader_collada_skinning]
[example:webgl_loader_collada_kinematics] @@ -86,15 +85,6 @@

[method:Object parse]( [page:Document doc], [page:Function callBack], [page: Parse an XML Document and return an [page:Object object] that contain loaded parts: .[page:Scene scene], .[page:Array morphs], .[page:Array skins], .[page:Array animations], .[page:Object dae]

-

[method:null setPreferredShading]( [page:Integer shading] )

-
- [page:Integer shading] — required -
-
- Set the .[page:Integer shading] property on the resource's materials.
- Options are [page:Materials THREE.SmoothShading], [page:Materials THREE.FlatShading]. -
-

[method:null applySkin]( [page:Geometry geometry], [page:Object instanceCtrl], [page:Integer frame] )

[page:Geometry geometry] — required
diff --git a/docs/examples/loaders/GLTF2Loader.html b/docs/examples/loaders/GLTFLoader.html similarity index 77% rename from docs/examples/loaders/GLTF2Loader.html rename to docs/examples/loaders/GLTFLoader.html index 6ccb728e3488ec..9629881573f0b9 100644 --- a/docs/examples/loaders/GLTF2Loader.html +++ b/docs/examples/loaders/GLTFLoader.html @@ -14,36 +14,34 @@

[name]

A loader for *glTF* 2.0 resources.

- glTF (GL Transmission Format) is an open format - specification for efficient delivery and loading of 3D content. Assets may be provided either - in JSON (.gltf) or binary (.glb) format. External files store textures (.jpg, .png, ...) and - additional binary data (.bin). A glTF asset may deliver one or more scenes, including meshes, - materials, textures, shaders, skins, skeletons, animations, lights, and/or cameras. Morph target - animations are not yet finalized in the - glTF specification. + glTF (GL Transmission Format) is an + open format specification + for efficient delivery and loading of 3D content. Assets may be provided either in JSON (.gltf) + or binary (.glb) format. External files store textures (.jpg, .png, ...) and additional binary + data (.bin). A glTF asset may deliver one or more scenes, including meshes, materials, + textures, skins, skeletons, morph targets, animations, lights, and/or cameras.

Extensions

- GLTF2Loader supports the following glTF extensions: + GLTFLoader supports the following glTF extensions:
@@ -51,7 +49,7 @@

Example

// Instantiate a loader - var loader = new THREE.GLTF2Loader(); + var loader = new THREE.GLTFLoader(); // Load a glTF resource loader.load( 'models/gltf/duck/duck.gltf', function ( gltf ) { @@ -64,7 +62,7 @@

Example

} );
- [example:webgl_loader_gltf2] + [example:webgl_loader_gltf]

Constructor

@@ -94,7 +92,7 @@

[method:null load]( [page:String url], [page:Function onLoad], [page:Functio

[method:null setPath]( [page:String path] )

- [page:String path] — Base path for loading additional resources e.g. textures, GLSL shaders, .bin data. + [page:String path] — Base path for loading additional resources e.g. textures and .bin data.
Set the base path for additional resources. @@ -109,7 +107,7 @@

[method:null parse]( [page:Object json], [page:Function callBack], [page:Str
[page:Object json] — JSON object to parse.
[page:Function callBack] — Will be called when parse completes.
- [page:String path] — The base path from which to find subsequent glTF resources such as textures, GLSL shaders and .bin data files.
+ [page:String path] — The base path from which to find subsequent glTF resources such as textures and .bin data files.
Parse a glTF-based JSON structure and fire [page:Function callback] when complete. The argument to [page:Function callback] will be an [page:object] that contains loaded parts: .[page:Scene scene], .[page:Array scenes], .[page:Array cameras], and .[page:Array animations]. @@ -117,6 +115,6 @@

[method:null parse]( [page:Object json], [page:Function callBack], [page:Str

Source

- [link:https://github.com/mrdoob/three.js/blob/master/examples/js/loaders/GLTF2Loader.js examples/js/loaders/GLTF2Loader.js] + [link:https://github.com/mrdoob/three.js/blob/master/examples/js/loaders/GLTFLoader.js examples/js/loaders/GLTFLoader.js] diff --git a/docs/examples/loaders/PDBLoader.html b/docs/examples/loaders/PDBLoader.html index ebbd26f0c471dd..e9d81ba3534139 100644 --- a/docs/examples/loaders/PDBLoader.html +++ b/docs/examples/loaders/PDBLoader.html @@ -28,7 +28,12 @@

Example

// resource URL 'models/molecules/caffeine.pdb', // Function when resource is loaded - function ( geometryAtoms, geometryBonds, json ) { + function ( pdb ) { + + var geometryAtoms = pdb.geometryAtoms; + var geometryBonds = pdb.geometryBonds; + var json = pdb.json; + console.log( 'This molecule has ' + json.atoms.length + ' atoms' ); }, // Function called when download progresses @@ -71,7 +76,7 @@

[method:null load]( [page:String url], [page:Function onLoad], [page:Functio Begin loading from url and call onLoad with the parsed response content.

-

[method:Object parsePDB]( [page:String text] )

+

[method:Object parse]( [page:String text] )

[page:String text] — The textual pdb structure to parse.
@@ -79,16 +84,6 @@

[method:Object parsePDB]( [page:String text] )

Parse a pdb text and return a JSON structure.
-

[method:null createModel]( [page:Object json], [page:Function callback] )

-
- [page:Object json] — The (JSON) pdb structure to parse.
- [page:Function callback] — Will be called when parse completes, with three arguments: [page:BufferGeometry geometryAtoms], [page:BufferGeometry geometryBonds] and the original [page:Object json].
-
-
- Parse a (JSON) pdb structure and return two [page:BufferGeometry]: one for atoms, one for bonds.
-
- -

Source

[link:https://github.com/mrdoob/three.js/blob/master/examples/js/loaders/PDBLoader.js examples/js/loaders/PDBLoader.js] diff --git a/docs/index.html b/docs/index.html index a476ebb0fb2aa1..9eaa1e7a3284d5 100644 --- a/docs/index.html +++ b/docs/index.html @@ -26,7 +26,7 @@

three.js / docs

- + @@ -44,11 +44,6 @@

three.js / docs

var categoryElements = []; -// ---------------------------------------------------------------------------- -// Initialization -// ---------------------------------------------------------------------------- - - // Functionality for hamburger button (on small devices) expandButton.onclick = function ( event ) { @@ -79,28 +74,40 @@

three.js / docs

}; - // Activate content and title change on browser navigation window.onpopstate = createNewIframe; - // Create the navigation panel and configure the iframe createNavigation(); createNewIframe(); + // Navigation Panel + + function createLink( pageName, pageURL ) { + + var link = document.createElement( 'a' ); + link.href = pageURL + '.html'; + link.textContent = pageName; + link.setAttribute( 'target', 'viewer' ); + link.addEventListener( 'click', function ( event ) { -// ---------------------------------------------------------------------------- -// Navigation Panel -// ---------------------------------------------------------------------------- + window.location.hash = pageURL; + panel.classList.add( 'collapsed' ); + + } ); + + return link; + } - function createNavigation () { + function createNavigation() { // Create the navigation panel using data from list.js - var navigation = createAndAppendDOMElement( { type: 'div', parent: content } ); + var navigation = document.createElement( 'div' ); + content.appendChild( navigation ); for ( var section in list ) { @@ -108,7 +115,9 @@

three.js / docs

var categories = list[ section ]; - var sectionHead = createAndAppendDOMElement( { type: 'h2', parent: navigation, content: section } ) + var sectionHead = document.createElement( 'h2' ); + sectionHead.textContent = section; + navigation.appendChild( sectionHead ); for ( var category in categories ) { @@ -116,9 +125,15 @@

three.js / docs

var pages = categories[ category ]; - var categoryContainer = createAndAppendDOMElement( { type: 'div', parent: navigation } ); - var categoryHead = createAndAppendDOMElement( { type: 'h3', parent: categoryContainer, content: category } ); - var categoryContent = createAndAppendDOMElement( { type: 'ul', parent: categoryContainer } ); + var categoryContainer = document.createElement( 'div' ); + navigation.appendChild( categoryContainer ); + + var categoryHead = document.createElement( 'h3' ); + categoryHead.textContent = category; + categoryContainer.appendChild( categoryHead ); + + var categoryContent = document.createElement( 'ul' ); + categoryContainer.appendChild( categoryContent ); for ( var pageName in pages ) { @@ -126,14 +141,11 @@

three.js / docs

var pageURL = pages[ pageName ]; - var listElement = createAndAppendDOMElement( { type: 'li', parent: categoryContent } ); - var linkElement = createAndAppendDOMElement( { type: 'a', parent: listElement, content: pageName } ); - - // The href attribute is only used for the option to create a new tab by right click + var listElement = document.createElement( 'li' ); + categoryContent.appendChild( listElement ); - linkElement.setAttribute( 'href', '#' + pageURL ); - - addClickHandlers( linkElement, pageURL ); + var linkElement = createLink( pageName, pageURL ) + listElement.appendChild( linkElement ); // Gather the main properties for the current subpage @@ -158,92 +170,15 @@

three.js / docs

} - }; - - - function createAndAppendDOMElement( properties ) { - - // Helper function for creating and appending new DOM elements - - var newElement = document.createElement( properties.type ); - - properties.parent.appendChild( newElement ); - - if ( properties.content ) { - - newElement.textContent = properties.content; - - } - - return newElement; - } - function addClickHandlers ( linkElement, pageURL ) { - - // Helper function for adding ClickHandlers to the page links - - linkElement.onclick = function ( event ) { - - event.preventDefault(); - - window.location.hash = pageURL; - createNewIframe(); - - panel.classList.add( 'collapsed' ); - - }; - - }; - - -// ---------------------------------------------------------------------------- -// Query Strings (optional) -// ---------------------------------------------------------------------------- - - -// (uncomment the following lines and the first line in updateFilter(), if you want query strings): - -// filterInput.value = extractFromQueryString(); -// updateFilter(); -// -// -// function extractFromQueryString() { -// -// var queryString = window.location.search; -// -// if ( queryString.indexOf( '?q=' ) === -1 ) return ''; -// -// return queryString.substr( 3 ); -// -// } -// -// function updateQueryString() { -// -// var searchString = filterInput.value; -// var query = ''; -// -// if (searchString !== '') { -// -// query = '?q=' + searchString; -// -// } -// -// window.history.replaceState( {} , '', window.location.pathname + query + window.location.hash ); -// -// } - - -// ---------------------------------------------------------------------------- -// Filtering -// ---------------------------------------------------------------------------- - + // Filtering function updateFilter() { -// (uncomment the following line and the "Query strings" section, if you want query strings): -// updateQueryString(); + // (uncomment the following line and the "Query strings" section, if you want query strings): + // updateQueryString(); var regExp = new RegExp( filterInput.value, 'gi' ); @@ -284,7 +219,6 @@

three.js / docs

} - function displayFilteredPanel() { // Show/hide categories depending on their content @@ -327,10 +261,7 @@

three.js / docs

} -// ---------------------------------------------------------------------------- -// Routing -// ---------------------------------------------------------------------------- - + // Routing function setUrlFragment( pageName ) { @@ -352,7 +283,6 @@

three.js / docs

} - function createNewIframe() { // Change the content displayed in the iframe @@ -391,11 +321,10 @@

three.js / docs

} - - function decomposePageName ( pageName, oldDelimiter, newDelimiter ) { + function decomposePageName( pageName, oldDelimiter, newDelimiter ) { // Helper function for separating the member (if existing) from the pageName - // For example: 'Geometry.morphTarget' can be converted to + // For example: 'Geometry.morphTarget' can be converted to // ['Geometry', '.morphTarget'] or ['Geometry', '#morphTarget'] // Note: According RFC 3986 no '#' allowed inside of an URL fragment! @@ -419,11 +348,7 @@

three.js / docs

} - -// ---------------------------------------------------------------------------- -// ASCII Art ;-) -// ---------------------------------------------------------------------------- - + // console.log([ ' __ __', diff --git a/docs/list.js b/docs/list.js index 355995d4f6d591..3483b4392bc8ef 100644 --- a/docs/list.js +++ b/docs/list.js @@ -4,6 +4,7 @@ var list = { "Getting Started": { "Creating a scene": "manual/introduction/Creating-a-scene", + "Import via modules": "manual/introduction/Import-via-modules", "WebGL compatibility check": "manual/introduction/WebGL-compatibility-check", "How to run things locally": "manual/introduction/How-to-run-thing-locally", "Drawing Lines": "manual/introduction/Drawing-lines", @@ -102,7 +103,6 @@ var list = { }, "Extras": { - "CurveUtils": "api/extras/CurveUtils", "SceneUtils": "api/extras/SceneUtils", "ShapeUtils": "api/extras/ShapeUtils" }, @@ -111,6 +111,7 @@ var list = { "Curve": "api/extras/core/Curve", "CurvePath": "api/extras/core/CurvePath", "Font": "api/extras/core/Font", + "Interpolations": "api/extras/core/Interpolations", "Path": "api/extras/core/Path", "Shape": "api/extras/core/Shape", "ShapePath": "api/extras/core/ShapePath" @@ -131,7 +132,6 @@ var list = { "Extras / Objects": { "ImmediateRenderObject": "api/extras/objects/ImmediateRenderObject", - "MorphBlendMesh": "api/extras/objects/MorphBlendMesh" }, "Geometries": { @@ -168,6 +168,7 @@ var list = { "SphereGeometry": "api/geometries/SphereGeometry", "TetrahedronBufferGeometry": "api/geometries/TetrahedronBufferGeometry", "TetrahedronGeometry": "api/geometries/TetrahedronGeometry", + "TextBufferGeometry": "api/geometries/TextBufferGeometry", "TextGeometry": "api/geometries/TextGeometry", "TorusBufferGeometry": "api/geometries/TorusBufferGeometry", "TorusGeometry": "api/geometries/TorusGeometry", @@ -332,15 +333,20 @@ var list = { "Examples": { + "Controls": { + "OrbitControls": "examples/controls/OrbitControls" + }, + "Geometries": { "ConvexBufferGeometry": "examples/geometries/ConvexBufferGeometry", - "ConvexGeometry": "examples/geometries/ConvexGeometry" + "ConvexGeometry": "examples/geometries/ConvexGeometry", + "DecalGeometry": "examples/geometries/DecalGeometry" }, "Loaders": { "BabylonLoader": "examples/loaders/BabylonLoader", "ColladaLoader": "examples/loaders/ColladaLoader", - "GLTF2Loader": "examples/loaders/GLTF2Loader", + "GLTFLoader": "examples/loaders/GLTFLoader", "MTLLoader": "examples/loaders/MTLLoader", "OBJLoader": "examples/loaders/OBJLoader", "OBJLoader2": "examples/loaders/OBJLoader2", @@ -351,6 +357,10 @@ var list = { "TGALoader": "examples/loaders/TGALoader" }, + "Exporters": { + "GLTFExporter": "examples/exporters/GLTFExporter" + }, + "Plugins": { "CombinedCamera": "examples/cameras/CombinedCamera", "LookupTable": "examples/Lut", @@ -390,4 +400,4 @@ var list = { } -} +}; diff --git a/docs/manual/buildTools/Testing-with-NPM.html b/docs/manual/buildTools/Testing-with-NPM.html index ac447117394036..88b85685ef1f2a 100644 --- a/docs/manual/buildTools/Testing-with-NPM.html +++ b/docs/manual/buildTools/Testing-with-NPM.html @@ -106,7 +106,7 @@

Add mocha

  • Rerun the test with - $ npm test. + $ npm test This should now succeed, reporting 0 passing (1ms) @@ -144,7 +144,7 @@

    Add three.js

  • Mocha will look for tests in test/, so let's - $ mkdir test. + $ mkdir test
  • diff --git a/docs/manual/introduction/Animation-system.html b/docs/manual/introduction/Animation-system.html index ee6fa1b1466214..9bc0baabf6bee2 100644 --- a/docs/manual/introduction/Animation-system.html +++ b/docs/manual/introduction/Animation-system.html @@ -111,7 +111,7 @@

    Supported Formats and Loaders

  • [page:ObjectLoader THREE.ObjectLoader]
  • THREE.BVHLoader
  • THREE.FBXLoader
  • -
  • [page:GLTF2Loader THREE.GLTF2Loader]
  • +
  • [page:GLTFLoader THREE.GLTFLoader]
  • THREE.MMDLoader
  • THREE.SEA3DLoader
  • diff --git a/docs/manual/introduction/Creating-a-scene.html b/docs/manual/introduction/Creating-a-scene.html index 92884f66b0c790..f76faec4c89181 100644 --- a/docs/manual/introduction/Creating-a-scene.html +++ b/docs/manual/introduction/Creating-a-scene.html @@ -86,14 +86,14 @@

    Creating the scene

    Rendering the scene

    -
    If you copied the code from above into the HTML file we created earlier, you wouldn't be able to see anything. This is because we're not actually rendering anything yet. For that, we need what's called a render loop.
    +
    If you copied the code from above into the HTML file we created earlier, you wouldn't be able to see anything. This is because we're not actually rendering anything yet. For that, we need what's called a render or animate loop.
    - function render() { - requestAnimationFrame( render ); + function animate() { + requestAnimationFrame( animate ); renderer.render( scene, camera ); } - render(); + animate();
    This will create a loop that causes the renderer to draw the scene 60 times per second. If you're new to writing games in the browser, you might say "why don't we just create a setInterval? The thing is - we could, but requestAnimationFrame has a number of advantages. Perhaps the most important one is that it pauses when the user navigates to another browser tab, hence not wasting their precious processing power and battery life.
    @@ -102,14 +102,14 @@

    Animating the cube

    If you insert all the code above into the file you created before we began, you should see a green box. Let's make it all a little more interesting by rotating it.
    -
    Add the following right above the renderer.render call in your render function:
    +
    Add the following right above the renderer.render call in your animate function:
    cube.rotation.x += 0.1; cube.rotation.y += 0.1; -
    This will be run every frame (60 times per second), and give the cube a nice rotation animation. Basically, anything you want to move or change while the app is running has to go through the render loop. You can of course call other functions from there, so that you don't end up with a render function that's hundreds of lines. +
    This will be run every frame (60 times per second), and give the cube a nice rotation animation. Basically, anything you want to move or change while the app is running has to go through the animate loop. You can of course call other functions from there, so that you don't end up with a animate function that's hundreds of lines.

    The result

    @@ -143,8 +143,8 @@

    The result

    camera.position.z = 5; - var render = function () { - requestAnimationFrame( render ); + var animate = function () { + requestAnimationFrame( animate ); cube.rotation.x += 0.1; cube.rotation.y += 0.1; @@ -152,7 +152,7 @@

    The result

    renderer.render(scene, camera); }; - render(); + animate(); </script> </body> </html> diff --git a/docs/manual/introduction/Creating-text.html b/docs/manual/introduction/Creating-text.html index acdf6bb35f62c7..ab32959201524b 100644 --- a/docs/manual/introduction/Creating-text.html +++ b/docs/manual/introduction/Creating-text.html @@ -68,7 +68,7 @@

    4. Procedural Text Geometry

    new THREE.TextGeometry( text, parameters );

    - In order for this to work, however, your TextGeomety will need an instance of THREE.Font + In order for this to work, however, your TextGeometry will need an instance of THREE.Font to be set on its "font" parameter. See the [page:TextGeometry] page for more info on how this can be done, descriptions of each diff --git a/docs/manual/introduction/How-to-run-thing-locally.html b/docs/manual/introduction/How-to-run-thing-locally.html index 166afc4447cd5e..8617043ce8871d 100644 --- a/docs/manual/introduction/How-to-run-thing-locally.html +++ b/docs/manual/introduction/How-to-run-thing-locally.html @@ -40,64 +40,6 @@

    Content loaded from external files

    -

    Change local files security policy

    -
    -

    Safari

    -
    -

    - Enable the develop menu using the preferences panel, under Advanced -> "Show develop menu - in menu bar". -

    - -

    - Then from the safari "Develop" menu, select "Disable local file restrictions", it is also - worth noting safari has some odd behaviour with caches, so it is advisable to use the - "Disable caches" option in the same menu; if you are editing & debugging using safari. -

    -
    - - -

    Chrome

    -
    -

    Close all running Chrome instances first. The important word here is 'all'.

    - -

    - On Windows, you may check for Chrome instances using the Windows Task Manager. - Alternatively, if you see a Chrome icon in the system tray, then you may open its context - menu and click 'Exit'. This should close all Chrome instances. -

    - -

    Then start the Chrome executable with a command line flag:

    - - chrome --allow-file-access-from-files - -

    - On Windows, probably the easiest is probably to create a special shortcut icon which has - added the flag given above (right-click on shortcut -> properties -> target). -

    - -

    On Mac OSX, you can do this with

    - - open /Applications/Google\ Chrome.app --args --allow-file-access-from-files -
    - -

    Firefox

    -
    -
      -
    1. - In the address bar, type about:config -
    2. -
    3. - Find the security.fileuri.strict_origin_policy parameter -
    4. -
    5. - Set it to false -
    6. -
    -
    - -
    -

    Run a local server

    @@ -107,7 +49,16 @@

    Run a local server

    three.js application.

    -

    Running a Python server

    +

    Node.js server

    +
    +

    Node.js has a simple HTTP server package. To install:

    + npm install http-server -g + +

    To run (from your local directory):

    + http-server . -p 8000 +
    + +

    Python server

    If you have [link:http://python.org/ Python] installed, it should be enough to run this @@ -126,7 +77,7 @@

    Running a Python server

    http://localhost:8000/
    -

    Running a Ruby server

    +

    Ruby server

    If you have Ruby installed, you can get the same result running this instead:

    @@ -134,22 +85,13 @@

    Running a Ruby server

    -

    Running a PHP server

    +

    PHP server

    PHP also has a built-in web server, starting with php 5.4.0:

    php -S localhost:8000
    -

    Running a Node.js server

    -
    -

    Node.js has a simple HTTP server package. To install:

    - npm install http-server -g - -

    To run (from your local directory):

    - http-server . -p 8000 -
    - -

    Running lighttpd on Mac

    +

    Lighttpd

    Lighttpd is a very lightweight general purpose webserver. We'll cover installing it on OSX with @@ -180,6 +122,64 @@

    Running lighttpd on Mac

    +

    Change local files security policy

    +
    +

    Safari

    +
    +

    + Enable the develop menu using the preferences panel, under Advanced -> "Show develop menu + in menu bar". +

    + +

    + Then from the safari "Develop" menu, select "Disable local file restrictions", it is also + worth noting safari has some odd behaviour with caches, so it is advisable to use the + "Disable caches" option in the same menu; if you are editing & debugging using safari. +

    +
    + + +

    Chrome

    +
    +

    Close all running Chrome instances first. The important word here is 'all'.

    + +

    + On Windows, you may check for Chrome instances using the Windows Task Manager. + Alternatively, if you see a Chrome icon in the system tray, then you may open its context + menu and click 'Exit'. This should close all Chrome instances. +

    + +

    Then start the Chrome executable with a command line flag:

    + + chrome --allow-file-access-from-files + +

    + On Windows, probably the easiest is probably to create a special shortcut icon which has + added the flag given above (right-click on shortcut -> properties -> target). +

    + +

    On Mac OSX, you can do this with

    + + open /Applications/Google\ Chrome.app --args --allow-file-access-from-files +
    + +

    Firefox

    +
    +
      +
    1. + In the address bar, type about:config +
    2. +
    3. + Find the security.fileuri.strict_origin_policy parameter +
    4. +
    5. + Set it to false +
    6. +
    +
    + +
    +

    Other simple alternatives are [link:http://stackoverflow.com/q/12905426/24874 discussed here] on Stack Overflow. diff --git a/docs/manual/introduction/How-to-update-things.html b/docs/manual/introduction/How-to-update-things.html index 70bac0dad5deea..41712885f0b8f9 100644 --- a/docs/manual/introduction/How-to-update-things.html +++ b/docs/manual/introduction/How-to-update-things.html @@ -118,7 +118,7 @@

    [page:BufferGeometry]

    [link:http://jsfiddle.net/w67tzfhx/ Here is a fiddle] showing an animated line which you can adapt to your use case.

    -

    Examples:

    +

    Examples:

    [example:webgl_custom_attributes WebGL / custom / attributes]
    [example:webgl_buffergeometry_custom_attributes_particles WebGL / buffergeometry / custom / attributes / particles] @@ -155,7 +155,7 @@

    [page:Geometry]

    geometry.dynamic = true;
    -

    Example:

    +

    Examples:

    [example:webgl_geometry_dynamic WebGL / geometry / dynamic]
    diff --git a/docs/manual/introduction/Import-via-modules.html b/docs/manual/introduction/Import-via-modules.html new file mode 100644 index 00000000000000..f0a5fbf29d6a13 --- /dev/null +++ b/docs/manual/introduction/Import-via-modules.html @@ -0,0 +1,72 @@ + + + + + + + + + + +

    [name]


    + +
    + While importing three.js via script tags is a great way to get up and running fast, it has a few drawbacks for longer lived projects, for example: +
      +
    • You have to manually fetch and include a copy of the library as part of your project's source code
    • +
    • Updating the library's version is a manual process
    • +
    • When checking in a new version of the library your version control diffs are cluttered by the many lines of the build file
    • +
    +
    + +
    Using a dependency manager like npm avoids these caveats by allowing you to simply download and import your desired version of the library onto your machine.
    + +

    Installation via npm

    + +
    Three.js is published as an npm module, see: npm. This means all you need to do to include three.js into your project is run "npm install three"
    + +

    Importing the module

    + +
    Assuming that you're bundling your files with a tool such as Webpack or Browserify, which allow you to "require('modules') in the browser by bundling up all of your dependencies."
    + +
    + You should now be able to import the module into your source files and continue to use it as per normal. +
    + + + var THREE = require('three'); + + var scene = new THREE.Scene(); + ... + + +
    + You're also able to leverage ES6 import syntax: +
    + + + import * as THREE from 'three'; + + const scene = new THREE.Scene(); + ... + + +
    + or if you wish to import only select parts of three.js library, for example Scene: +
    + + + import { Scene } from 'three'; + + const scene = new Scene(); + ... + + +

    Caveats

    + +
    + Currently it's not possible to import the files within the "examples/js" directory in this way. + This is due to some of the files relying on global namespace pollution of THREE. For more information see Transform `examples/js` to support modules #9562. +
    + + diff --git a/docs/manual/introduction/Useful-links.html b/docs/manual/introduction/Useful-links.html index 0483b11f62e04c..6c149496693f09 100644 --- a/docs/manual/introduction/Useful-links.html +++ b/docs/manual/introduction/Useful-links.html @@ -31,7 +31,7 @@

    Help forums

    Tutorials and courses

    -

    Getting started with three.js

    +

    Getting started with three.js

    • [link:https://codepen.io/rachsmith/post/beginning-with-3d-webgl-pt-1-the-scene Beginning with 3D WebGL] by [link:https://codepen.io/rachsmith/ Rachel Smith]. @@ -41,13 +41,13 @@

      Getting started with three.js

    -

    More extensive / advanced articles and courses

    +

    More extensive / advanced articles and courses

    • [link:http://blog.cjgammon.com/ Collection of tutorials] by [link:http://www.cjgammon.com/ CJ Gammon].
    • - Glossy spheres in three.js. + [link:https://medium.com/@soffritti.pierfrancesco/glossy-spheres-in-three-js-bfd2785d4857] Glossy spheres in three.js.
    • [link:https://www.udacity.com/course/cs291 Interactive 3D Graphics] - a free course on Udacity that teaches the fundamentals of 3D Graphics, @@ -65,7 +65,7 @@

      More extensive / advanced articles and courses

    -

    Tutorials in other languages

    +

    Tutorials in other languages

    • [link:http://www.natural-science.or.jp/article/20120220155529.php Building A Physics Simulation Environment] - three.js tutorial in Japanese @@ -73,14 +73,6 @@

      Tutorials in other languages

    - -

    More documentation

    -
      -
    • - [link:http://ushiroad.com/3j/ Three.js walking map] - a graphical breakdown of the structure of a three.js scene. -
    • -
    -

    News and Updates

    • diff --git a/docs/manual/introduction/WebGL-compatibility-check.html b/docs/manual/introduction/WebGL-compatibility-check.html index d34330af5e9040..d8d5c1b05f3bb4 100644 --- a/docs/manual/introduction/WebGL-compatibility-check.html +++ b/docs/manual/introduction/WebGL-compatibility-check.html @@ -21,7 +21,7 @@

      [name]


      if (Detector.webgl) { - init(); + // Initiate function or other initializations here animate(); } else { var warning = Detector.getWebGLErrorMessage(); diff --git a/docs/scenes/bones-browser.html b/docs/scenes/bones-browser.html index 0ccb48103862a9..38ef492f886084 100644 --- a/docs/scenes/bones-browser.html +++ b/docs/scenes/bones-browser.html @@ -149,7 +149,7 @@ color: 0x156289, emissive: 0x072534, side: THREE.DoubleSide, - shading: THREE.FlatShading + flatShading: true } ); var mesh = new THREE.SkinnedMesh( geometry, material ); @@ -253,8 +253,6 @@ } - skeletonHelper.update(); - renderer.render( scene, camera ); } diff --git a/docs/scenes/geometry-browser.html b/docs/scenes/geometry-browser.html index 54e59bd4aa74af..24d3fd0a4a6710 100644 --- a/docs/scenes/geometry-browser.html +++ b/docs/scenes/geometry-browser.html @@ -94,7 +94,7 @@ color: 0x156289, emissive: 0x072534, side: THREE.DoubleSide, - shading: THREE.FlatShading + flatShading: true } ) ) ); diff --git a/docs/scenes/js/geometry.js b/docs/scenes/js/geometry.js index 2c650cbf5c9c86..decb05cb78371c 100644 --- a/docs/scenes/js/geometry.js +++ b/docs/scenes/js/geometry.js @@ -22,13 +22,6 @@ var constants = { }, - shading : { - - "THREE.FlatShading" : THREE.FlatShading, - "THREE.SmoothShading" : THREE.SmoothShading - - }, - colors : { "THREE.NoColors" : THREE.NoColors, @@ -984,6 +977,75 @@ var guis = { }, + TextBufferGeometry : function( mesh ) { + + var data = { + text : "TextBufferGeometry", + size : 5, + height : 2, + curveSegments : 12, + font : "helvetiker", + weight : "regular", + bevelEnabled : false, + bevelThickness : 1, + bevelSize : 0.5, + bevelSegments : 3 + }; + + var fonts = [ + "helvetiker", + "optimer", + "gentilis", + "droid/droid_serif" + ]; + + var weights = [ + "regular", "bold" + ]; + + function generateGeometry() { + + var loader = new THREE.FontLoader(); + loader.load( '../../examples/fonts/' + data.font + '_' + data.weight + '.typeface.json', function ( font ) { + + var geometry = new THREE.TextBufferGeometry( data.text, { + font: font, + size: data.size, + height: data.height, + curveSegments: data.curveSegments, + bevelEnabled: data.bevelEnabled, + bevelThickness: data.bevelThickness, + bevelSize: data.bevelSize, + bevelSegments: data.bevelSegments + } ); + geometry.center(); + + updateGroupGeometry( mesh, geometry ); + + } ); + + } + + //Hide the wireframe + mesh.children[ 0 ].visible = false; + + var folder = gui.addFolder( 'THREE.TextBufferGeometry' ); + + folder.add( data, 'text' ).onChange( generateGeometry ); + folder.add( data, 'size', 1, 30 ).onChange( generateGeometry ); + folder.add( data, 'height', 1, 20 ).onChange( generateGeometry ); + folder.add( data, 'curveSegments', 1, 20 ).step( 1 ).onChange( generateGeometry ); + folder.add( data, 'font', fonts ).onChange( generateGeometry ); + folder.add( data, 'weight', weights ).onChange( generateGeometry ); + folder.add( data, 'bevelEnabled' ).onChange( generateGeometry ); + folder.add( data, 'bevelThickness', 0.1, 3 ).onChange( generateGeometry ); + folder.add( data, 'bevelSize', 0.1, 3 ).onChange( generateGeometry ); + folder.add( data, 'bevelSegments', 0, 8 ).step( 1 ).onChange( generateGeometry ); + + generateGeometry(); + + }, + TorusBufferGeometry : function( mesh ) { var data = { @@ -1356,7 +1418,7 @@ function chooseFromHash ( mesh ) { } - if ( selectedGeometry === 'TextGeometry' ) { + if ( selectedGeometry === 'TextGeometry' || selectedGeometry === 'TextBufferGeometry' ) { return { fixed : true }; diff --git a/docs/scenes/js/material.js b/docs/scenes/js/material.js index 4b331842bdc593..4f2d2a09272b18 100644 --- a/docs/scenes/js/material.js +++ b/docs/scenes/js/material.js @@ -20,13 +20,6 @@ var constants = { }, - shading : { - - "THREE.FlatShading" : THREE.FlatShading, - "THREE.SmoothShading" : THREE.SmoothShading - - }, - colors : { "THREE.NoColors" : THREE.NoColors, @@ -202,7 +195,6 @@ function needsUpdate ( material, geometry ) { return function () { - material.shading = +material.shading; //Ensure number material.vertexColors = +material.vertexColors; //Ensure number material.side = +material.side; //Ensure number material.needsUpdate = true; @@ -330,7 +322,6 @@ function guiMeshBasicMaterial ( gui, mesh, material, geometry ) { folder.addColor( data, 'color' ).onChange( handleColorChange( material.color ) ); folder.add( material, 'wireframe' ); folder.add( material, 'wireframeLinewidth', 0, 10 ); - folder.add( material, 'shading', constants.shading); folder.add( material, 'vertexColors', constants.colors).onChange( needsUpdate( material, geometry ) ); folder.add( material, 'fog' ); @@ -360,6 +351,7 @@ function guiMeshNormalMaterial ( gui, mesh, material, geometry ) { var folder = gui.addFolder('THREE.MeshNormalMaterial'); + folder.add( material, 'flatShading' ).onChange( needsUpdate( material, geometry ) ); folder.add( material, 'wireframe' ); folder.add( material, 'wireframeLinewidth', 0, 10 ); folder.add( material, 'morphTargets' ).onChange( updateMorphs( mesh, material ) ); @@ -438,7 +430,7 @@ function guiMeshPhongMaterial ( gui, mesh, material, geometry ) { folder.addColor( data, 'specular' ).onChange( handleColorChange( material.specular ) ); folder.add( material, 'shininess', 0, 100); - folder.add( material, 'shading', constants.shading).onChange( needsUpdate( material, geometry ) ); + folder.add( material, 'flatShading' ).onChange( needsUpdate( material, geometry ) ); folder.add( material, 'wireframe' ); folder.add( material, 'wireframeLinewidth', 0, 10 ); folder.add( material, 'vertexColors', constants.colors); @@ -470,7 +462,7 @@ function guiMeshStandardMaterial ( gui, mesh, material, geometry ) { folder.add( material, 'roughness', 0, 1 ); folder.add( material, 'metalness', 0, 1 ); - folder.add( material, 'shading', constants.shading).onChange( needsUpdate( material, geometry ) ); + folder.add( material, 'flatShading' ).onChange( needsUpdate( material, geometry ) ); folder.add( material, 'wireframe' ); folder.add( material, 'wireframeLinewidth', 0, 10 ); folder.add( material, 'vertexColors', constants.colors); @@ -533,7 +525,7 @@ function chooseFromHash ( gui, mesh, geometry ) { case "MeshDepthMaterial" : - material = new THREE.MeshDepthMaterial({color: 0x2194CE}); + material = new THREE.MeshDepthMaterial(); guiMaterial( gui, mesh, material, geometry ); guiMeshDepthMaterial( gui, mesh, material, geometry ); diff --git a/docs/scenes/material-browser.html b/docs/scenes/material-browser.html index c0bb52c58e48f8..f192817e6c759e 100644 --- a/docs/scenes/material-browser.html +++ b/docs/scenes/material-browser.html @@ -44,7 +44,7 @@ var gui = new dat.GUI(); var scene = new THREE.Scene(); - var camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 50 ); + var camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 10, 50 ); camera.position.z = 30; var renderer = new THREE.WebGLRenderer( { antialias: true } ); diff --git a/editor/css/dark.css b/editor/css/dark.css index 215bd9cee6d955..117390ee5793eb 100644 --- a/editor/css/dark.css +++ b/editor/css/dark.css @@ -110,11 +110,13 @@ select { } #menubar .menu .options { - position: absolute; + position: fixed; display: none; padding: 5px 0; background: #111; width: 150px; + max-height: calc(100% - 80px); + overflow: auto; } #menubar .menu:hover .options { diff --git a/editor/css/light.css b/editor/css/light.css index 3eeb4b951f7244..ac7b73b7e1a720 100644 --- a/editor/css/light.css +++ b/editor/css/light.css @@ -106,11 +106,13 @@ select { } #menubar .menu .options { - position: absolute; + position: fixed; display: none; padding: 5px 0; background: #eee; width: 150px; + max-height: calc(100% - 80px); + overflow: auto; } #menubar .menu:hover .options { diff --git a/editor/index.html b/editor/index.html index 321600354ad934..6f9d718cdcd6a6 100644 --- a/editor/index.html +++ b/editor/index.html @@ -27,6 +27,7 @@ + @@ -39,6 +40,7 @@ + @@ -83,8 +85,6 @@ - - @@ -390,51 +390,6 @@ }, false ); */ - // VR - - var groupVR; - - // TODO: Use editor.signals.enteredVR (WebVR 1.0) - - editor.signals.enterVR.add( function () { - - if ( groupVR === undefined ) { - - groupVR = new THREE.HTMLGroup( viewport.dom ); - editor.sceneHelpers.add( groupVR ); - - var mesh = new THREE.HTMLMesh( sidebar.dom ); - mesh.position.set( 15, 0, 15 ); - mesh.rotation.y = - 0.5; - groupVR.add( mesh ); - - var signals = editor.signals; - - function updateTexture() { - - mesh.material.map.update(); - - } - - signals.objectSelected.add( updateTexture ); - signals.objectAdded.add( updateTexture ); - signals.objectChanged.add( updateTexture ); - signals.objectRemoved.add( updateTexture ); - signals.sceneGraphChanged.add( updateTexture ); - signals.historyChanged.add( updateTexture ); - - } - - groupVR.visible = true; - - } ); - - editor.signals.exitedVR.add( function () { - - if ( groupVR !== undefined ) groupVR.visible = false; - - } ); - diff --git a/editor/js/Editor.js b/editor/js/Editor.js index ea63e412117c08..1ffba507b612e2 100644 --- a/editor/js/Editor.js +++ b/editor/js/Editor.js @@ -22,13 +22,6 @@ var Editor = function () { startPlayer: new Signal(), stopPlayer: new Signal(), - // vr - - enterVR: new Signal(), - - enteredVR: new Signal(), - exitedVR: new Signal(), - // actions showModal: new Signal(), @@ -347,6 +340,34 @@ Editor.prototype = { }, + getObjectMaterial: function ( object, slot ) { + + var material = object.material; + + if ( Array.isArray( material ) ) { + + material = material[ slot ]; + + } + + return material; + + }, + + setObjectMaterial: function ( object, slot, newMaterial ) { + + if ( Array.isArray( object.material ) ) { + + object.material[ slot ] = newMaterial; + + } else { + + object.material = newMaterial; + + } + + }, + // select: function ( object ) { diff --git a/editor/js/History.js b/editor/js/History.js index cb0338259290aa..d5830442182e6f 100644 --- a/editor/js/History.js +++ b/editor/js/History.js @@ -273,7 +273,7 @@ History.prototype = { if ( cmd === undefined || id === cmd.id ) break; - cmd = this.undo(); + this.undo(); } diff --git a/editor/js/Loader.js b/editor/js/Loader.js index 4479669f045af1..3be687970b023d 100644 --- a/editor/js/Loader.js +++ b/editor/js/Loader.js @@ -177,7 +177,7 @@ var Loader = function ( editor ) { var contents = event.target.result; var loader = new THREE.GLTFLoader(); - loader.parse( contents, function ( result ) { + loader.parse( contents, '', function ( result ) { result.scene.name = filename; editor.execute( new AddObjectCommand( result.scene ) ); @@ -428,6 +428,29 @@ var Loader = function ( editor ) { break; + case 'zip': + + reader.addEventListener( 'load', function ( event ) { + + var contents = event.target.result; + + var zip = new JSZip( contents ); + + // BLOCKS + + if ( zip.files[ 'model.obj' ] && zip.files[ 'materials.mtl' ] ) { + + var materials = new THREE.MTLLoader().parse( zip.file( 'materials.mtl' ).asText() ); + var object = new THREE.OBJLoader().setMaterials( materials ).parse( zip.file( 'model.obj' ).asText() ); + editor.execute( new AddObjectCommand( object ) ); + + } + + }, false ); + reader.readAsBinaryString( file ); + + break; + default: alert( 'Unsupported file format (' + extension + ').' ); diff --git a/editor/js/Menubar.File.js b/editor/js/Menubar.File.js index b87853585150d6..ceec61b810d9d3 100644 --- a/editor/js/Menubar.File.js +++ b/editor/js/Menubar.File.js @@ -48,13 +48,19 @@ Menubar.File = function ( editor ) { // Import + var form = document.createElement( 'form' ); + form.style.display = 'none'; + document.body.appendChild( form ); + var fileInput = document.createElement( 'input' ); fileInput.type = 'file'; fileInput.addEventListener( 'change', function ( event ) { editor.loader.loadFile( fileInput.files[ 0 ] ); + form.reset(); } ); + form.appendChild( fileInput ); var option = new UI.Row(); option.setClass( 'option' ); @@ -172,6 +178,29 @@ Menubar.File = function ( editor ) { } ); options.add( option ); + // + + options.add( new UI.HorizontalRule() ); + + // Export GLTF + + var option = new UI.Row(); + option.setClass( 'option' ); + option.setTextContent( 'Export GLTF' ); + option.onClick( function () { + + var exporter = new THREE.GLTFExporter(); + + exporter.parse( editor.scene, function ( result ) { + + saveString( JSON.stringify( result, null, 2 ), 'scene.gltf' ); + + } ); + + + } ); + options.add( option ); + // Export OBJ var option = new UI.Row(); @@ -250,8 +279,6 @@ Menubar.File = function ( editor ) { if ( vr ) { - includes.push( '' ); - includes.push( '' ); includes.push( '' ); } @@ -274,19 +301,7 @@ Menubar.File = function ( editor ) { if ( vr ) { - loader.load( '../examples/js/controls/VRControls.js', function ( content ) { - - zip.file( 'js/VRControls.js', content ); - - } ); - - loader.load( '../examples/js/effects/VREffect.js', function ( content ) { - - zip.file( 'js/VREffect.js', content ); - - } ); - - loader.load( '../examples/js/WebVR.js', function ( content ) { + loader.load( '../examples/js/vr/WebVR.js', function ( content ) { zip.file( 'js/WebVR.js', content ); diff --git a/editor/js/Sidebar.Material.js b/editor/js/Sidebar.Material.js index 421d39cf9ae540..47fb335c93a01d 100644 --- a/editor/js/Sidebar.Material.js +++ b/editor/js/Sidebar.Material.js @@ -5,8 +5,11 @@ Sidebar.Material = function ( editor ) { var signals = editor.signals; + var currentObject; + var currentMaterialSlot = 0; + var container = new UI.Panel(); container.setBorderTop( '0' ); container.setPaddingTop( '20px' ); @@ -14,13 +17,27 @@ Sidebar.Material = function ( editor ) { // New / Copy / Paste var copiedMaterial; + var managerRow = new UI.Row(); + // Current material slot + + var materialSlotRow = new UI.Row(); + + materialSlotRow.add( new UI.Text( 'Slot' ).setWidth( '90px' ) ); + + var materialSlotSelect = new UI.Select().setWidth( '170px' ).setFontSize( '12px' ).onChange( update ); + materialSlotSelect.setOptions( { 0: '' } ).setValue( 0 ); + materialSlotRow.add( materialSlotSelect ); + + container.add( materialSlotRow ); + managerRow.add( new UI.Text( '' ).setWidth( '90px' ) ); + managerRow.add( new UI.Button( 'New' ).onClick( function () { var material = new THREE[ materialClass.getValue() ](); - editor.execute( new SetMaterialCommand( currentObject, material ), 'New Material: ' + materialClass.getValue() ); + editor.execute( new SetMaterialCommand( currentObject, material, currentMaterialSlot ), 'New Material: ' + materialClass.getValue() ); update(); } ) ); @@ -29,13 +46,21 @@ Sidebar.Material = function ( editor ) { copiedMaterial = currentObject.material; + if ( Array.isArray( copiedMaterial ) ) { + + if ( copiedMaterial.length === 0 ) return; + + copiedMaterial = copiedMaterial[ currentMaterialSlot ]; + + } + } ) ); managerRow.add( new UI.Button( 'Paste' ).setMarginLeft( '4px' ).onClick( function () { if ( copiedMaterial === undefined ) return; - editor.execute( new SetMaterialCommand( currentObject, copiedMaterial ), 'Pasted Material: ' + materialClass.getValue() ); + editor.execute( new SetMaterialCommand( currentObject, copiedMaterial, currentMaterialSlot ), 'Pasted Material: ' + materialClass.getValue() ); refreshUI(); update(); @@ -90,7 +115,7 @@ Sidebar.Material = function ( editor ) { var materialNameRow = new UI.Row(); var materialName = new UI.Input().setWidth( '150px' ).setFontSize( '12px' ).onChange( function () { - editor.execute( new SetMaterialValueCommand( editor.selected, 'name', materialName.getValue() ) ); + editor.execute( new SetMaterialValueCommand( editor.selected, 'name', materialName.getValue(), currentMaterialSlot ) ); } ); @@ -410,15 +435,9 @@ Sidebar.Material = function ( editor ) { // shading var materialShadingRow = new UI.Row(); - var materialShading = new UI.Select().setOptions( { - - 0: 'No', - 1: 'Flat', - 2: 'Smooth' + var materialShading = new UI.Checkbox(false).setLeft( '100px' ).onChange( update ); - } ).setWidth( '150px' ).setFontSize( '12px' ).onChange( update ); - - materialShadingRow.add( new UI.Text( 'Shading' ).setWidth( '90px' ) ); + materialShadingRow.add( new UI.Text( 'Flat Shaded' ).setWidth( '90px' ) ); materialShadingRow.add( materialShading ); container.add( materialShadingRow ); @@ -491,7 +510,14 @@ Sidebar.Material = function ( editor ) { var object = currentObject; var geometry = object.geometry; - var material = object.material; + + var previousSelectedSlot = currentMaterialSlot; + + currentMaterialSlot = parseInt( materialSlotSelect.getValue() ); + + if ( currentMaterialSlot !== previousSelectedSlot ) refreshUI( true ); + + var material = editor.getObjectMaterial( currentObject, currentMaterialSlot ) var textureWarning = false; var objectHasUvs = false; @@ -504,7 +530,7 @@ Sidebar.Material = function ( editor ) { if ( material.uuid !== undefined && material.uuid !== materialUUID.getValue() ) { - editor.execute( new SetMaterialValueCommand( currentObject, 'uuid', materialUUID.getValue() ) ); + editor.execute( new SetMaterialValueCommand( currentObject, 'uuid', materialUUID.getValue(), currentMaterialSlot ) ); } @@ -512,7 +538,7 @@ Sidebar.Material = function ( editor ) { material = new THREE[ materialClass.getValue() ](); - editor.execute( new SetMaterialCommand( currentObject, material ), 'New Material: ' + materialClass.getValue() ); + editor.execute( new SetMaterialCommand( currentObject, material, currentMaterialSlot ), 'New Material: ' + materialClass.getValue() ); // TODO Copy other references in the scene graph // keeping name and UUID then. // Also there should be means to create a unique @@ -523,49 +549,49 @@ Sidebar.Material = function ( editor ) { if ( material.color !== undefined && material.color.getHex() !== materialColor.getHexValue() ) { - editor.execute( new SetMaterialColorCommand( currentObject, 'color', materialColor.getHexValue() ) ); + editor.execute( new SetMaterialColorCommand( currentObject, 'color', materialColor.getHexValue(), currentMaterialSlot ) ); } if ( material.roughness !== undefined && Math.abs( material.roughness - materialRoughness.getValue() ) >= 0.01 ) { - editor.execute( new SetMaterialValueCommand( currentObject, 'roughness', materialRoughness.getValue() ) ); + editor.execute( new SetMaterialValueCommand( currentObject, 'roughness', materialRoughness.getValue(), currentMaterialSlot ) ); } if ( material.metalness !== undefined && Math.abs( material.metalness - materialMetalness.getValue() ) >= 0.01 ) { - editor.execute( new SetMaterialValueCommand( currentObject, 'metalness', materialMetalness.getValue() ) ); + editor.execute( new SetMaterialValueCommand( currentObject, 'metalness', materialMetalness.getValue(), currentMaterialSlot ) ); } if ( material.emissive !== undefined && material.emissive.getHex() !== materialEmissive.getHexValue() ) { - editor.execute( new SetMaterialColorCommand( currentObject, 'emissive', materialEmissive.getHexValue() ) ); + editor.execute( new SetMaterialColorCommand( currentObject, 'emissive', materialEmissive.getHexValue(), currentMaterialSlot ) ); } if ( material.specular !== undefined && material.specular.getHex() !== materialSpecular.getHexValue() ) { - editor.execute( new SetMaterialColorCommand( currentObject, 'specular', materialSpecular.getHexValue() ) ); + editor.execute( new SetMaterialColorCommand( currentObject, 'specular', materialSpecular.getHexValue(), currentMaterialSlot ) ); } if ( material.shininess !== undefined && Math.abs( material.shininess - materialShininess.getValue() ) >= 0.01 ) { - editor.execute( new SetMaterialValueCommand( currentObject, 'shininess', materialShininess.getValue() ) ); + editor.execute( new SetMaterialValueCommand( currentObject, 'shininess', materialShininess.getValue(), currentMaterialSlot ) ); } if ( material.clearCoat !== undefined && Math.abs( material.clearCoat - materialClearCoat.getValue() ) >= 0.01 ) { - editor.execute( new SetMaterialValueCommand( currentObject, 'clearCoat', materialClearCoat.getValue() ) ); + editor.execute( new SetMaterialValueCommand( currentObject, 'clearCoat', materialClearCoat.getValue(), currentMaterialSlot ) ); } if ( material.clearCoatRoughness !== undefined && Math.abs( material.clearCoatRoughness - materialClearCoatRoughness.getValue() ) >= 0.01 ) { - editor.execute( new SetMaterialValueCommand( currentObject, 'clearCoatRoughness', materialClearCoatRoughness.getValue() ) ); + editor.execute( new SetMaterialValueCommand( currentObject, 'clearCoatRoughness', materialClearCoatRoughness.getValue(), currentMaterialSlot ) ); } @@ -575,7 +601,7 @@ Sidebar.Material = function ( editor ) { if ( material.vertexColors !== vertexColors ) { - editor.execute( new SetMaterialValueCommand( currentObject, 'vertexColors', vertexColors ) ); + editor.execute( new SetMaterialValueCommand( currentObject, 'vertexColors', vertexColors, currentMaterialSlot ) ); } @@ -583,7 +609,7 @@ Sidebar.Material = function ( editor ) { if ( material.skinning !== undefined && material.skinning !== materialSkinning.getValue() ) { - editor.execute( new SetMaterialValueCommand( currentObject, 'skinning', materialSkinning.getValue() ) ); + editor.execute( new SetMaterialValueCommand( currentObject, 'skinning', materialSkinning.getValue(), currentMaterialSlot ) ); } @@ -596,7 +622,7 @@ Sidebar.Material = function ( editor ) { var map = mapEnabled ? materialMap.getValue() : null; if ( material.map !== map ) { - editor.execute( new SetMaterialMapCommand( currentObject, 'map', map ) ); + editor.execute( new SetMaterialMapCommand( currentObject, 'map', map, currentMaterialSlot ) ); } @@ -617,7 +643,7 @@ Sidebar.Material = function ( editor ) { var alphaMap = mapEnabled ? materialAlphaMap.getValue() : null; if ( material.alphaMap !== alphaMap ) { - editor.execute( new SetMaterialMapCommand( currentObject, 'alphaMap', alphaMap ) ); + editor.execute( new SetMaterialMapCommand( currentObject, 'alphaMap', alphaMap, currentMaterialSlot ) ); } @@ -638,13 +664,13 @@ Sidebar.Material = function ( editor ) { var bumpMap = bumpMapEnabled ? materialBumpMap.getValue() : null; if ( material.bumpMap !== bumpMap ) { - editor.execute( new SetMaterialMapCommand( currentObject, 'bumpMap', bumpMap ) ); + editor.execute( new SetMaterialMapCommand( currentObject, 'bumpMap', bumpMap, currentMaterialSlot ) ); } if ( material.bumpScale !== materialBumpScale.getValue() ) { - editor.execute( new SetMaterialValueCommand( currentObject, 'bumpScale', materialBumpScale.getValue() ) ); + editor.execute( new SetMaterialValueCommand( currentObject, 'bumpScale', materialBumpScale.getValue(), currentMaterialSlot ) ); } @@ -665,7 +691,7 @@ Sidebar.Material = function ( editor ) { var normalMap = normalMapEnabled ? materialNormalMap.getValue() : null; if ( material.normalMap !== normalMap ) { - editor.execute( new SetMaterialMapCommand( currentObject, 'normalMap', normalMap ) ); + editor.execute( new SetMaterialMapCommand( currentObject, 'normalMap', normalMap, currentMaterialSlot ) ); } @@ -686,13 +712,13 @@ Sidebar.Material = function ( editor ) { var displacementMap = displacementMapEnabled ? materialDisplacementMap.getValue() : null; if ( material.displacementMap !== displacementMap ) { - editor.execute( new SetMaterialMapCommand( currentObject, 'displacementMap', displacementMap ) ); + editor.execute( new SetMaterialMapCommand( currentObject, 'displacementMap', displacementMap, currentMaterialSlot ) ); } if ( material.displacementScale !== materialDisplacementScale.getValue() ) { - editor.execute( new SetMaterialValueCommand( currentObject, 'displacementScale', materialDisplacementScale.getValue() ) ); + editor.execute( new SetMaterialValueCommand( currentObject, 'displacementScale', materialDisplacementScale.getValue(), currentMaterialSlot ) ); } @@ -713,7 +739,7 @@ Sidebar.Material = function ( editor ) { var roughnessMap = roughnessMapEnabled ? materialRoughnessMap.getValue() : null; if ( material.roughnessMap !== roughnessMap ) { - editor.execute( new SetMaterialMapCommand( currentObject, 'roughnessMap', roughnessMap ) ); + editor.execute( new SetMaterialMapCommand( currentObject, 'roughnessMap', roughnessMap, currentMaterialSlot ) ); } @@ -734,7 +760,7 @@ Sidebar.Material = function ( editor ) { var metalnessMap = metalnessMapEnabled ? materialMetalnessMap.getValue() : null; if ( material.metalnessMap !== metalnessMap ) { - editor.execute( new SetMaterialMapCommand( currentObject, 'metalnessMap', metalnessMap ) ); + editor.execute( new SetMaterialMapCommand( currentObject, 'metalnessMap', metalnessMap, currentMaterialSlot ) ); } @@ -755,7 +781,7 @@ Sidebar.Material = function ( editor ) { var specularMap = specularMapEnabled ? materialSpecularMap.getValue() : null; if ( material.specularMap !== specularMap ) { - editor.execute( new SetMaterialMapCommand( currentObject, 'specularMap', specularMap ) ); + editor.execute( new SetMaterialMapCommand( currentObject, 'specularMap', specularMap, currentMaterialSlot ) ); } @@ -775,7 +801,7 @@ Sidebar.Material = function ( editor ) { if ( material.envMap !== envMap ) { - editor.execute( new SetMaterialMapCommand( currentObject, 'envMap', envMap ) ); + editor.execute( new SetMaterialMapCommand( currentObject, 'envMap', envMap, currentMaterialSlot ) ); } @@ -787,7 +813,7 @@ Sidebar.Material = function ( editor ) { if ( material.reflectivity !== reflectivity ) { - editor.execute( new SetMaterialValueCommand( currentObject, 'reflectivity', reflectivity ) ); + editor.execute( new SetMaterialValueCommand( currentObject, 'reflectivity', reflectivity, currentMaterialSlot ) ); } @@ -802,7 +828,7 @@ Sidebar.Material = function ( editor ) { var lightMap = lightMapEnabled ? materialLightMap.getValue() : null; if ( material.lightMap !== lightMap ) { - editor.execute( new SetMaterialMapCommand( currentObject, 'lightMap', lightMap ) ); + editor.execute( new SetMaterialMapCommand( currentObject, 'lightMap', lightMap, currentMaterialSlot ) ); } @@ -823,13 +849,13 @@ Sidebar.Material = function ( editor ) { var aoMap = aoMapEnabled ? materialAOMap.getValue() : null; if ( material.aoMap !== aoMap ) { - editor.execute( new SetMaterialMapCommand( currentObject, 'aoMap', aoMap ) ); + editor.execute( new SetMaterialMapCommand( currentObject, 'aoMap', aoMap, currentMaterialSlot ) ); } if ( material.aoMapIntensity !== materialAOScale.getValue() ) { - editor.execute( new SetMaterialValueCommand( currentObject, 'aoMapIntensity', materialAOScale.getValue() ) ); + editor.execute( new SetMaterialValueCommand( currentObject, 'aoMapIntensity', materialAOScale.getValue(), currentMaterialSlot ) ); } @@ -850,7 +876,7 @@ Sidebar.Material = function ( editor ) { var emissiveMap = emissiveMapEnabled ? materialEmissiveMap.getValue() : null; if ( material.emissiveMap !== emissiveMap ) { - editor.execute( new SetMaterialMapCommand( currentObject, 'emissiveMap', emissiveMap ) ); + editor.execute( new SetMaterialMapCommand( currentObject, 'emissiveMap', emissiveMap, currentMaterialSlot ) ); } @@ -867,19 +893,19 @@ Sidebar.Material = function ( editor ) { var side = parseInt( materialSide.getValue() ); if ( material.side !== side ) { - editor.execute( new SetMaterialValueCommand( currentObject, 'side', side ) ); + editor.execute( new SetMaterialValueCommand( currentObject, 'side', side, currentMaterialSlot ) ); } } - if ( material.shading !== undefined ) { + if ( material.flatShading !== undefined ) { - var shading = parseInt( materialShading.getValue() ); - if ( material.shading !== shading ) { + var flatShading = materialShading.getValue(); + if ( material.flatShading != flatShading ) { - editor.execute( new SetMaterialValueCommand( currentObject, 'shading', shading ) ); + editor.execute( new SetMaterialValueCommand( currentObject, 'flatShading', flatShading, currentMaterialSlot ) ); } @@ -890,7 +916,7 @@ Sidebar.Material = function ( editor ) { var blending = parseInt( materialBlending.getValue() ); if ( material.blending !== blending ) { - editor.execute( new SetMaterialValueCommand( currentObject, 'blending', blending ) ); + editor.execute( new SetMaterialValueCommand( currentObject, 'blending', blending, currentMaterialSlot ) ); } @@ -898,31 +924,31 @@ Sidebar.Material = function ( editor ) { if ( material.opacity !== undefined && Math.abs( material.opacity - materialOpacity.getValue() ) >= 0.01 ) { - editor.execute( new SetMaterialValueCommand( currentObject, 'opacity', materialOpacity.getValue() ) ); + editor.execute( new SetMaterialValueCommand( currentObject, 'opacity', materialOpacity.getValue(), currentMaterialSlot ) ); } if ( material.transparent !== undefined && material.transparent !== materialTransparent.getValue() ) { - editor.execute( new SetMaterialValueCommand( currentObject, 'transparent', materialTransparent.getValue() ) ); + editor.execute( new SetMaterialValueCommand( currentObject, 'transparent', materialTransparent.getValue(), currentMaterialSlot ) ); } if ( material.alphaTest !== undefined && Math.abs( material.alphaTest - materialAlphaTest.getValue() ) >= 0.01 ) { - editor.execute( new SetMaterialValueCommand( currentObject, 'alphaTest', materialAlphaTest.getValue() ) ); + editor.execute( new SetMaterialValueCommand( currentObject, 'alphaTest', materialAlphaTest.getValue(), currentMaterialSlot ) ); } if ( material.wireframe !== undefined && material.wireframe !== materialWireframe.getValue() ) { - editor.execute( new SetMaterialValueCommand( currentObject, 'wireframe', materialWireframe.getValue() ) ); + editor.execute( new SetMaterialValueCommand( currentObject, 'wireframe', materialWireframe.getValue(), currentMaterialSlot) ); } if ( material.wireframeLinewidth !== undefined && Math.abs( material.wireframeLinewidth - materialWireframeLinewidth.getValue() ) >= 0.01 ) { - editor.execute( new SetMaterialValueCommand( currentObject, 'wireframeLinewidth', materialWireframeLinewidth.getValue() ) ); + editor.execute( new SetMaterialValueCommand( currentObject, 'wireframeLinewidth', materialWireframeLinewidth.getValue(), currentMaterialSlot ) ); } @@ -968,7 +994,7 @@ Sidebar.Material = function ( editor ) { 'aoMap': materialAOMapRow, 'emissiveMap': materialEmissiveMapRow, 'side': materialSideRow, - 'shading': materialShadingRow, + 'flatShading': materialShadingRow, 'blending': materialBlendingRow, 'opacity': materialOpacityRow, 'transparent': materialTransparentRow, @@ -978,6 +1004,20 @@ Sidebar.Material = function ( editor ) { var material = currentObject.material; + if ( Array.isArray( material ) ) { + + materialSlotRow.setDisplay( '' ); + + if ( material.length === 0 ) return; + + material = material[ currentMaterialSlot ]; + + } else { + + materialSlotRow.setDisplay( 'none' ); + + } + for ( var property in properties ) { properties[ property ].setDisplay( material[ property ] !== undefined ? '' : 'none' ); @@ -993,6 +1033,24 @@ Sidebar.Material = function ( editor ) { var material = currentObject.material; + if ( Array.isArray( material ) ) { + + var slotOptions = {}; + + currentMaterialSlot = Math.max( 0, Math.min( material.length, currentMaterialSlot ) ); + + for ( var i = 0; i < material.length; i ++ ) { + + slotOptions[ i ] = String( i + 1 ) + ': ' + material[ i ].name; + + } + + materialSlotSelect.setOptions( slotOptions ).setValue( currentMaterialSlot ); + + } + + material = editor.getObjectMaterial( currentObject, currentMaterialSlot ); + if ( material.uuid !== undefined ) { materialUUID.setValue( material.uuid ); @@ -1229,9 +1287,9 @@ Sidebar.Material = function ( editor ) { } - if ( material.shading !== undefined ) { + if ( material.flatShading !== undefined ) { - materialShading.setValue( material.shading ); + materialShading.setValue( material.flatShading ); } @@ -1279,8 +1337,21 @@ Sidebar.Material = function ( editor ) { signals.objectSelected.add( function ( object ) { - if ( object && object.material && - Array.isArray( object.material ) === false ) { + var hasMaterial = false; + + if ( object && object.material ) { + + hasMaterial = true; + + if ( Array.isArray( object.material ) && object.material.length === 0 ) { + + hasMaterial = false; + + } + + } + + if ( hasMaterial ) { var objectChanged = object !== currentObject; diff --git a/editor/js/Viewport.js b/editor/js/Viewport.js index 7cfb034ce798f3..8d7330e4ce24a5 100644 --- a/editor/js/Viewport.js +++ b/editor/js/Viewport.js @@ -22,18 +22,6 @@ var Viewport = function ( editor ) { var objects = []; - // - - var vrEffect, vrControls; - - if ( WEBVR.isAvailable() === true ) { - - var vrCamera = new THREE.PerspectiveCamera(); - vrCamera.projectionMatrix = camera.projectionMatrix; - camera.add( vrCamera ); - - } - // helpers var grid = new THREE.GridHelper( 60, 60 ); @@ -283,12 +271,6 @@ var Viewport = function ( editor ) { } ); - signals.enterVR.add( function () { - - vrEffect.isPresenting ? vrEffect.exitPresent() : vrEffect.requestPresent(); - - } ); - signals.themeChanged.add( function ( value ) { switch ( value ) { @@ -345,19 +327,6 @@ var Viewport = function ( editor ) { container.dom.appendChild( renderer.domElement ); - if ( WEBVR.isAvailable() === true ) { - - vrControls = new THREE.VRControls( vrCamera ); - vrEffect = new THREE.VREffect( renderer ); - - window.addEventListener( 'vrdisplaypresentchange', function ( event ) { - - effect.isPresenting ? signals.enteredVR.dispatch() : signals.exitedVR.dispatch(); - - }, false ); - - } - render(); } ); @@ -557,49 +526,21 @@ var Viewport = function ( editor ) { // - function animate() { - - requestAnimationFrame( animate ); - - if ( vrEffect && vrEffect.isPresenting ) { - - render(); - - } - - } - function render() { sceneHelpers.updateMatrixWorld(); scene.updateMatrixWorld(); - if ( vrEffect && vrEffect.isPresenting ) { + renderer.render( scene, camera ); - vrControls.update(); + if ( renderer instanceof THREE.RaytracingRenderer === false ) { - camera.updateMatrixWorld(); - - vrEffect.render( scene, vrCamera ); - vrEffect.render( sceneHelpers, vrCamera ); - - } else { - - renderer.render( scene, camera ); - - if ( renderer instanceof THREE.RaytracingRenderer === false ) { - - renderer.render( sceneHelpers, camera ); - - } + renderer.render( sceneHelpers, camera ); } - } - requestAnimationFrame( animate ); - return container; }; diff --git a/editor/js/commands/SetMaterialColorCommand.js b/editor/js/commands/SetMaterialColorCommand.js index 4cda80f437e82e..f4b271b32896d2 100644 --- a/editor/js/commands/SetMaterialColorCommand.js +++ b/editor/js/commands/SetMaterialColorCommand.js @@ -10,7 +10,7 @@ * @constructor */ -var SetMaterialColorCommand = function ( object, attributeName, newValue ) { +var SetMaterialColorCommand = function ( object, attributeName, newValue, materialSlot ) { Command.call( this ); @@ -19,25 +19,30 @@ var SetMaterialColorCommand = function ( object, attributeName, newValue ) { this.updatable = true; this.object = object; - this.attributeName = attributeName; - this.oldValue = ( object !== undefined ) ? this.object.material[ this.attributeName ].getHex() : undefined; + this.material = this.editor.getObjectMaterial( object, materialSlot ); + + this.oldValue = ( this.material !== undefined ) ? this.material[ attributeName ].getHex() : undefined; this.newValue = newValue; + this.attributeName = attributeName; + }; SetMaterialColorCommand.prototype = { execute: function () { - this.object.material[ this.attributeName ].setHex( this.newValue ); - this.editor.signals.materialChanged.dispatch( this.object.material ); + this.material[ this.attributeName ].setHex( this.newValue ); + + this.editor.signals.materialChanged.dispatch( this.material ); }, undo: function () { - this.object.material[ this.attributeName ].setHex( this.oldValue ); - this.editor.signals.materialChanged.dispatch( this.object.material ); + this.material[ this.attributeName ].setHex( this.oldValue ); + + this.editor.signals.materialChanged.dispatch( this.material ); }, diff --git a/editor/js/commands/SetMaterialCommand.js b/editor/js/commands/SetMaterialCommand.js index a78e4b0e07a2ae..949db2674ef659 100644 --- a/editor/js/commands/SetMaterialCommand.js +++ b/editor/js/commands/SetMaterialCommand.js @@ -9,7 +9,8 @@ * @constructor */ -var SetMaterialCommand = function ( object, newMaterial ) { + +var SetMaterialCommand = function ( object, newMaterial, materialSlot ) { Command.call( this ); @@ -17,7 +18,9 @@ var SetMaterialCommand = function ( object, newMaterial ) { this.name = 'New Material'; this.object = object; - this.oldMaterial = ( object !== undefined ) ? object.material : undefined; + this.materialSlot = materialSlot; + + this.oldMaterial = this.editor.getObjectMaterial( object, materialSlot ); this.newMaterial = newMaterial; }; @@ -26,14 +29,14 @@ SetMaterialCommand.prototype = { execute: function () { - this.object.material = this.newMaterial; + this.editor.setObjectMaterial( this.object, this.materialSlot, this.newMaterial ); this.editor.signals.materialChanged.dispatch( this.newMaterial ); }, undo: function () { - this.object.material = this.oldMaterial; + this.editor.setObjectMaterial( this.object, this.materialSlot, this.oldMaterial ); this.editor.signals.materialChanged.dispatch( this.oldMaterial ); }, @@ -58,7 +61,6 @@ SetMaterialCommand.prototype = { this.oldMaterial = parseMaterial( json.oldMaterial ); this.newMaterial = parseMaterial( json.newMaterial ); - function parseMaterial ( json ) { var loader = new THREE.ObjectLoader(); diff --git a/editor/js/commands/SetMaterialMapCommand.js b/editor/js/commands/SetMaterialMapCommand.js index 08a00d85dc0abe..8aff3aa17e2f0e 100644 --- a/editor/js/commands/SetMaterialMapCommand.js +++ b/editor/js/commands/SetMaterialMapCommand.js @@ -10,34 +10,40 @@ * @constructor */ -var SetMaterialMapCommand = function ( object, mapName, newMap ) { +var SetMaterialMapCommand = function ( object, mapName, newMap, materialSlot ) { Command.call( this ); + this.type = 'SetMaterialMapCommand'; this.name = 'Set Material.' + mapName; this.object = object; - this.mapName = mapName; - this.oldMap = ( object !== undefined ) ? object.material[ mapName ] : undefined; + this.material = this.editor.getObjectMaterial( object, materialSlot ); + + this.oldMap = ( object !== undefined ) ? this.material[ mapName ] : undefined; this.newMap = newMap; + this.mapName = mapName; + }; SetMaterialMapCommand.prototype = { execute: function () { - this.object.material[ this.mapName ] = this.newMap; - this.object.material.needsUpdate = true; - this.editor.signals.materialChanged.dispatch( this.object.material ); + this.material[ this.mapName ] = this.newMap; + this.material.needsUpdate = true; + + this.editor.signals.materialChanged.dispatch( this.material ); }, undo: function () { - this.object.material[ this.mapName ] = this.oldMap; - this.object.material.needsUpdate = true; - this.editor.signals.materialChanged.dispatch( this.object.material ); + this.material[ this.mapName ] = this.oldMap; + this.material.needsUpdate = true; + + this.editor.signals.materialChanged.dispatch( this.material ); }, diff --git a/editor/js/commands/SetMaterialValueCommand.js b/editor/js/commands/SetMaterialValueCommand.js index 3b03ade1981e25..adfda994d741d0 100644 --- a/editor/js/commands/SetMaterialValueCommand.js +++ b/editor/js/commands/SetMaterialValueCommand.js @@ -10,7 +10,7 @@ * @constructor */ -var SetMaterialValueCommand = function ( object, attributeName, newValue ) { +var SetMaterialValueCommand = function ( object, attributeName, newValue, materialSlot ) { Command.call( this ); @@ -19,8 +19,11 @@ var SetMaterialValueCommand = function ( object, attributeName, newValue ) { this.updatable = true; this.object = object; - this.oldValue = ( object !== undefined ) ? object.material[ attributeName ] : undefined; + this.material = this.editor.getObjectMaterial( object, materialSlot ); + + this.oldValue = ( this.material !== undefined ) ? this.material[ attributeName ] : undefined; this.newValue = newValue; + this.attributeName = attributeName; }; @@ -29,19 +32,21 @@ SetMaterialValueCommand.prototype = { execute: function () { - this.object.material[ this.attributeName ] = this.newValue; - this.object.material.needsUpdate = true; + this.material[ this.attributeName ] = this.newValue; + this.material.needsUpdate = true; + this.editor.signals.objectChanged.dispatch( this.object ); - this.editor.signals.materialChanged.dispatch( this.object.material ); + this.editor.signals.materialChanged.dispatch( this.material ); }, undo: function () { - this.object.material[ this.attributeName ] = this.oldValue; - this.object.material.needsUpdate = true; + this.material[ this.attributeName ] = this.oldValue; + this.material.needsUpdate = true; + this.editor.signals.objectChanged.dispatch( this.object ); - this.editor.signals.materialChanged.dispatch( this.object.material ); + this.editor.signals.materialChanged.dispatch( this.material ); }, diff --git a/editor/js/libs/app.js b/editor/js/libs/app.js index 6acec01426c57f..3dcc65d495a6f0 100644 --- a/editor/js/libs/app.js +++ b/editor/js/libs/app.js @@ -9,34 +9,29 @@ var APP = { var loader = new THREE.ObjectLoader(); var camera, scene, renderer; - var controls, effect, cameraVR, isVR; - var events = {}; - this.dom = document.createElement( 'div' ); + var dom = document.createElement( 'div' ); + + this.dom = dom; this.width = 500; this.height = 500; this.load = function ( json ) { - isVR = json.project.vr; - renderer = new THREE.WebGLRenderer( { antialias: true } ); renderer.setClearColor( 0x000000 ); renderer.setPixelRatio( window.devicePixelRatio ); - if ( json.project.gammaInput ) renderer.gammaInput = true; - if ( json.project.gammaOutput ) renderer.gammaOutput = true; - - if ( json.project.shadows ) { - - renderer.shadowMap.enabled = true; - // renderer.shadowMap.type = THREE.PCFSoftShadowMap; + var project = json.project; - } + if ( project.gammaInput ) renderer.gammaInput = true; + if ( project.gammaOutput ) renderer.gammaOutput = true; + if ( project.shadows ) renderer.shadowMap.enabled = true; + if ( project.vr ) renderer.vr.enabled = true; - this.dom.appendChild( renderer.domElement ); + dom.appendChild( renderer.domElement ); this.setScene( loader.parse( json.scene ) ); this.setCamera( loader.parse( json.camera ) ); @@ -116,26 +111,20 @@ var APP = { camera.aspect = this.width / this.height; camera.updateProjectionMatrix(); - if ( isVR === true ) { - - cameraVR = new THREE.PerspectiveCamera(); - cameraVR.projectionMatrix = camera.projectionMatrix; - camera.add( cameraVR ); + if ( renderer.vr.enabled ) { - controls = new THREE.VRControls( cameraVR ); - effect = new THREE.VREffect( renderer ); + WEBVR.checkAvailability().catch( function( message ) { - if ( WEBVR.isAvailable() === true ) { + dom.appendChild( WEBVR.getMessageContainer( message ) ); - this.dom.appendChild( WEBVR.getButton( effect ) ); + } ); - } + WEBVR.getVRDisplay( function ( device ) { - if ( WEBVR.isLatestAvailable() === false ) { + renderer.vr.setDevice( device ); + dom.appendChild( WEBVR.getButton( device, renderer.domElement ) ); - this.dom.appendChild( WEBVR.getMessage() ); - - } + } ); } @@ -177,12 +166,10 @@ var APP = { } - var prevTime, request; + var prevTime; function animate( time ) { - request = requestAnimationFrame( animate ); - try { dispatch( events.update, { time: time, delta: time - prevTime } ); @@ -193,18 +180,7 @@ var APP = { } - if ( isVR === true ) { - - camera.updateMatrixWorld(); - - controls.update(); - effect.render( scene, cameraVR ); - - } else { - - renderer.render( scene, camera ); - - } + renderer.render( scene, camera ); prevTime = time; @@ -212,6 +188,8 @@ var APP = { this.play = function () { + prevTime = performance.now(); + document.addEventListener( 'keydown', onDocumentKeyDown ); document.addEventListener( 'keyup', onDocumentKeyUp ); document.addEventListener( 'mousedown', onDocumentMouseDown ); @@ -223,8 +201,7 @@ var APP = { dispatch( events.start, arguments ); - request = requestAnimationFrame( animate ); - prevTime = performance.now(); + renderer.animate( animate ); }; @@ -241,15 +218,15 @@ var APP = { dispatch( events.stop, arguments ); - cancelAnimationFrame( request ); + renderer.animate( null ); }; this.dispose = function () { - while ( this.dom.children.length ) { + while ( dom.children.length ) { - this.dom.removeChild( this.dom.firstChild ); + dom.removeChild( dom.firstChild ); } diff --git a/editor/js/libs/tern-threejs/threejs.js b/editor/js/libs/tern-threejs/threejs.js index a75a9c274c3b70..7150ca34f5947f 100644 --- a/editor/js/libs/tern-threejs/threejs.js +++ b/editor/js/libs/tern-threejs/threejs.js @@ -1731,74 +1731,6 @@ "!doc": "base class for immediate rendering objects.", "!type": "fn()" }, - "MorphBlendMesh": { - "!url": "http://threejs.org/docs/#Reference/extras/objects/MorphBlendMesh", - "prototype": { - "!proto": "THREE.Mesh.prototype", - "animationsMap": { - "!type": "object", - "!doc": "todo" - }, - "animationsList": { - "!type": "array", - "!doc": "todo" - }, - "setAnimationWeight": { - "!type": "fn(name: todo, weight: todo) -> todo", - "!doc": "todo" - }, - "setAnimationFPS": { - "!type": "fn(name: todo, fps: todo) -> todo", - "!doc": "todo" - }, - "createAnimation": { - "!type": "fn(name: todo, start: todo, end: todo, fps: todo) -> todo", - "!doc": "todo" - }, - "playAnimation": { - "!type": "fn(name: todo) -> todo", - "!doc": "todo" - }, - "update": { - "!type": "fn(delta: todo) -> todo", - "!doc": "todo" - }, - "autoCreateAnimations": { - "!type": "fn(fps: todo) -> todo", - "!doc": "todo" - }, - "setAnimationDuration": { - "!type": "fn(name: todo, duration: todo) -> todo", - "!doc": "todo" - }, - "setAnimationDirectionForward": { - "!type": "fn(name: todo) -> todo", - "!doc": "todo" - }, - "getAnimationDuration": { - "!type": "fn(name: todo) -> todo", - "!doc": "todo" - }, - "getAnimationTime": { - "!type": "fn(name: todo) -> todo", - "!doc": "todo" - }, - "setAnimationDirectionBackward": { - "!type": "fn(name: todo) -> todo", - "!doc": "todo" - }, - "setAnimationTime": { - "!type": "fn(name: todo, time: todo) -> todo", - "!doc": "todo" - }, - "stopAnimation": { - "!type": "fn(name: todo) -> todo", - "!doc": "todo" - } - }, - "!doc": "todo", - "!type": "fn(geometry: todo, material: todo)" - }, "AmbientLight": { "!url": "http://threejs.org/docs/#Reference/lights/AmbientLight", "prototype": { diff --git a/examples/canvas_ascii_effect.html b/examples/canvas_ascii_effect.html index ed41d914756c39..a7cf8749584519 100644 --- a/examples/canvas_ascii_effect.html +++ b/examples/canvas_ascii_effect.html @@ -62,6 +62,7 @@ controls = new THREE.TrackballControls( camera ); scene = new THREE.Scene(); + scene.background = new THREE.Color( 0xf0f0f0 ); var light = new THREE.PointLight( 0xffffff ); light.position.set( 500, 500, 500 ); @@ -82,7 +83,6 @@ scene.add( plane ); renderer = new THREE.CanvasRenderer(); - renderer.setClearColor( 0xf0f0f0 ); renderer.setSize( width, height ); // container.appendChild( renderer.domElement ); diff --git a/examples/canvas_camera_orthographic.html b/examples/canvas_camera_orthographic.html index 296e4bfe31974e..95e780c0499cca 100644 --- a/examples/canvas_camera_orthographic.html +++ b/examples/canvas_camera_orthographic.html @@ -26,6 +26,7 @@ var container, stats; var camera, scene, renderer; + var frustumSize = 1000; init(); animate(); @@ -40,15 +41,15 @@ info.style.top = '10px'; info.style.width = '100%'; info.style.textAlign = 'center'; - info.innerHTML = 'three.js - orthographic view'; + info.innerHTML = 'three.js - orthographic view'; container.appendChild( info ); - camera = new THREE.OrthographicCamera( window.innerWidth / - 2, window.innerWidth / 2, window.innerHeight / 2, window.innerHeight / - 2, - 500, 1000 ); - camera.position.x = 200; - camera.position.y = 100; - camera.position.z = 200; + var aspect = window.innerWidth / window.innerHeight; + camera = new THREE.OrthographicCamera( frustumSize * aspect / - 2, frustumSize * aspect / 2, frustumSize / 2, frustumSize / - 2, 1, 2000 ); + camera.position.y = 400; scene = new THREE.Scene(); + scene.background = new THREE.Color( 0xf0f0f0 ); // Grid @@ -94,7 +95,6 @@ scene.add( directionalLight ); renderer = new THREE.CanvasRenderer(); - renderer.setClearColor( 0xf0f0f0 ); renderer.setPixelRatio( window.devicePixelRatio ); renderer.setSize( window.innerWidth, window.innerHeight ); container.appendChild( renderer.domElement ); @@ -110,10 +110,12 @@ function onWindowResize() { - camera.left = window.innerWidth / - 2; - camera.right = window.innerWidth / 2; - camera.top = window.innerHeight / 2; - camera.bottom = window.innerHeight / - 2; + var aspect = window.innerWidth / window.innerHeight; + + camera.left = - frustumSize * aspect / 2; + camera.right = frustumSize * aspect / 2; + camera.top = frustumSize / 2; + camera.bottom = - frustumSize / 2; camera.updateProjectionMatrix(); @@ -137,8 +139,8 @@ var timer = Date.now() * 0.0001; - camera.position.x = Math.cos( timer ) * 200; - camera.position.z = Math.sin( timer ) * 200; + camera.position.x = Math.cos( timer ) * 800; + camera.position.z = Math.sin( timer ) * 800; camera.lookAt( scene.position ); renderer.render( scene, camera ); diff --git a/examples/canvas_camera_orthographic2.html b/examples/canvas_camera_orthographic2.html index aee60d54bb7b28..7164ef875fb2ad 100644 --- a/examples/canvas_camera_orthographic2.html +++ b/examples/canvas_camera_orthographic2.html @@ -30,7 +30,7 @@
      - three.js - Combo Camera
      + three.js - Combo Camera
      View: Orthographic | Perspective
      Lens: 12mm | @@ -118,6 +118,7 @@ camera.position.z = 200; scene = new THREE.Scene(); + scene.background = new THREE.Color( 0xf0f0f0 ); // Grid @@ -163,7 +164,6 @@ scene.add( directionalLight ); renderer = new THREE.CanvasRenderer(); - renderer.setClearColor( 0xf0f0f0 ); renderer.setPixelRatio( window.devicePixelRatio ); renderer.setSize( window.innerWidth, window.innerHeight ); container.appendChild( renderer.domElement ); diff --git a/examples/canvas_geometry_birds.html b/examples/canvas_geometry_birds.html index 5daf65dfb574d6..9c26e0944414ce 100644 --- a/examples/canvas_geometry_birds.html +++ b/examples/canvas_geometry_birds.html @@ -26,7 +26,7 @@
      -
      three.js - birds demo
      +
      three.js - birds demo
      @@ -342,6 +342,7 @@ camera.position.z = 450; scene = new THREE.Scene(); + scene.background = new THREE.Color( 0xffffff ); birds = []; boids = []; @@ -366,7 +367,6 @@ } renderer = new THREE.CanvasRenderer(); - renderer.setClearColor( 0xffffff ); renderer.setPixelRatio( window.devicePixelRatio ); renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT ); diff --git a/examples/canvas_geometry_cube.html b/examples/canvas_geometry_cube.html index a1b964b4fdb359..c6cf153afdeaba 100644 --- a/examples/canvas_geometry_cube.html +++ b/examples/canvas_geometry_cube.html @@ -60,6 +60,8 @@ camera.position.z = 500; scene = new THREE.Scene(); + scene.background = new THREE.Color( 0xf0f0f0 ); + // Cube @@ -90,7 +92,6 @@ scene.add( plane ); renderer = new THREE.CanvasRenderer(); - renderer.setClearColor( 0xf0f0f0 ); renderer.setPixelRatio( window.devicePixelRatio ); renderer.setSize( window.innerWidth, window.innerHeight ); container.appendChild( renderer.domElement ); diff --git a/examples/canvas_geometry_earth.html b/examples/canvas_geometry_earth.html index ce082734004bc5..1b892faad43a09 100644 --- a/examples/canvas_geometry_earth.html +++ b/examples/canvas_geometry_earth.html @@ -32,7 +32,7 @@
      -
      three.js - earth demo
      +
      three.js - earth demo
      @@ -62,6 +62,7 @@ camera.position.z = 500; scene = new THREE.Scene(); + scene.background = new THREE.Color( 0xffffff ); group = new THREE.Group(); scene.add( group ); @@ -111,7 +112,6 @@ group.add( mesh ); renderer = new THREE.CanvasRenderer(); - renderer.setClearColor( 0xffffff ); renderer.setPixelRatio( window.devicePixelRatio ); renderer.setSize( window.innerWidth, window.innerHeight ); container.appendChild( renderer.domElement ); diff --git a/examples/canvas_geometry_hierarchy.html b/examples/canvas_geometry_hierarchy.html index 8278de17d95f9f..299db71d4b5a1c 100644 --- a/examples/canvas_geometry_hierarchy.html +++ b/examples/canvas_geometry_hierarchy.html @@ -50,6 +50,7 @@ camera.position.z = 500; scene = new THREE.Scene(); + scene.background = new THREE.Color( 0xffffff ); var geometry = new THREE.BoxGeometry( 100, 100, 100 ); var material = new THREE.MeshNormalMaterial( { overdraw: 0.5 } ); @@ -73,7 +74,6 @@ scene.add( group ); renderer = new THREE.CanvasRenderer(); - renderer.setClearColor( 0xffffff ); renderer.setPixelRatio( window.devicePixelRatio ); renderer.setSize( window.innerWidth, window.innerHeight ); container.appendChild( renderer.domElement ); diff --git a/examples/canvas_geometry_nurbs.html b/examples/canvas_geometry_nurbs.html index 3a0a623991d5ef..6de5bc131a758b 100644 --- a/examples/canvas_geometry_nurbs.html +++ b/examples/canvas_geometry_nurbs.html @@ -23,7 +23,7 @@ -
      three.js - NURBS curve example
      +
      three.js - NURBS curve example
      @@ -71,6 +71,7 @@ camera.position.set( 0, 150, 500 ); scene = new THREE.Scene(); + scene.background = new THREE.Color( 0xf0f0f0 ); group = new THREE.Group(); group.position.y = 50; @@ -127,7 +128,6 @@ // renderer = new THREE.CanvasRenderer(); - renderer.setClearColor( 0xf0f0f0 ); renderer.setPixelRatio( window.devicePixelRatio ); renderer.setSize( window.innerWidth, window.innerHeight ); container.appendChild( renderer.domElement ); diff --git a/examples/canvas_geometry_panorama.html b/examples/canvas_geometry_panorama.html index 10a8fc14b7a116..0c4d7280500a18 100644 --- a/examples/canvas_geometry_panorama.html +++ b/examples/canvas_geometry_panorama.html @@ -30,7 +30,7 @@
      -
      three.js - panorama demo. cubemap by Jochum Skoglund.
      +
      three.js - panorama demo. cubemap by Jochum Skoglund.
      @@ -164,7 +164,10 @@ function onDocumentMouseWheel( event ) { - camera.fov += event.deltaY * 0.05; + var fov = camera.fov + event.deltaY * 0.05; + + camera.fov = THREE.Math.clamp( fov, 10, 75 ); + camera.updateProjectionMatrix(); } diff --git a/examples/canvas_geometry_panorama_fisheye.html b/examples/canvas_geometry_panorama_fisheye.html index da1e078d0b108f..810bd569bb5346 100644 --- a/examples/canvas_geometry_panorama_fisheye.html +++ b/examples/canvas_geometry_panorama_fisheye.html @@ -30,7 +30,7 @@
      -
      three.js - panorama fisheye demo. cubemap by Jochum Skoglund. (mousewheel: change fov)
      +
      three.js - panorama fisheye demo. cubemap by Jochum Skoglund. (mousewheel: change fov)
      @@ -172,7 +172,10 @@ function onDocumentMouseWheel( event ) { - camera.fov += event.deltaY * 0.05; + var fov = camera.fov + event.deltaY * 0.05; + + camera.fov = THREE.Math.clamp( fov, 10, 75 ); + camera.updateProjectionMatrix(); } diff --git a/examples/canvas_geometry_shapes.html b/examples/canvas_geometry_shapes.html index ad642ad8258b7f..8525565078947f 100644 --- a/examples/canvas_geometry_shapes.html +++ b/examples/canvas_geometry_shapes.html @@ -23,7 +23,7 @@ -
      three.js - shape geometry
      +
      three.js - shape geometry
      @@ -61,6 +61,7 @@ camera.position.set( 0, 150, 500 ); scene = new THREE.Scene(); + scene.background = new THREE.Color( 0xf0f0f0 ); group = new THREE.Group(); group.position.y = 50; @@ -293,7 +294,6 @@ // renderer = new THREE.CanvasRenderer(); - renderer.setClearColor( 0xf0f0f0 ); renderer.setPixelRatio( window.devicePixelRatio ); renderer.setSize( window.innerWidth, window.innerHeight ); renderer.sortElements = false; diff --git a/examples/canvas_geometry_terrain.html b/examples/canvas_geometry_terrain.html index e50cc5078ad860..9cedb85655b062 100644 --- a/examples/canvas_geometry_terrain.html +++ b/examples/canvas_geometry_terrain.html @@ -32,7 +32,7 @@





      Generating...
      -
      three.js - terrain demo. generate another
      +
      three.js - terrain demo. generate another
      @@ -67,6 +67,7 @@ camera.position.z = 500; scene = new THREE.Scene(); + scene.background = new THREE.Color( 0xbfd1e5 ); var data = generateHeight( 1024, 1024 ); var texture = new THREE.CanvasTexture( generateTexture( data, 1024, 1024 ) ); @@ -88,7 +89,6 @@ scene.add( mesh ); renderer = new THREE.CanvasRenderer(); - renderer.setClearColor( 0xbfd1e5 ); renderer.setPixelRatio( window.devicePixelRatio ); renderer.setSize( window.innerWidth, window.innerHeight ); diff --git a/examples/canvas_geometry_text.html b/examples/canvas_geometry_text.html index 069f71459f6392..3901c973325e54 100644 --- a/examples/canvas_geometry_text.html +++ b/examples/canvas_geometry_text.html @@ -66,6 +66,7 @@ camera.position.set( 0, 150, 500 ); scene = new THREE.Scene(); + scene.background = new THREE.Color( 0xf0f0f0 ); // Get text from hash @@ -112,7 +113,6 @@ scene.add( group ); renderer = new THREE.CanvasRenderer(); - renderer.setClearColor( 0xf0f0f0 ); renderer.setPixelRatio( window.devicePixelRatio ); renderer.setSize( window.innerWidth, window.innerHeight ); container.appendChild( renderer.domElement ); diff --git a/examples/canvas_interactive_cubes.html b/examples/canvas_interactive_cubes.html index e4b5ee77131d5a..cc973704fc2a13 100644 --- a/examples/canvas_interactive_cubes.html +++ b/examples/canvas_interactive_cubes.html @@ -46,13 +46,14 @@ info.style.top = '10px'; info.style.width = '100%'; info.style.textAlign = 'center'; - info.innerHTML = 'three.js - clickable objects'; + info.innerHTML = 'three.js - clickable objects'; container.appendChild( info ); camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 10000 ); camera.position.set( 0, 300, 500 ); scene = new THREE.Scene(); + scene.background = new THREE.Color( 0xf0f0f0 ); var geometry = new THREE.BoxGeometry( 100, 100, 100 ); @@ -97,7 +98,6 @@ mouse = new THREE.Vector2(); renderer = new THREE.CanvasRenderer(); - renderer.setClearColor( 0xf0f0f0 ); renderer.setPixelRatio( window.devicePixelRatio ); renderer.setSize( window.innerWidth, window.innerHeight ); container.appendChild( renderer.domElement ); diff --git a/examples/canvas_interactive_cubes_tween.html b/examples/canvas_interactive_cubes_tween.html index 8868d5ba376b86..6af2dbe3cfbde7 100644 --- a/examples/canvas_interactive_cubes_tween.html +++ b/examples/canvas_interactive_cubes_tween.html @@ -44,7 +44,7 @@ info.style.top = '10px'; info.style.width = '100%'; info.style.textAlign = 'center'; - info.innerHTML = 'three.js - clickable objects'; + info.innerHTML = 'three.js - clickable objects'; container.appendChild( info ); camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 10000 ); @@ -52,6 +52,7 @@ camera.position.z = 500; scene = new THREE.Scene(); + scene.background = new THREE.Color( 0xf0f0f0 ); var geometry = new THREE.BoxGeometry( 100, 100, 100 ); @@ -77,7 +78,6 @@ mouse = new THREE.Vector2(); renderer = new THREE.CanvasRenderer(); - renderer.setClearColor( 0xf0f0f0 ); renderer.setPixelRatio( window.devicePixelRatio ); renderer.setSize( window.innerWidth, window.innerHeight ); container.appendChild(renderer.domElement); diff --git a/examples/canvas_interactive_particles.html b/examples/canvas_interactive_particles.html index f4d97a9a8c7a11..a0bb1058f05889 100644 --- a/examples/canvas_interactive_particles.html +++ b/examples/canvas_interactive_particles.html @@ -64,13 +64,14 @@ info.style.top = '10px'; info.style.width = '100%'; info.style.textAlign = 'center'; - info.innerHTML = 'three.js canvas - interactive particles'; + info.innerHTML = 'three.js canvas - interactive particles'; container.appendChild( info ); camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 10000 ); camera.position.set( 0, 300, 500 ); scene = new THREE.Scene(); + scene.background = new THREE.Color( 0xf0f0f0 ); for ( var i = 0; i < 100; i ++ ) { @@ -89,7 +90,6 @@ mouse = new THREE.Vector2(); renderer = new THREE.CanvasRenderer(); - renderer.setClearColor( 0xf0f0f0 ); renderer.setPixelRatio( window.devicePixelRatio ); renderer.setSize( window.innerWidth, window.innerHeight ); container.appendChild( renderer.domElement ); diff --git a/examples/canvas_interactive_voxelpainter.html b/examples/canvas_interactive_voxelpainter.html index c5f8b59aa5799a..0818cc7a1d272e 100644 --- a/examples/canvas_interactive_voxelpainter.html +++ b/examples/canvas_interactive_voxelpainter.html @@ -46,7 +46,7 @@ info.style.top = '10px'; info.style.width = '100%'; info.style.textAlign = 'center'; - info.innerHTML = 'three.js - voxel painter
      click: add voxel, shift + click: remove voxel, save .png'; + info.innerHTML = 'three.js - voxel painter
      click: add voxel, shift + click: remove voxel, save .png'; container.appendChild( info ); camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 10000 ); @@ -54,6 +54,7 @@ camera.lookAt( new THREE.Vector3() ); scene = new THREE.Scene(); + scene.background = new THREE.Color( 0xf0f0f0 ); // Grid @@ -95,7 +96,6 @@ scene.add( directionalLight ); renderer = new THREE.CanvasRenderer(); - renderer.setClearColor( 0xf0f0f0 ); renderer.setPixelRatio( window.devicePixelRatio ); renderer.setSize( window.innerWidth, window.innerHeight ); container.appendChild(renderer.domElement); diff --git a/examples/canvas_lights_pointlights.html b/examples/canvas_lights_pointlights.html index 2028738c39f583..3a25017a4df00c 100644 --- a/examples/canvas_lights_pointlights.html +++ b/examples/canvas_lights_pointlights.html @@ -35,8 +35,8 @@
      - three.js - point lights demo.
      - Walt Disney head by David OReilly + three.js - point lights demo.
      + Walt Disney head by David OReilly
      diff --git a/examples/canvas_lines_colors.html b/examples/canvas_lines_colors.html index dbfc6185ffc082..3be772e5b6759b 100644 --- a/examples/canvas_lines_colors.html +++ b/examples/canvas_lines_colors.html @@ -40,7 +40,7 @@
      - three.js - color lines + three.js - color lines [Hilbert curve thanks to Thomas Diewald]
      diff --git a/examples/canvas_lines_colors_2d.html b/examples/canvas_lines_colors_2d.html index 0579a068ffa8c2..34419b4f99bc3a 100644 --- a/examples/canvas_lines_colors_2d.html +++ b/examples/canvas_lines_colors_2d.html @@ -40,7 +40,7 @@
      - three.js - color lines WebGL demo + three.js - color lines WebGL demo [Hilbert curve thanks to Thomas Diewald]
      diff --git a/examples/canvas_lines_dashed.html b/examples/canvas_lines_dashed.html index 2b513bde0efb21..76c9bbdbbb6691 100644 --- a/examples/canvas_lines_dashed.html +++ b/examples/canvas_lines_dashed.html @@ -28,7 +28,7 @@ -
      three.js - dashed lines example
      +
      three.js - dashed lines example
      @@ -61,8 +61,7 @@ camera.position.z = 150; scene = new THREE.Scene(); - - scene.fog = new THREE.Fog( 0x111111, 150, 200 ); + scene.background = new THREE.Color( 0x111111 ); root = new THREE.Object3D(); @@ -93,13 +92,12 @@ objects.push( object ); scene.add( object ); - var object = new THREE.LineSegments( geometryCube, new THREE.LineDashedMaterial( { color: 0xffaa00, dashSize: 3, gapSize: 1, linewidth: 2 } ) ); + var object = new THREE.LineSegments( geometryCube, new THREE.LineDashedMaterial( { color: 0xffaa00, dashSize: 30, gapSize: 10, linewidth: 2 } ) ); objects.push( object ); scene.add( object ); renderer = new THREE.CanvasRenderer(); - renderer.setClearColor( 0x111111 ); renderer.setPixelRatio( window.devicePixelRatio ); renderer.setSize( WIDTH, HEIGHT ); diff --git a/examples/canvas_materials_normal.html b/examples/canvas_materials_normal.html index 64bca9725213ef..edf05f12b15a92 100644 --- a/examples/canvas_materials_normal.html +++ b/examples/canvas_materials_normal.html @@ -35,8 +35,8 @@
      - three.js - normal material.
      - Walt Disney head by David OReilly + three.js - normal material.
      + Walt Disney head by David OReilly
      diff --git a/examples/canvas_materials_reflection.html b/examples/canvas_materials_reflection.html index 18f94cc9621677..8333c135b18c3f 100644 --- a/examples/canvas_materials_reflection.html +++ b/examples/canvas_materials_reflection.html @@ -34,8 +34,8 @@
      - three.js - spherical reflection demo.
      - Walt Disney head by David OReilly. Reflection texture by Kewlers. + three.js - spherical reflection demo.
      + Walt Disney head by David OReilly. Reflection texture by Kewlers.
      diff --git a/examples/canvas_materials_video.html b/examples/canvas_materials_video.html index 472838e81d3e82..ff1c37150c82a2 100644 --- a/examples/canvas_materials_video.html +++ b/examples/canvas_materials_video.html @@ -60,13 +60,14 @@ info.style.top = '10px'; info.style.width = '100%'; info.style.textAlign = 'center'; - info.innerHTML = 'three.js - video demo. playing sintel trailer'; + info.innerHTML = 'three.js - video demo. playing sintel trailer'; container.appendChild( info ); camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 10000 ); camera.position.z = 1000; scene = new THREE.Scene(); + scene.background = new THREE.Color( 0xf0f0f0 ); video = document.getElementById( 'video' ); @@ -150,7 +151,6 @@ } renderer = new THREE.CanvasRenderer(); - renderer.setClearColor( 0xf0f0f0 ); renderer.setPixelRatio( window.devicePixelRatio ); renderer.setSize( window.innerWidth, window.innerHeight ); container.appendChild( renderer.domElement ); diff --git a/examples/canvas_morphtargets_horse.html b/examples/canvas_morphtargets_horse.html index 37783773e9ceb1..c25afe0dd3d7bd 100644 --- a/examples/canvas_morphtargets_horse.html +++ b/examples/canvas_morphtargets_horse.html @@ -41,7 +41,7 @@ info.style.top = '10px'; info.style.width = '100%'; info.style.textAlign = 'center'; - info.innerHTML = 'three.js canvas - morph targets - horse. model by mirada from rome'; + info.innerHTML = 'three.js canvas - morph targets - horse. model by mirada from rome'; container.appendChild( info ); // @@ -51,6 +51,7 @@ camera.target = new THREE.Vector3( 0, 150, 0 ); scene = new THREE.Scene(); + scene.background = new THREE.Color( 0xf0f0f0 ); // @@ -85,7 +86,6 @@ // renderer = new THREE.CanvasRenderer(); - renderer.setClearColor( 0xf0f0f0 ); renderer.setPixelRatio( window.devicePixelRatio ); renderer.setSize( window.innerWidth, window.innerHeight ); container.appendChild(renderer.domElement); diff --git a/examples/canvas_particles_sprites.html b/examples/canvas_particles_sprites.html index d882febb22e6aa..e781ab0e178c4f 100644 --- a/examples/canvas_particles_sprites.html +++ b/examples/canvas_particles_sprites.html @@ -47,6 +47,7 @@ camera.position.z = 1000; scene = new THREE.Scene(); + scene.background = new THREE.Color( 0x000040 ); var material = new THREE.SpriteMaterial( { map: new THREE.CanvasTexture( generateSprite() ), @@ -63,7 +64,6 @@ } renderer = new THREE.CanvasRenderer(); - renderer.setClearColor( 0x000040 ); renderer.setPixelRatio( window.devicePixelRatio ); renderer.setSize( window.innerWidth, window.innerHeight ); container.appendChild( renderer.domElement ); diff --git a/examples/canvas_performance.html b/examples/canvas_performance.html index 07eb8142af288d..01eeae7856ae98 100644 --- a/examples/canvas_performance.html +++ b/examples/canvas_performance.html @@ -39,6 +39,7 @@ document.body.appendChild( container ); scene = new THREE.Scene(); + scene.background = new THREE.Color( 0xf0f0f0 ); camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 10000 ); camera.position.set( 0, 1000, 1000 ); @@ -79,7 +80,6 @@ scene.add( light ); renderer = new THREE.CanvasRenderer(); - renderer.setClearColor( 0xf0f0f0 ); renderer.setPixelRatio( window.devicePixelRatio ); renderer.setSize( window.innerWidth, window.innerHeight ); container.appendChild( renderer.domElement ); diff --git a/examples/canvas_sandbox.html b/examples/canvas_sandbox.html index 23c1020611ee01..fa76d181305125 100644 --- a/examples/canvas_sandbox.html +++ b/examples/canvas_sandbox.html @@ -44,6 +44,7 @@ var controls = new THREE.OrbitControls( camera ); scene = new THREE.Scene(); + scene.background = new THREE.Color( 0xf0f0f0 ); // Grid @@ -81,7 +82,6 @@ } renderer = new THREE.CanvasRenderer(); - renderer.setClearColor( 0xf0f0f0 ); renderer.setPixelRatio( window.devicePixelRatio ); renderer.setSize( window.innerWidth, window.innerHeight ); container.appendChild( renderer.domElement ); diff --git a/examples/css3d_molecules.html b/examples/css3d_molecules.html index 98f23519b4d090..8d5833ac1bc6d3 100644 --- a/examples/css3d_molecules.html +++ b/examples/css3d_molecules.html @@ -11,14 +11,7 @@ body { background-color: #050505; - - background: rgb(43,45,48); /* Old browsers */ - background: -moz-radial-gradient(center, ellipse cover, rgba(43,45,48,1) 0%, rgba(0,0,0,1) 100%); /* FF3.6+ */ - background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%,rgba(43,45,48,1)), color-stop(100%,rgba(0,0,0,1))); /* Chrome,Safari4+ */ - background: -webkit-radial-gradient(center, ellipse cover, rgba(43,45,48,1) 0%,rgba(0,0,0,1) 100%); /* Chrome10+,Safari5.1+ */ - background: -o-radial-gradient(center, ellipse cover, rgba(43,45,48,1) 0%,rgba(0,0,0,1) 100%); /* Opera 12+ */ - background: -ms-radial-gradient(center, ellipse cover, rgba(43,45,48,1) 0%,rgba(0,0,0,1) 100%); /* IE10+ */ - background: radial-gradient(ellipse at center, rgba(43,45,48,1) 0%,rgba(0,0,0,1) 100%); /* W3C */ + background: radial-gradient(ellipse at center, rgba(43,45,48,1) 0%,rgba(0,0,0,1) 100%); margin: 0; font-family: Arial; @@ -92,7 +85,7 @@
      -
      three.js css3d - molecules
      +
      three.js css3d - molecules
      @@ -286,27 +279,18 @@ // - function colorify( ctx, width, height, color, a ) { + function colorify( ctx, width, height, color ) { - var r = color.r; - var g = color.g; - var b = color.b; + var r = color.r, g = color.g, b = color.b; var imageData = ctx.getImageData( 0, 0, width, height ); var data = imageData.data; - for ( var y = 0; y < height; y ++ ) { - - for ( var x = 0; x < width; x ++ ) { - - var index = ( y * width + x ) * 4; + for ( var i = 0, l = data.length; i < l; i += 4 ) { - data[ index ] *= r; - data[ index + 1 ] *= g; - data[ index + 2 ] *= b; - data[ index + 3 ] *= a; - - } + data[ i + 0 ] *= r; + data[ i + 1 ] *= g; + data[ i + 2 ] *= b; } @@ -344,13 +328,17 @@ objects = []; - loader.load( url, function ( geometry, geometryBonds ) { + loader.load( url, function ( pdb ) { + + var geometryAtoms = pdb.geometryAtoms; + var geometryBonds = pdb.geometryBonds; + var json = pdb.json; - var offset = geometry.center(); + var offset = geometryAtoms.center(); geometryBonds.translate( offset.x, offset.y, offset.z ); - var positions = geometry.getAttribute( 'position' ); - var colors = geometry.getAttribute( 'color' ); + var positions = geometryAtoms.getAttribute( 'position' ); + var colors = geometryAtoms.getAttribute( 'color' ); var position = new THREE.Vector3(); var color = new THREE.Color(); @@ -365,14 +353,15 @@ color.g = colors.getY( i ); color.b = colors.getZ( i ); - var element = geometry.elements[ i ]; + var atom = json.atoms[ i ]; + var element = atom[ 4 ]; if ( ! colorSpriteMap[ element ] ) { var canvas = imageToCanvas( baseSprite ); var context = canvas.getContext( '2d' ); - colorify( context, canvas.width, canvas.height, color, 1 ); + colorify( context, canvas.width, canvas.height, color ); var dataUrl = canvas.toDataURL(); diff --git a/examples/css3d_panorama.html b/examples/css3d_panorama.html index 98ced077c77b24..68edbebd17bf34 100644 --- a/examples/css3d_panorama.html +++ b/examples/css3d_panorama.html @@ -33,7 +33,7 @@ -
      three.js css3d - panorama demo. cubemap by Humus.
      +
      three.js css3d - panorama demo. cubemap by Humus.
      -
      three.js css3d - panorama - decideorientation. cubemap by Humus.
      +
      three.js css3d - panorama - decideorientation. cubemap by Humus.
      -
      three.js css3d - periodic table. info.
      +
      three.js css3d - periodic table. info.