\n\t\t\t);\n\n\t\t\tvar supportedObjectNames = [ 'material', 'materials', 'bones' ];\n\n\t\t\treturn function parseTrackName( trackName ) {\n\n\t\t\t\tvar matches = trackRe.exec( trackName );\n\n\t\t\t\tif ( ! matches ) {\n\n\t\t\t\t\tthrow new Error( 'PropertyBinding: Cannot parse trackName: ' + trackName );\n\n\t\t\t\t}\n\n\t\t\t\tvar results = {\n\t\t\t\t\t\u002F\u002F directoryName: matches[ 1 ], \u002F\u002F (tschw) currently unused\n\t\t\t\t\tnodeName: matches[ 2 ],\n\t\t\t\t\tobjectName: matches[ 3 ],\n\t\t\t\t\tobjectIndex: matches[ 4 ],\n\t\t\t\t\tpropertyName: matches[ 5 ], \u002F\u002F required\n\t\t\t\t\tpropertyIndex: matches[ 6 ]\n\t\t\t\t};\n\n\t\t\t\tvar lastDot = results.nodeName && results.nodeName.lastIndexOf( '.' );\n\n\t\t\t\tif ( lastDot !== undefined && lastDot !== - 1 ) {\n\n\t\t\t\t\tvar objectName = results.nodeName.substring( lastDot + 1 );\n\n\t\t\t\t\t\u002F\u002F Object names must be checked against a whitelist. Otherwise, there\n\t\t\t\t\t\u002F\u002F is no way to parse 'foo.bar.baz': 'baz' must be a property, but\n\t\t\t\t\t\u002F\u002F 'bar' could be the objectName, or part of a nodeName (which can\n\t\t\t\t\t\u002F\u002F include '.' characters).\n\t\t\t\t\tif ( supportedObjectNames.indexOf( objectName ) !== - 1 ) {\n\n\t\t\t\t\t\tresults.nodeName = results.nodeName.substring( 0, lastDot );\n\t\t\t\t\t\tresults.objectName = objectName;\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\tif ( results.propertyName === null || results.propertyName.length === 0 ) {\n\n\t\t\t\t\tthrow new Error( 'PropertyBinding: can not parse propertyName from trackName: ' + trackName );\n\n\t\t\t\t}\n\n\t\t\t\treturn results;\n\n\t\t\t};\n\n\t\t}(),\n\n\t\tfindNode: function ( root, nodeName ) {\n\n\t\t\tif ( ! nodeName || nodeName === \"\" || nodeName === \"root\" || nodeName === \".\" || nodeName === - 1 || nodeName === root.name || nodeName === root.uuid ) {\n\n\t\t\t\treturn root;\n\n\t\t\t}\n\n\t\t\t\u002F\u002F search into skeleton bones.\n\t\t\tif ( root.skeleton ) {\n\n\t\t\t\tvar bone = root.skeleton.getBoneByName( nodeName );\n\n\t\t\t\tif ( bone !== undefined ) {\n\n\t\t\t\t\treturn bone;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t\u002F\u002F search into node subtree.\n\t\t\tif ( root.children ) {\n\n\t\t\t\tvar searchNodeSubtree = function ( children ) {\n\n\t\t\t\t\tfor ( var i = 0; i \u003C children.length; i ++ ) {\n\n\t\t\t\t\t\tvar childNode = children[ i ];\n\n\t\t\t\t\t\tif ( childNode.name === nodeName || childNode.uuid === nodeName ) {\n\n\t\t\t\t\t\t\treturn childNode;\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tvar result = searchNodeSubtree( childNode.children );\n\n\t\t\t\t\t\tif ( result ) return result;\n\n\t\t\t\t\t}\n\n\t\t\t\t\treturn null;\n\n\t\t\t\t};\n\n\t\t\t\tvar subTreeNode = searchNodeSubtree( root.children );\n\n\t\t\t\tif ( subTreeNode ) {\n\n\t\t\t\t\treturn subTreeNode;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn null;\n\n\t\t}\n\n\t} );\n\n\tObject.assign( PropertyBinding.prototype, { \u002F\u002F prototype, continued\n\n\t\t\u002F\u002F these are used to \"bind\" a nonexistent property\n\t\t_getValue_unavailable: function () {},\n\t\t_setValue_unavailable: function () {},\n\n\t\tBindingType: {\n\t\t\tDirect: 0,\n\t\t\tEntireArray: 1,\n\t\t\tArrayElement: 2,\n\t\t\tHasFromToArray: 3\n\t\t},\n\n\t\tVersioning: {\n\t\t\tNone: 0,\n\t\t\tNeedsUpdate: 1,\n\t\t\tMatrixWorldNeedsUpdate: 2\n\t\t},\n\n\t\tGetterByBindingType: [\n\n\t\t\tfunction getValue_direct( buffer, offset ) {\n\n\t\t\t\tbuffer[ offset ] = this.node[ this.propertyName ];\n\n\t\t\t},\n\n\t\t\tfunction getValue_array( buffer, offset ) {\n\n\t\t\t\tvar source = this.resolvedProperty;\n\n\t\t\t\tfor ( var i = 0, n = source.length; i !== n; ++ i ) {\n\n\t\t\t\t\tbuffer[ offset ++ ] = source[ i ];\n\n\t\t\t\t}\n\n\t\t\t},\n\n\t\t\tfunction getValue_arrayElement( buffer, offset ) {\n\n\t\t\t\tbuffer[ offset ] = this.resolvedProperty[ this.propertyIndex ];\n\n\t\t\t},\n\n\t\t\tfunction getValue_toArray( buffer, offset ) {\n\n\t\t\t\tthis.resolvedProperty.toArray( buffer, offset );\n\n\t\t\t}\n\n\t\t],\n\n\t\tSetterByBindingTypeAndVersioning: [\n\n\t\t\t[\n\t\t\t\t\u002F\u002F Direct\n\n\t\t\t\tfunction setValue_direct( buffer, offset ) {\n\n\t\t\t\t\tthis.targetObject[ this.propertyName ] = buffer[ offset ];\n\n\t\t\t\t},\n\n\t\t\t\tfunction setValue_direct_setNeedsUpdate( buffer, offset ) {\n\n\t\t\t\t\tthis.targetObject[ this.propertyName ] = buffer[ offset ];\n\t\t\t\t\tthis.targetObject.needsUpdate = true;\n\n\t\t\t\t},\n\n\t\t\t\tfunction setValue_direct_setMatrixWorldNeedsUpdate( buffer, offset ) {\n\n\t\t\t\t\tthis.targetObject[ this.propertyName ] = buffer[ offset ];\n\t\t\t\t\tthis.targetObject.matrixWorldNeedsUpdate = true;\n\n\t\t\t\t}\n\n\t\t\t], [\n\n\t\t\t\t\u002F\u002F EntireArray\n\n\t\t\t\tfunction setValue_array( buffer, offset ) {\n\n\t\t\t\t\tvar dest = this.resolvedProperty;\n\n\t\t\t\t\tfor ( var i = 0, n = dest.length; i !== n; ++ i ) {\n\n\t\t\t\t\t\tdest[ i ] = buffer[ offset ++ ];\n\n\t\t\t\t\t}\n\n\t\t\t\t},\n\n\t\t\t\tfunction setValue_array_setNeedsUpdate( buffer, offset ) {\n\n\t\t\t\t\tvar dest = this.resolvedProperty;\n\n\t\t\t\t\tfor ( var i = 0, n = dest.length; i !== n; ++ i ) {\n\n\t\t\t\t\t\tdest[ i ] = buffer[ offset ++ ];\n\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.targetObject.needsUpdate = true;\n\n\t\t\t\t},\n\n\t\t\t\tfunction setValue_array_setMatrixWorldNeedsUpdate( buffer, offset ) {\n\n\t\t\t\t\tvar dest = this.resolvedProperty;\n\n\t\t\t\t\tfor ( var i = 0, n = dest.length; i !== n; ++ i ) {\n\n\t\t\t\t\t\tdest[ i ] = buffer[ offset ++ ];\n\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.targetObject.matrixWorldNeedsUpdate = true;\n\n\t\t\t\t}\n\n\t\t\t], [\n\n\t\t\t\t\u002F\u002F ArrayElement\n\n\t\t\t\tfunction setValue_arrayElement( buffer, offset ) {\n\n\t\t\t\t\tthis.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];\n\n\t\t\t\t},\n\n\t\t\t\tfunction setValue_arrayElement_setNeedsUpdate( buffer, offset ) {\n\n\t\t\t\t\tthis.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];\n\t\t\t\t\tthis.targetObject.needsUpdate = true;\n\n\t\t\t\t},\n\n\t\t\t\tfunction setValue_arrayElement_setMatrixWorldNeedsUpdate( buffer, offset ) {\n\n\t\t\t\t\tthis.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];\n\t\t\t\t\tthis.targetObject.matrixWorldNeedsUpdate = true;\n\n\t\t\t\t}\n\n\t\t\t], [\n\n\t\t\t\t\u002F\u002F HasToFromArray\n\n\t\t\t\tfunction setValue_fromArray( buffer, offset ) {\n\n\t\t\t\t\tthis.resolvedProperty.fromArray( buffer, offset );\n\n\t\t\t\t},\n\n\t\t\t\tfunction setValue_fromArray_setNeedsUpdate( buffer, offset ) {\n\n\t\t\t\t\tthis.resolvedProperty.fromArray( buffer, offset );\n\t\t\t\t\tthis.targetObject.needsUpdate = true;\n\n\t\t\t\t},\n\n\t\t\t\tfunction setValue_fromArray_setMatrixWorldNeedsUpdate( buffer, offset ) {\n\n\t\t\t\t\tthis.resolvedProperty.fromArray( buffer, offset );\n\t\t\t\t\tthis.targetObject.matrixWorldNeedsUpdate = true;\n\n\t\t\t\t}\n\n\t\t\t]\n\n\t\t],\n\n\t\tgetValue: function getValue_unbound( targetArray, offset ) {\n\n\t\t\tthis.bind();\n\t\t\tthis.getValue( targetArray, offset );\n\n\t\t\t\u002F\u002F Note: This class uses a State pattern on a per-method basis:\n\t\t\t\u002F\u002F 'bind' sets 'this.getValue' \u002F 'setValue' and shadows the\n\t\t\t\u002F\u002F prototype version of these methods with one that represents\n\t\t\t\u002F\u002F the bound state. When the property is not found, the methods\n\t\t\t\u002F\u002F become no-ops.\n\n\t\t},\n\n\t\tsetValue: function getValue_unbound( sourceArray, offset ) {\n\n\t\t\tthis.bind();\n\t\t\tthis.setValue( sourceArray, offset );\n\n\t\t},\n\n\t\t\u002F\u002F create getter \u002F setter pair for a property in the scene graph\n\t\tbind: function () {\n\n\t\t\tvar targetObject = this.node,\n\t\t\t\tparsedPath = this.parsedPath,\n\n\t\t\t\tobjectName = parsedPath.objectName,\n\t\t\t\tpropertyName = parsedPath.propertyName,\n\t\t\t\tpropertyIndex = parsedPath.propertyIndex;\n\n\t\t\tif ( ! targetObject ) {\n\n\t\t\t\ttargetObject = PropertyBinding.findNode( this.rootNode, parsedPath.nodeName ) || this.rootNode;\n\n\t\t\t\tthis.node = targetObject;\n\n\t\t\t}\n\n\t\t\t\u002F\u002F set fail state so we can just 'return' on error\n\t\t\tthis.getValue = this._getValue_unavailable;\n\t\t\tthis.setValue = this._setValue_unavailable;\n\n\t\t\t\u002F\u002F ensure there is a value node\n\t\t\tif ( ! targetObject ) {\n\n\t\t\t\tconsole.error( 'THREE.PropertyBinding: Trying to update node for track: ' + this.path + ' but it wasn\\'t found.' );\n\t\t\t\treturn;\n\n\t\t\t}\n\n\t\t\tif ( objectName ) {\n\n\t\t\t\tvar objectIndex = parsedPath.objectIndex;\n\n\t\t\t\t\u002F\u002F special cases were we need to reach deeper into the hierarchy to get the face materials....\n\t\t\t\tswitch ( objectName ) {\n\n\t\t\t\t\tcase 'materials':\n\n\t\t\t\t\t\tif ( ! targetObject.material ) {\n\n\t\t\t\t\t\t\tconsole.error( 'THREE.PropertyBinding: Can not bind to material as node does not have a material.', this );\n\t\t\t\t\t\t\treturn;\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif ( ! targetObject.material.materials ) {\n\n\t\t\t\t\t\t\tconsole.error( 'THREE.PropertyBinding: Can not bind to material.materials as node.material does not have a materials array.', this );\n\t\t\t\t\t\t\treturn;\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\ttargetObject = targetObject.material.materials;\n\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'bones':\n\n\t\t\t\t\t\tif ( ! targetObject.skeleton ) {\n\n\t\t\t\t\t\t\tconsole.error( 'THREE.PropertyBinding: Can not bind to bones as node does not have a skeleton.', this );\n\t\t\t\t\t\t\treturn;\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\u002F\u002F potential future optimization: skip this if propertyIndex is already an integer\n\t\t\t\t\t\t\u002F\u002F and convert the integer string to a true integer.\n\n\t\t\t\t\t\ttargetObject = targetObject.skeleton.bones;\n\n\t\t\t\t\t\t\u002F\u002F support resolving morphTarget names into indices.\n\t\t\t\t\t\tfor ( var i = 0; i \u003C targetObject.length; i ++ ) {\n\n\t\t\t\t\t\t\tif ( targetObject[ i ].name === objectIndex ) {\n\n\t\t\t\t\t\t\t\tobjectIndex = i;\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\n\t\t\t\t\t\tif ( targetObject[ objectName ] === undefined ) {\n\n\t\t\t\t\t\t\tconsole.error( 'THREE.PropertyBinding: Can not bind to objectName of node undefined.', this );\n\t\t\t\t\t\t\treturn;\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\ttargetObject = targetObject[ objectName ];\n\n\t\t\t\t}\n\n\n\t\t\t\tif ( objectIndex !== undefined ) {\n\n\t\t\t\t\tif ( targetObject[ objectIndex ] === undefined ) {\n\n\t\t\t\t\t\tconsole.error( 'THREE.PropertyBinding: Trying to bind to objectIndex of objectName, but is undefined.', this, targetObject );\n\t\t\t\t\t\treturn;\n\n\t\t\t\t\t}\n\n\t\t\t\t\ttargetObject = targetObject[ objectIndex ];\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t\u002F\u002F resolve property\n\t\t\tvar nodeProperty = targetObject[ propertyName ];\n\n\t\t\tif ( nodeProperty === undefined ) {\n\n\t\t\t\tvar nodeName = parsedPath.nodeName;\n\n\t\t\t\tconsole.error( 'THREE.PropertyBinding: Trying to update property for track: ' + nodeName +\n\t\t\t\t\t'.' + propertyName + ' but it wasn\\'t found.', targetObject );\n\t\t\t\treturn;\n\n\t\t\t}\n\n\t\t\t\u002F\u002F determine versioning scheme\n\t\t\tvar versioning = this.Versioning.None;\n\n\t\t\tthis.targetObject = targetObject;\n\n\t\t\tif ( targetObject.needsUpdate !== undefined ) { \u002F\u002F material\n\n\t\t\t\tversioning = this.Versioning.NeedsUpdate;\n\n\t\t\t} else if ( targetObject.matrixWorldNeedsUpdate !== undefined ) { \u002F\u002F node transform\n\n\t\t\t\tversioning = this.Versioning.MatrixWorldNeedsUpdate;\n\n\t\t\t}\n\n\t\t\t\u002F\u002F determine how the property gets bound\n\t\t\tvar bindingType = this.BindingType.Direct;\n\n\t\t\tif ( propertyIndex !== undefined ) {\n\n\t\t\t\t\u002F\u002F access a sub element of the property array (only primitives are supported right now)\n\n\t\t\t\tif ( propertyName === \"morphTargetInfluences\" ) {\n\n\t\t\t\t\t\u002F\u002F potential optimization, skip this if propertyIndex is already an integer, and convert the integer string to a true integer.\n\n\t\t\t\t\t\u002F\u002F support resolving morphTarget names into indices.\n\t\t\t\t\tif ( ! targetObject.geometry ) {\n\n\t\t\t\t\t\tconsole.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.', this );\n\t\t\t\t\t\treturn;\n\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( targetObject.geometry.isBufferGeometry ) {\n\n\t\t\t\t\t\tif ( ! targetObject.geometry.morphAttributes ) {\n\n\t\t\t\t\t\t\tconsole.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.morphAttributes.', this );\n\t\t\t\t\t\t\treturn;\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tfor ( var i = 0; i \u003C this.node.geometry.morphAttributes.position.length; i ++ ) {\n\n\t\t\t\t\t\t\tif ( targetObject.geometry.morphAttributes.position[ i ].name === propertyIndex ) {\n\n\t\t\t\t\t\t\t\tpropertyIndex = i;\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t}\n\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\tif ( ! targetObject.geometry.morphTargets ) {\n\n\t\t\t\t\t\t\tconsole.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.morphTargets.', this );\n\t\t\t\t\t\t\treturn;\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tfor ( var i = 0; i \u003C this.node.geometry.morphTargets.length; i ++ ) {\n\n\t\t\t\t\t\t\tif ( targetObject.geometry.morphTargets[ i ].name === propertyIndex ) {\n\n\t\t\t\t\t\t\t\tpropertyIndex = i;\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\tbindingType = this.BindingType.ArrayElement;\n\n\t\t\t\tthis.resolvedProperty = nodeProperty;\n\t\t\t\tthis.propertyIndex = propertyIndex;\n\n\t\t\t} else if ( nodeProperty.fromArray !== undefined && nodeProperty.toArray !== undefined ) {\n\n\t\t\t\t\u002F\u002F must use copy for Object3D.Euler\u002FQuaternion\n\n\t\t\t\tbindingType = this.BindingType.HasFromToArray;\n\n\t\t\t\tthis.resolvedProperty = nodeProperty;\n\n\t\t\t} else if ( Array.isArray( nodeProperty ) ) {\n\n\t\t\t\tbindingType = this.BindingType.EntireArray;\n\n\t\t\t\tthis.resolvedProperty = nodeProperty;\n\n\t\t\t} else {\n\n\t\t\t\tthis.propertyName = propertyName;\n\n\t\t\t}\n\n\t\t\t\u002F\u002F select getter \u002F setter\n\t\t\tthis.getValue = this.GetterByBindingType[ bindingType ];\n\t\t\tthis.setValue = this.SetterByBindingTypeAndVersioning[ bindingType ][ versioning ];\n\n\t\t},\n\n\t\tunbind: function () {\n\n\t\t\tthis.node = null;\n\n\t\t\t\u002F\u002F back to the prototype version of getValue \u002F setValue\n\t\t\t\u002F\u002F note: avoiding to mutate the shape of 'this' via 'delete'\n\t\t\tthis.getValue = this._getValue_unbound;\n\t\t\tthis.setValue = this._setValue_unbound;\n\n\t\t}\n\n\t} );\n\n\t\u002F\u002F!\\ DECLARE ALIAS AFTER assign prototype !\n\tObject.assign( PropertyBinding.prototype, {\n\n\t\t\u002F\u002F initial state of these methods that calls 'bind'\n\t\t_getValue_unbound: PropertyBinding.prototype.getValue,\n\t\t_setValue_unbound: PropertyBinding.prototype.setValue,\n\n\t} );\n\n\t\u002F**\n\t *\n\t * A group of objects that receives a shared animation state.\n\t *\n\t * Usage:\n\t *\n\t * - Add objects you would otherwise pass as 'root' to the\n\t * constructor or the .clipAction method of AnimationMixer.\n\t *\n\t * - Instead pass this object as 'root'.\n\t *\n\t * - You can also add and remove objects later when the mixer\n\t * is running.\n\t *\n\t * Note:\n\t *\n\t * Objects of this class appear as one object to the mixer,\n\t * so cache control of the individual objects must be done\n\t * on the group.\n\t *\n\t * Limitation:\n\t *\n\t * - The animated properties must be compatible among the\n\t * all objects in the group.\n\t *\n\t * - A single property can either be controlled through a\n\t * target group or directly, but not both.\n\t *\n\t * @author tschw\n\t *\u002F\n\n\tfunction AnimationObjectGroup() {\n\n\t\tthis.uuid = _Math.generateUUID();\n\n\t\t\u002F\u002F cached objects followed by the active ones\n\t\tthis._objects = Array.prototype.slice.call( arguments );\n\n\t\tthis.nCachedObjects_ = 0; \u002F\u002F threshold\n\t\t\u002F\u002F note: read by PropertyBinding.Composite\n\n\t\tvar indices = {};\n\t\tthis._indicesByUUID = indices; \u002F\u002F for bookkeeping\n\n\t\tfor ( var i = 0, n = arguments.length; i !== n; ++ i ) {\n\n\t\t\tindices[ arguments[ i ].uuid ] = i;\n\n\t\t}\n\n\t\tthis._paths = []; \u002F\u002F inside: string\n\t\tthis._parsedPaths = []; \u002F\u002F inside: { we don't care, here }\n\t\tthis._bindings = []; \u002F\u002F inside: Array\u003C PropertyBinding \u003E\n\t\tthis._bindingsIndicesByPath = {}; \u002F\u002F inside: indices in these arrays\n\n\t\tvar scope = this;\n\n\t\tthis.stats = {\n\n\t\t\tobjects: {\n\t\t\t\tget total() {\n\n\t\t\t\t\treturn scope._objects.length;\n\n\t\t\t\t},\n\t\t\t\tget inUse() {\n\n\t\t\t\t\treturn this.total - scope.nCachedObjects_;\n\n\t\t\t\t}\n\t\t\t},\n\t\t\tget bindingsPerObject() {\n\n\t\t\t\treturn scope._bindings.length;\n\n\t\t\t}\n\n\t\t};\n\n\t}\n\n\tObject.assign( AnimationObjectGroup.prototype, {\n\n\t\tisAnimationObjectGroup: true,\n\n\t\tadd: function () {\n\n\t\t\tvar objects = this._objects,\n\t\t\t\tnObjects = objects.length,\n\t\t\t\tnCachedObjects = this.nCachedObjects_,\n\t\t\t\tindicesByUUID = this._indicesByUUID,\n\t\t\t\tpaths = this._paths,\n\t\t\t\tparsedPaths = this._parsedPaths,\n\t\t\t\tbindings = this._bindings,\n\t\t\t\tnBindings = bindings.length,\n\t\t\t\tknownObject = undefined;\n\n\t\t\tfor ( var i = 0, n = arguments.length; i !== n; ++ i ) {\n\n\t\t\t\tvar object = arguments[ i ],\n\t\t\t\t\tuuid = object.uuid,\n\t\t\t\t\tindex = indicesByUUID[ uuid ];\n\n\t\t\t\tif ( index === undefined ) {\n\n\t\t\t\t\t\u002F\u002F unknown object -\u003E add it to the ACTIVE region\n\n\t\t\t\t\tindex = nObjects ++;\n\t\t\t\t\tindicesByUUID[ uuid ] = index;\n\t\t\t\t\tobjects.push( object );\n\n\t\t\t\t\t\u002F\u002F accounting is done, now do the same for all bindings\n\n\t\t\t\t\tfor ( var j = 0, m = nBindings; j !== m; ++ j ) {\n\n\t\t\t\t\t\tbindings[ j ].push( new PropertyBinding( object, paths[ j ], parsedPaths[ j ] ) );\n\n\t\t\t\t\t}\n\n\t\t\t\t} else if ( index \u003C nCachedObjects ) {\n\n\t\t\t\t\tknownObject = objects[ index ];\n\n\t\t\t\t\t\u002F\u002F move existing object to the ACTIVE region\n\n\t\t\t\t\tvar firstActiveIndex = -- nCachedObjects,\n\t\t\t\t\t\tlastCachedObject = objects[ firstActiveIndex ];\n\n\t\t\t\t\tindicesByUUID[ lastCachedObject.uuid ] = index;\n\t\t\t\t\tobjects[ index ] = lastCachedObject;\n\n\t\t\t\t\tindicesByUUID[ uuid ] = firstActiveIndex;\n\t\t\t\t\tobjects[ firstActiveIndex ] = object;\n\n\t\t\t\t\t\u002F\u002F accounting is done, now do the same for all bindings\n\n\t\t\t\t\tfor ( var j = 0, m = nBindings; j !== m; ++ j ) {\n\n\t\t\t\t\t\tvar bindingsForPath = bindings[ j ],\n\t\t\t\t\t\t\tlastCached = bindingsForPath[ firstActiveIndex ],\n\t\t\t\t\t\t\tbinding = bindingsForPath[ index ];\n\n\t\t\t\t\t\tbindingsForPath[ index ] = lastCached;\n\n\t\t\t\t\t\tif ( binding === undefined ) {\n\n\t\t\t\t\t\t\t\u002F\u002F since we do not bother to create new bindings\n\t\t\t\t\t\t\t\u002F\u002F for objects that are cached, the binding may\n\t\t\t\t\t\t\t\u002F\u002F or may not exist\n\n\t\t\t\t\t\t\tbinding = new PropertyBinding( object, paths[ j ], parsedPaths[ j ] );\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbindingsForPath[ firstActiveIndex ] = binding;\n\n\t\t\t\t\t}\n\n\t\t\t\t} else if ( objects[ index ] !== knownObject ) {\n\n\t\t\t\t\tconsole.error( 'THREE.AnimationObjectGroup: Different objects with the same UUID ' +\n\t\t\t\t\t\t'detected. Clean the caches or recreate your infrastructure when reloading scenes.' );\n\n\t\t\t\t} \u002F\u002F else the object is already where we want it to be\n\n\t\t\t} \u002F\u002F for arguments\n\n\t\t\tthis.nCachedObjects_ = nCachedObjects;\n\n\t\t},\n\n\t\tremove: function () {\n\n\t\t\tvar objects = this._objects,\n\t\t\t\tnCachedObjects = this.nCachedObjects_,\n\t\t\t\tindicesByUUID = this._indicesByUUID,\n\t\t\t\tbindings = this._bindings,\n\t\t\t\tnBindings = bindings.length;\n\n\t\t\tfor ( var i = 0, n = arguments.length; i !== n; ++ i ) {\n\n\t\t\t\tvar object = arguments[ i ],\n\t\t\t\t\tuuid = object.uuid,\n\t\t\t\t\tindex = indicesByUUID[ uuid ];\n\n\t\t\t\tif ( index !== undefined && index \u003E= nCachedObjects ) {\n\n\t\t\t\t\t\u002F\u002F move existing object into the CACHED region\n\n\t\t\t\t\tvar lastCachedIndex = nCachedObjects ++,\n\t\t\t\t\t\tfirstActiveObject = objects[ lastCachedIndex ];\n\n\t\t\t\t\tindicesByUUID[ firstActiveObject.uuid ] = index;\n\t\t\t\t\tobjects[ index ] = firstActiveObject;\n\n\t\t\t\t\tindicesByUUID[ uuid ] = lastCachedIndex;\n\t\t\t\t\tobjects[ lastCachedIndex ] = object;\n\n\t\t\t\t\t\u002F\u002F accounting is done, now do the same for all bindings\n\n\t\t\t\t\tfor ( var j = 0, m = nBindings; j !== m; ++ j ) {\n\n\t\t\t\t\t\tvar bindingsForPath = bindings[ j ],\n\t\t\t\t\t\t\tfirstActive = bindingsForPath[ lastCachedIndex ],\n\t\t\t\t\t\t\tbinding = bindingsForPath[ index ];\n\n\t\t\t\t\t\tbindingsForPath[ index ] = firstActive;\n\t\t\t\t\t\tbindingsForPath[ lastCachedIndex ] = binding;\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t} \u002F\u002F for arguments\n\n\t\t\tthis.nCachedObjects_ = nCachedObjects;\n\n\t\t},\n\n\t\t\u002F\u002F remove & forget\n\t\tuncache: function () {\n\n\t\t\tvar objects = this._objects,\n\t\t\t\tnObjects = objects.length,\n\t\t\t\tnCachedObjects = this.nCachedObjects_,\n\t\t\t\tindicesByUUID = this._indicesByUUID,\n\t\t\t\tbindings = this._bindings,\n\t\t\t\tnBindings = bindings.length;\n\n\t\t\tfor ( var i = 0, n = arguments.length; i !== n; ++ i ) {\n\n\t\t\t\tvar object = arguments[ i ],\n\t\t\t\t\tuuid = object.uuid,\n\t\t\t\t\tindex = indicesByUUID[ uuid ];\n\n\t\t\t\tif ( index !== undefined ) {\n\n\t\t\t\t\tdelete indicesByUUID[ uuid ];\n\n\t\t\t\t\tif ( index \u003C nCachedObjects ) {\n\n\t\t\t\t\t\t\u002F\u002F object is cached, shrink the CACHED region\n\n\t\t\t\t\t\tvar firstActiveIndex = -- nCachedObjects,\n\t\t\t\t\t\t\tlastCachedObject = objects[ firstActiveIndex ],\n\t\t\t\t\t\t\tlastIndex = -- nObjects,\n\t\t\t\t\t\t\tlastObject = objects[ lastIndex ];\n\n\t\t\t\t\t\t\u002F\u002F last cached object takes this object's place\n\t\t\t\t\t\tindicesByUUID[ lastCachedObject.uuid ] = index;\n\t\t\t\t\t\tobjects[ index ] = lastCachedObject;\n\n\t\t\t\t\t\t\u002F\u002F last object goes to the activated slot and pop\n\t\t\t\t\t\tindicesByUUID[ lastObject.uuid ] = firstActiveIndex;\n\t\t\t\t\t\tobjects[ firstActiveIndex ] = lastObject;\n\t\t\t\t\t\tobjects.pop();\n\n\t\t\t\t\t\t\u002F\u002F accounting is done, now do the same for all bindings\n\n\t\t\t\t\t\tfor ( var j = 0, m = nBindings; j !== m; ++ j ) {\n\n\t\t\t\t\t\t\tvar bindingsForPath = bindings[ j ],\n\t\t\t\t\t\t\t\tlastCached = bindingsForPath[ firstActiveIndex ],\n\t\t\t\t\t\t\t\tlast = bindingsForPath[ lastIndex ];\n\n\t\t\t\t\t\t\tbindingsForPath[ index ] = lastCached;\n\t\t\t\t\t\t\tbindingsForPath[ firstActiveIndex ] = last;\n\t\t\t\t\t\t\tbindingsForPath.pop();\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\u002F\u002F object is active, just swap with the last and pop\n\n\t\t\t\t\t\tvar lastIndex = -- nObjects,\n\t\t\t\t\t\t\tlastObject = objects[ lastIndex ];\n\n\t\t\t\t\t\tindicesByUUID[ lastObject.uuid ] = index;\n\t\t\t\t\t\tobjects[ index ] = lastObject;\n\t\t\t\t\t\tobjects.pop();\n\n\t\t\t\t\t\t\u002F\u002F accounting is done, now do the same for all bindings\n\n\t\t\t\t\t\tfor ( var j = 0, m = nBindings; j !== m; ++ j ) {\n\n\t\t\t\t\t\t\tvar bindingsForPath = bindings[ j ];\n\n\t\t\t\t\t\t\tbindingsForPath[ index ] = bindingsForPath[ lastIndex ];\n\t\t\t\t\t\t\tbindingsForPath.pop();\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} \u002F\u002F cached or active\n\n\t\t\t\t} \u002F\u002F if object is known\n\n\t\t\t} \u002F\u002F for arguments\n\n\t\t\tthis.nCachedObjects_ = nCachedObjects;\n\n\t\t},\n\n\t\t\u002F\u002F Internal interface used by befriended PropertyBinding.Composite:\n\n\t\tsubscribe_: function ( path, parsedPath ) {\n\n\t\t\t\u002F\u002F returns an array of bindings for the given path that is changed\n\t\t\t\u002F\u002F according to the contained objects in the group\n\n\t\t\tvar indicesByPath = this._bindingsIndicesByPath,\n\t\t\t\tindex = indicesByPath[ path ],\n\t\t\t\tbindings = this._bindings;\n\n\t\t\tif ( index !== undefined ) return bindings[ index ];\n\n\t\t\tvar paths = this._paths,\n\t\t\t\tparsedPaths = this._parsedPaths,\n\t\t\t\tobjects = this._objects,\n\t\t\t\tnObjects = objects.length,\n\t\t\t\tnCachedObjects = this.nCachedObjects_,\n\t\t\t\tbindingsForPath = new Array( nObjects );\n\n\t\t\tindex = bindings.length;\n\n\t\t\tindicesByPath[ path ] = index;\n\n\t\t\tpaths.push( path );\n\t\t\tparsedPaths.push( parsedPath );\n\t\t\tbindings.push( bindingsForPath );\n\n\t\t\tfor ( var i = nCachedObjects, n = objects.length; i !== n; ++ i ) {\n\n\t\t\t\tvar object = objects[ i ];\n\t\t\t\tbindingsForPath[ i ] = new PropertyBinding( object, path, parsedPath );\n\n\t\t\t}\n\n\t\t\treturn bindingsForPath;\n\n\t\t},\n\n\t\tunsubscribe_: function ( path ) {\n\n\t\t\t\u002F\u002F tells the group to forget about a property path and no longer\n\t\t\t\u002F\u002F update the array previously obtained with 'subscribe_'\n\n\t\t\tvar indicesByPath = this._bindingsIndicesByPath,\n\t\t\t\tindex = indicesByPath[ path ];\n\n\t\t\tif ( index !== undefined ) {\n\n\t\t\t\tvar paths = this._paths,\n\t\t\t\t\tparsedPaths = this._parsedPaths,\n\t\t\t\t\tbindings = this._bindings,\n\t\t\t\t\tlastBindingsIndex = bindings.length - 1,\n\t\t\t\t\tlastBindings = bindings[ lastBindingsIndex ],\n\t\t\t\t\tlastBindingsPath = path[ lastBindingsIndex ];\n\n\t\t\t\tindicesByPath[ lastBindingsPath ] = index;\n\n\t\t\t\tbindings[ index ] = lastBindings;\n\t\t\t\tbindings.pop();\n\n\t\t\t\tparsedPaths[ index ] = parsedPaths[ lastBindingsIndex ];\n\t\t\t\tparsedPaths.pop();\n\n\t\t\t\tpaths[ index ] = paths[ lastBindingsIndex ];\n\t\t\t\tpaths.pop();\n\n\t\t\t}\n\n\t\t}\n\n\t} );\n\n\t\u002F**\n\t *\n\t * Action provided by AnimationMixer for scheduling clip playback on specific\n\t * objects.\n\t *\n\t * @author Ben Houston \u002F http:\u002F\u002Fclara.io\u002F\n\t * @author David Sarno \u002F http:\u002F\u002Flighthaus.us\u002F\n\t * @author tschw\n\t *\n\t *\u002F\n\n\tfunction AnimationAction( mixer, clip, localRoot ) {\n\n\t\tthis._mixer = mixer;\n\t\tthis._clip = clip;\n\t\tthis._localRoot = localRoot || null;\n\n\t\tvar tracks = clip.tracks,\n\t\t\tnTracks = tracks.length,\n\t\t\tinterpolants = new Array( nTracks );\n\n\t\tvar interpolantSettings = {\n\t\t\tendingStart: ZeroCurvatureEnding,\n\t\t\tendingEnd: ZeroCurvatureEnding\n\t\t};\n\n\t\tfor ( var i = 0; i !== nTracks; ++ i ) {\n\n\t\t\tvar interpolant = tracks[ i ].createInterpolant( null );\n\t\t\tinterpolants[ i ] = interpolant;\n\t\t\tinterpolant.settings = interpolantSettings;\n\n\t\t}\n\n\t\tthis._interpolantSettings = interpolantSettings;\n\n\t\tthis._interpolants = interpolants; \u002F\u002F bound by the mixer\n\n\t\t\u002F\u002F inside: PropertyMixer (managed by the mixer)\n\t\tthis._propertyBindings = new Array( nTracks );\n\n\t\tthis._cacheIndex = null; \u002F\u002F for the memory manager\n\t\tthis._byClipCacheIndex = null; \u002F\u002F for the memory manager\n\n\t\tthis._timeScaleInterpolant = null;\n\t\tthis._weightInterpolant = null;\n\n\t\tthis.loop = LoopRepeat;\n\t\tthis._loopCount = - 1;\n\n\t\t\u002F\u002F global mixer time when the action is to be started\n\t\t\u002F\u002F it's set back to 'null' upon start of the action\n\t\tthis._startTime = null;\n\n\t\t\u002F\u002F scaled local time of the action\n\t\t\u002F\u002F gets clamped or wrapped to 0..clip.duration according to loop\n\t\tthis.time = 0;\n\n\t\tthis.timeScale = 1;\n\t\tthis._effectiveTimeScale = 1;\n\n\t\tthis.weight = 1;\n\t\tthis._effectiveWeight = 1;\n\n\t\tthis.repetitions = Infinity; \u002F\u002F no. of repetitions when looping\n\n\t\tthis.paused = false; \u002F\u002F true -\u003E zero effective time scale\n\t\tthis.enabled = true; \u002F\u002F false -\u003E zero effective weight\n\n\t\tthis.clampWhenFinished = false;\u002F\u002F keep feeding the last frame?\n\n\t\tthis.zeroSlopeAtStart = true;\u002F\u002F for smooth interpolation w\u002Fo separate\n\t\tthis.zeroSlopeAtEnd = true;\u002F\u002F clips for start, loop and end\n\n\t}\n\n\tObject.assign( AnimationAction.prototype, {\n\n\t\t\u002F\u002F State & Scheduling\n\n\t\tplay: function () {\n\n\t\t\tthis._mixer._activateAction( this );\n\n\t\t\treturn this;\n\n\t\t},\n\n\t\tstop: function () {\n\n\t\t\tthis._mixer._deactivateAction( this );\n\n\t\t\treturn this.reset();\n\n\t\t},\n\n\t\treset: function () {\n\n\t\t\tthis.paused = false;\n\t\t\tthis.enabled = true;\n\n\t\t\tthis.time = 0; \u002F\u002F restart clip\n\t\t\tthis._loopCount = - 1;\u002F\u002F forget previous loops\n\t\t\tthis._startTime = null;\u002F\u002F forget scheduling\n\n\t\t\treturn this.stopFading().stopWarping();\n\n\t\t},\n\n\t\tisRunning: function () {\n\n\t\t\treturn this.enabled && ! this.paused && this.timeScale !== 0 &&\n\t\t\t\tthis._startTime === null && this._mixer._isActiveAction( this );\n\n\t\t},\n\n\t\t\u002F\u002F return true when play has been called\n\t\tisScheduled: function () {\n\n\t\t\treturn this._mixer._isActiveAction( this );\n\n\t\t},\n\n\t\tstartAt: function ( time ) {\n\n\t\t\tthis._startTime = time;\n\n\t\t\treturn this;\n\n\t\t},\n\n\t\tsetLoop: function ( mode, repetitions ) {\n\n\t\t\tthis.loop = mode;\n\t\t\tthis.repetitions = repetitions;\n\n\t\t\treturn this;\n\n\t\t},\n\n\t\t\u002F\u002F Weight\n\n\t\t\u002F\u002F set the weight stopping any scheduled fading\n\t\t\u002F\u002F although .enabled = false yields an effective weight of zero, this\n\t\t\u002F\u002F method does *not* change .enabled, because it would be confusing\n\t\tsetEffectiveWeight: function ( weight ) {\n\n\t\t\tthis.weight = weight;\n\n\t\t\t\u002F\u002F note: same logic as when updated at runtime\n\t\t\tthis._effectiveWeight = this.enabled ? weight : 0;\n\n\t\t\treturn this.stopFading();\n\n\t\t},\n\n\t\t\u002F\u002F return the weight considering fading and .enabled\n\t\tgetEffectiveWeight: function () {\n\n\t\t\treturn this._effectiveWeight;\n\n\t\t},\n\n\t\tfadeIn: function ( duration ) {\n\n\t\t\treturn this._scheduleFading( duration, 0, 1 );\n\n\t\t},\n\n\t\tfadeOut: function ( duration ) {\n\n\t\t\treturn this._scheduleFading( duration, 1, 0 );\n\n\t\t},\n\n\t\tcrossFadeFrom: function ( fadeOutAction, duration, warp ) {\n\n\t\t\tfadeOutAction.fadeOut( duration );\n\t\t\tthis.fadeIn( duration );\n\n\t\t\tif ( warp ) {\n\n\t\t\t\tvar fadeInDuration = this._clip.duration,\n\t\t\t\t\tfadeOutDuration = fadeOutAction._clip.duration,\n\n\t\t\t\t\tstartEndRatio = fadeOutDuration \u002F fadeInDuration,\n\t\t\t\t\tendStartRatio = fadeInDuration \u002F fadeOutDuration;\n\n\t\t\t\tfadeOutAction.warp( 1.0, startEndRatio, duration );\n\t\t\t\tthis.warp( endStartRatio, 1.0, duration );\n\n\t\t\t}\n\n\t\t\treturn this;\n\n\t\t},\n\n\t\tcrossFadeTo: function ( fadeInAction, duration, warp ) {\n\n\t\t\treturn fadeInAction.crossFadeFrom( this, duration, warp );\n\n\t\t},\n\n\t\tstopFading: function () {\n\n\t\t\tvar weightInterpolant = this._weightInterpolant;\n\n\t\t\tif ( weightInterpolant !== null ) {\n\n\t\t\t\tthis._weightInterpolant = null;\n\t\t\t\tthis._mixer._takeBackControlInterpolant( weightInterpolant );\n\n\t\t\t}\n\n\t\t\treturn this;\n\n\t\t},\n\n\t\t\u002F\u002F Time Scale Control\n\n\t\t\u002F\u002F set the time scale stopping any scheduled warping\n\t\t\u002F\u002F although .paused = true yields an effective time scale of zero, this\n\t\t\u002F\u002F method does *not* change .paused, because it would be confusing\n\t\tsetEffectiveTimeScale: function ( timeScale ) {\n\n\t\t\tthis.timeScale = timeScale;\n\t\t\tthis._effectiveTimeScale = this.paused ? 0 : timeScale;\n\n\t\t\treturn this.stopWarping();\n\n\t\t},\n\n\t\t\u002F\u002F return the time scale considering warping and .paused\n\t\tgetEffectiveTimeScale: function () {\n\n\t\t\treturn this._effectiveTimeScale;\n\n\t\t},\n\n\t\tsetDuration: function ( duration ) {\n\n\t\t\tthis.timeScale = this._clip.duration \u002F duration;\n\n\t\t\treturn this.stopWarping();\n\n\t\t},\n\n\t\tsyncWith: function ( action ) {\n\n\t\t\tthis.time = action.time;\n\t\t\tthis.timeScale = action.timeScale;\n\n\t\t\treturn this.stopWarping();\n\n\t\t},\n\n\t\thalt: function ( duration ) {\n\n\t\t\treturn this.warp( this._effectiveTimeScale, 0, duration );\n\n\t\t},\n\n\t\twarp: function ( startTimeScale, endTimeScale, duration ) {\n\n\t\t\tvar mixer = this._mixer, now = mixer.time,\n\t\t\t\tinterpolant = this._timeScaleInterpolant,\n\n\t\t\t\ttimeScale = this.timeScale;\n\n\t\t\tif ( interpolant === null ) {\n\n\t\t\t\tinterpolant = mixer._lendControlInterpolant();\n\t\t\t\tthis._timeScaleInterpolant = interpolant;\n\n\t\t\t}\n\n\t\t\tvar times = interpolant.parameterPositions,\n\t\t\t\tvalues = interpolant.sampleValues;\n\n\t\t\ttimes[ 0 ] = now;\n\t\t\ttimes[ 1 ] = now + duration;\n\n\t\t\tvalues[ 0 ] = startTimeScale \u002F timeScale;\n\t\t\tvalues[ 1 ] = endTimeScale \u002F timeScale;\n\n\t\t\treturn this;\n\n\t\t},\n\n\t\tstopWarping: function () {\n\n\t\t\tvar timeScaleInterpolant = this._timeScaleInterpolant;\n\n\t\t\tif ( timeScaleInterpolant !== null ) {\n\n\t\t\t\tthis._timeScaleInterpolant = null;\n\t\t\t\tthis._mixer._takeBackControlInterpolant( timeScaleInterpolant );\n\n\t\t\t}\n\n\t\t\treturn this;\n\n\t\t},\n\n\t\t\u002F\u002F Object Accessors\n\n\t\tgetMixer: function () {\n\n\t\t\treturn this._mixer;\n\n\t\t},\n\n\t\tgetClip: function () {\n\n\t\t\treturn this._clip;\n\n\t\t},\n\n\t\tgetRoot: function () {\n\n\t\t\treturn this._localRoot || this._mixer._root;\n\n\t\t},\n\n\t\t\u002F\u002F Interna\n\n\t\t_update: function ( time, deltaTime, timeDirection, accuIndex ) {\n\n\t\t\t\u002F\u002F called by the mixer\n\n\t\t\tif ( ! this.enabled ) {\n\n\t\t\t\t\u002F\u002F call ._updateWeight() to update ._effectiveWeight\n\n\t\t\t\tthis._updateWeight( time );\n\t\t\t\treturn;\n\n\t\t\t}\n\n\t\t\tvar startTime = this._startTime;\n\n\t\t\tif ( startTime !== null ) {\n\n\t\t\t\t\u002F\u002F check for scheduled start of action\n\n\t\t\t\tvar timeRunning = ( time - startTime ) * timeDirection;\n\t\t\t\tif ( timeRunning \u003C 0 || timeDirection === 0 ) {\n\n\t\t\t\t\treturn; \u002F\u002F yet to come \u002F don't decide when delta = 0\n\n\t\t\t\t}\n\n\t\t\t\t\u002F\u002F start\n\n\t\t\t\tthis._startTime = null; \u002F\u002F unschedule\n\t\t\t\tdeltaTime = timeDirection * timeRunning;\n\n\t\t\t}\n\n\t\t\t\u002F\u002F apply time scale and advance time\n\n\t\t\tdeltaTime *= this._updateTimeScale( time );\n\t\t\tvar clipTime = this._updateTime( deltaTime );\n\n\t\t\t\u002F\u002F note: _updateTime may disable the action resulting in\n\t\t\t\u002F\u002F an effective weight of 0\n\n\t\t\tvar weight = this._updateWeight( time );\n\n\t\t\tif ( weight \u003E 0 ) {\n\n\t\t\t\tvar interpolants = this._interpolants;\n\t\t\t\tvar propertyMixers = this._propertyBindings;\n\n\t\t\t\tfor ( var j = 0, m = interpolants.length; j !== m; ++ j ) {\n\n\t\t\t\t\tinterpolants[ j ].evaluate( clipTime );\n\t\t\t\t\tpropertyMixers[ j ].accumulate( accuIndex, weight );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t},\n\n\t\t_updateWeight: function ( time ) {\n\n\t\t\tvar weight = 0;\n\n\t\t\tif ( this.enabled ) {\n\n\t\t\t\tweight = this.weight;\n\t\t\t\tvar interpolant = this._weightInterpolant;\n\n\t\t\t\tif ( interpolant !== null ) {\n\n\t\t\t\t\tvar interpolantValue = interpolant.evaluate( time )[ 0 ];\n\n\t\t\t\t\tweight *= interpolantValue;\n\n\t\t\t\t\tif ( time \u003E interpolant.parameterPositions[ 1 ] ) {\n\n\t\t\t\t\t\tthis.stopFading();\n\n\t\t\t\t\t\tif ( interpolantValue === 0 ) {\n\n\t\t\t\t\t\t\t\u002F\u002F faded out, disable\n\t\t\t\t\t\t\tthis.enabled = false;\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tthis._effectiveWeight = weight;\n\t\t\treturn weight;\n\n\t\t},\n\n\t\t_updateTimeScale: function ( time ) {\n\n\t\t\tvar timeScale = 0;\n\n\t\t\tif ( ! this.paused ) {\n\n\t\t\t\ttimeScale = this.timeScale;\n\n\t\t\t\tvar interpolant = this._timeScaleInterpolant;\n\n\t\t\t\tif ( interpolant !== null ) {\n\n\t\t\t\t\tvar interpolantValue = interpolant.evaluate( time )[ 0 ];\n\n\t\t\t\t\ttimeScale *= interpolantValue;\n\n\t\t\t\t\tif ( time \u003E interpolant.parameterPositions[ 1 ] ) {\n\n\t\t\t\t\t\tthis.stopWarping();\n\n\t\t\t\t\t\tif ( timeScale === 0 ) {\n\n\t\t\t\t\t\t\t\u002F\u002F motion has halted, pause\n\t\t\t\t\t\t\tthis.paused = true;\n\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t\u002F\u002F warp done - apply final time scale\n\t\t\t\t\t\t\tthis.timeScale = timeScale;\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tthis._effectiveTimeScale = timeScale;\n\t\t\treturn timeScale;\n\n\t\t},\n\n\t\t_updateTime: function ( deltaTime ) {\n\n\t\t\tvar time = this.time + deltaTime;\n\t\t\tvar duration = this._clip.duration;\n\t\t\tvar loop = this.loop;\n\t\t\tvar loopCount = this._loopCount;\n\n\t\t\tvar pingPong = ( loop === LoopPingPong );\n\n\t\t\tif ( deltaTime === 0 ) {\n\n\t\t\t\tif ( loopCount === - 1 ) return time;\n\n\t\t\t\treturn ( pingPong && ( loopCount & 1 ) === 1 ) ? duration - time : time;\n\n\t\t\t}\n\n\t\t\tif ( loop === LoopOnce ) {\n\n\t\t\t\tif ( loopCount === - 1 ) {\n\n\t\t\t\t\t\u002F\u002F just started\n\n\t\t\t\t\tthis._loopCount = 0;\n\t\t\t\t\tthis._setEndings( true, true, false );\n\n\t\t\t\t}\n\n\t\t\t\thandle_stop: {\n\n\t\t\t\t\tif ( time \u003E= duration ) {\n\n\t\t\t\t\t\ttime = duration;\n\n\t\t\t\t\t} else if ( time \u003C 0 ) {\n\n\t\t\t\t\t\ttime = 0;\n\n\t\t\t\t\t} else break handle_stop;\n\n\t\t\t\t\tif ( this.clampWhenFinished ) this.paused = true;\n\t\t\t\t\telse this.enabled = false;\n\n\t\t\t\t\tthis._mixer.dispatchEvent( {\n\t\t\t\t\t\ttype: 'finished', action: this,\n\t\t\t\t\t\tdirection: deltaTime \u003C 0 ? - 1 : 1\n\t\t\t\t\t} );\n\n\t\t\t\t}\n\n\t\t\t} else { \u002F\u002F repetitive Repeat or PingPong\n\n\t\t\t\tif ( loopCount === - 1 ) {\n\n\t\t\t\t\t\u002F\u002F just started\n\n\t\t\t\t\tif ( deltaTime \u003E= 0 ) {\n\n\t\t\t\t\t\tloopCount = 0;\n\n\t\t\t\t\t\tthis._setEndings( true, this.repetitions === 0, pingPong );\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\u002F\u002F when looping in reverse direction, the initial\n\t\t\t\t\t\t\u002F\u002F transition through zero counts as a repetition,\n\t\t\t\t\t\t\u002F\u002F so leave loopCount at -1\n\n\t\t\t\t\t\tthis._setEndings( this.repetitions === 0, true, pingPong );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\tif ( time \u003E= duration || time \u003C 0 ) {\n\n\t\t\t\t\t\u002F\u002F wrap around\n\n\t\t\t\t\tvar loopDelta = Math.floor( time \u002F duration ); \u002F\u002F signed\n\t\t\t\t\ttime -= duration * loopDelta;\n\n\t\t\t\t\tloopCount += Math.abs( loopDelta );\n\n\t\t\t\t\tvar pending = this.repetitions - loopCount;\n\n\t\t\t\t\tif ( pending \u003C= 0 ) {\n\n\t\t\t\t\t\t\u002F\u002F have to stop (switch state, clamp time, fire event)\n\n\t\t\t\t\t\tif ( this.clampWhenFinished ) this.paused = true;\n\t\t\t\t\t\telse this.enabled = false;\n\n\t\t\t\t\t\ttime = deltaTime \u003E 0 ? duration : 0;\n\n\t\t\t\t\t\tthis._mixer.dispatchEvent( {\n\t\t\t\t\t\t\ttype: 'finished', action: this,\n\t\t\t\t\t\t\tdirection: deltaTime \u003E 0 ? 1 : - 1\n\t\t\t\t\t\t} );\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\u002F\u002F keep running\n\n\t\t\t\t\t\tif ( pending === 1 ) {\n\n\t\t\t\t\t\t\t\u002F\u002F entering the last round\n\n\t\t\t\t\t\t\tvar atStart = deltaTime \u003C 0;\n\t\t\t\t\t\t\tthis._setEndings( atStart, ! atStart, pingPong );\n\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\tthis._setEndings( false, false, pingPong );\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tthis._loopCount = loopCount;\n\n\t\t\t\t\t\tthis._mixer.dispatchEvent( {\n\t\t\t\t\t\t\ttype: 'loop', action: this, loopDelta: loopDelta\n\t\t\t\t\t\t} );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\tif ( pingPong && ( loopCount & 1 ) === 1 ) {\n\n\t\t\t\t\t\u002F\u002F invert time for the \"pong round\"\n\n\t\t\t\t\tthis.time = time;\n\t\t\t\t\treturn duration - time;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tthis.time = time;\n\t\t\treturn time;\n\n\t\t},\n\n\t\t_setEndings: function ( atStart, atEnd, pingPong ) {\n\n\t\t\tvar settings = this._interpolantSettings;\n\n\t\t\tif ( pingPong ) {\n\n\t\t\t\tsettings.endingStart = ZeroSlopeEnding;\n\t\t\t\tsettings.endingEnd = ZeroSlopeEnding;\n\n\t\t\t} else {\n\n\t\t\t\t\u002F\u002F assuming for LoopOnce atStart == atEnd == true\n\n\t\t\t\tif ( atStart ) {\n\n\t\t\t\t\tsettings.endingStart = this.zeroSlopeAtStart ? ZeroSlopeEnding : ZeroCurvatureEnding;\n\n\t\t\t\t} else {\n\n\t\t\t\t\tsettings.endingStart = WrapAroundEnding;\n\n\t\t\t\t}\n\n\t\t\t\tif ( atEnd ) {\n\n\t\t\t\t\tsettings.endingEnd = this.zeroSlopeAtEnd ? ZeroSlopeEnding : ZeroCurvatureEnding;\n\n\t\t\t\t} else {\n\n\t\t\t\t\tsettings.endingEnd \t = WrapAroundEnding;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t},\n\n\t\t_scheduleFading: function ( duration, weightNow, weightThen ) {\n\n\t\t\tvar mixer = this._mixer, now = mixer.time,\n\t\t\t\tinterpolant = this._weightInterpolant;\n\n\t\t\tif ( interpolant === null ) {\n\n\t\t\t\tinterpolant = mixer._lendControlInterpolant();\n\t\t\t\tthis._weightInterpolant = interpolant;\n\n\t\t\t}\n\n\t\t\tvar times = interpolant.parameterPositions,\n\t\t\t\tvalues = interpolant.sampleValues;\n\n\t\t\ttimes[ 0 ] = now;\n\t\t\tvalues[ 0 ] = weightNow;\n\t\t\ttimes[ 1 ] = now + duration;\n\t\t\tvalues[ 1 ] = weightThen;\n\n\t\t\treturn this;\n\n\t\t}\n\n\t} );\n\n\t\u002F**\n\t *\n\t * Player for AnimationClips.\n\t *\n\t *\n\t * @author Ben Houston \u002F http:\u002F\u002Fclara.io\u002F\n\t * @author David Sarno \u002F http:\u002F\u002Flighthaus.us\u002F\n\t * @author tschw\n\t *\u002F\n\n\tfunction AnimationMixer( root ) {\n\n\t\tthis._root = root;\n\t\tthis._initMemoryManager();\n\t\tthis._accuIndex = 0;\n\n\t\tthis.time = 0;\n\n\t\tthis.timeScale = 1.0;\n\n\t}\n\n\tAnimationMixer.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {\n\n\t\tconstructor: AnimationMixer,\n\n\t\t_bindAction: function ( action, prototypeAction ) {\n\n\t\t\tvar root = action._localRoot || this._root,\n\t\t\t\ttracks = action._clip.tracks,\n\t\t\t\tnTracks = tracks.length,\n\t\t\t\tbindings = action._propertyBindings,\n\t\t\t\tinterpolants = action._interpolants,\n\t\t\t\trootUuid = root.uuid,\n\t\t\t\tbindingsByRoot = this._bindingsByRootAndName,\n\t\t\t\tbindingsByName = bindingsByRoot[ rootUuid ];\n\n\t\t\tif ( bindingsByName === undefined ) {\n\n\t\t\t\tbindingsByName = {};\n\t\t\t\tbindingsByRoot[ rootUuid ] = bindingsByName;\n\n\t\t\t}\n\n\t\t\tfor ( var i = 0; i !== nTracks; ++ i ) {\n\n\t\t\t\tvar track = tracks[ i ],\n\t\t\t\t\ttrackName = track.name,\n\t\t\t\t\tbinding = bindingsByName[ trackName ];\n\n\t\t\t\tif ( binding !== undefined ) {\n\n\t\t\t\t\tbindings[ i ] = binding;\n\n\t\t\t\t} else {\n\n\t\t\t\t\tbinding = bindings[ i ];\n\n\t\t\t\t\tif ( binding !== undefined ) {\n\n\t\t\t\t\t\t\u002F\u002F existing binding, make sure the cache knows\n\n\t\t\t\t\t\tif ( binding._cacheIndex === null ) {\n\n\t\t\t\t\t\t\t++ binding.referenceCount;\n\t\t\t\t\t\t\tthis._addInactiveBinding( binding, rootUuid, trackName );\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcontinue;\n\n\t\t\t\t\t}\n\n\t\t\t\t\tvar path = prototypeAction && prototypeAction.\n\t\t\t\t\t\t_propertyBindings[ i ].binding.parsedPath;\n\n\t\t\t\t\tbinding = new PropertyMixer(\n\t\t\t\t\t\tPropertyBinding.create( root, trackName, path ),\n\t\t\t\t\t\ttrack.ValueTypeName, track.getValueSize() );\n\n\t\t\t\t\t++ binding.referenceCount;\n\t\t\t\t\tthis._addInactiveBinding( binding, rootUuid, trackName );\n\n\t\t\t\t\tbindings[ i ] = binding;\n\n\t\t\t\t}\n\n\t\t\t\tinterpolants[ i ].resultBuffer = binding.buffer;\n\n\t\t\t}\n\n\t\t},\n\n\t\t_activateAction: function ( action ) {\n\n\t\t\tif ( ! this._isActiveAction( action ) ) {\n\n\t\t\t\tif ( action._cacheIndex === null ) {\n\n\t\t\t\t\t\u002F\u002F this action has been forgotten by the cache, but the user\n\t\t\t\t\t\u002F\u002F appears to be still using it -\u003E rebind\n\n\t\t\t\t\tvar rootUuid = ( action._localRoot || this._root ).uuid,\n\t\t\t\t\t\tclipUuid = action._clip.uuid,\n\t\t\t\t\t\tactionsForClip = this._actionsByClip[ clipUuid ];\n\n\t\t\t\t\tthis._bindAction( action,\n\t\t\t\t\t\tactionsForClip && actionsForClip.knownActions[ 0 ] );\n\n\t\t\t\t\tthis._addInactiveAction( action, clipUuid, rootUuid );\n\n\t\t\t\t}\n\n\t\t\t\tvar bindings = action._propertyBindings;\n\n\t\t\t\t\u002F\u002F increment reference counts \u002F sort out state\n\t\t\t\tfor ( var i = 0, n = bindings.length; i !== n; ++ i ) {\n\n\t\t\t\t\tvar binding = bindings[ i ];\n\n\t\t\t\t\tif ( binding.useCount ++ === 0 ) {\n\n\t\t\t\t\t\tthis._lendBinding( binding );\n\t\t\t\t\t\tbinding.saveOriginalState();\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\tthis._lendAction( action );\n\n\t\t\t}\n\n\t\t},\n\n\t\t_deactivateAction: function ( action ) {\n\n\t\t\tif ( this._isActiveAction( action ) ) {\n\n\t\t\t\tvar bindings = action._propertyBindings;\n\n\t\t\t\t\u002F\u002F decrement reference counts \u002F sort out state\n\t\t\t\tfor ( var i = 0, n = bindings.length; i !== n; ++ i ) {\n\n\t\t\t\t\tvar binding = bindings[ i ];\n\n\t\t\t\t\tif ( -- binding.useCount === 0 ) {\n\n\t\t\t\t\t\tbinding.restoreOriginalState();\n\t\t\t\t\t\tthis._takeBackBinding( binding );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\tthis._takeBackAction( action );\n\n\t\t\t}\n\n\t\t},\n\n\t\t\u002F\u002F Memory manager\n\n\t\t_initMemoryManager: function () {\n\n\t\t\tthis._actions = []; \u002F\u002F 'nActiveActions' followed by inactive ones\n\t\t\tthis._nActiveActions = 0;\n\n\t\t\tthis._actionsByClip = {};\n\t\t\t\u002F\u002F inside:\n\t\t\t\u002F\u002F {\n\t\t\t\u002F\u002F \tknownActions: Array\u003C AnimationAction \u003E - used as prototypes\n\t\t\t\u002F\u002F \tactionByRoot: AnimationAction - lookup\n\t\t\t\u002F\u002F }\n\n\n\t\t\tthis._bindings = []; \u002F\u002F 'nActiveBindings' followed by inactive ones\n\t\t\tthis._nActiveBindings = 0;\n\n\t\t\tthis._bindingsByRootAndName = {}; \u002F\u002F inside: Map\u003C name, PropertyMixer \u003E\n\n\n\t\t\tthis._controlInterpolants = []; \u002F\u002F same game as above\n\t\t\tthis._nActiveControlInterpolants = 0;\n\n\t\t\tvar scope = this;\n\n\t\t\tthis.stats = {\n\n\t\t\t\tactions: {\n\t\t\t\t\tget total() {\n\n\t\t\t\t\t\treturn scope._actions.length;\n\n\t\t\t\t\t},\n\t\t\t\t\tget inUse() {\n\n\t\t\t\t\t\treturn scope._nActiveActions;\n\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tbindings: {\n\t\t\t\t\tget total() {\n\n\t\t\t\t\t\treturn scope._bindings.length;\n\n\t\t\t\t\t},\n\t\t\t\t\tget inUse() {\n\n\t\t\t\t\t\treturn scope._nActiveBindings;\n\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tcontrolInterpolants: {\n\t\t\t\t\tget total() {\n\n\t\t\t\t\t\treturn scope._controlInterpolants.length;\n\n\t\t\t\t\t},\n\t\t\t\t\tget inUse() {\n\n\t\t\t\t\t\treturn scope._nActiveControlInterpolants;\n\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t};\n\n\t\t},\n\n\t\t\u002F\u002F Memory management for AnimationAction objects\n\n\t\t_isActiveAction: function ( action ) {\n\n\t\t\tvar index = action._cacheIndex;\n\t\t\treturn index !== null && index \u003C this._nActiveActions;\n\n\t\t},\n\n\t\t_addInactiveAction: function ( action, clipUuid, rootUuid ) {\n\n\t\t\tvar actions = this._actions,\n\t\t\t\tactionsByClip = this._actionsByClip,\n\t\t\t\tactionsForClip = actionsByClip[ clipUuid ];\n\n\t\t\tif ( actionsForClip === undefined ) {\n\n\t\t\t\tactionsForClip = {\n\n\t\t\t\t\tknownActions: [ action ],\n\t\t\t\t\tactionByRoot: {}\n\n\t\t\t\t};\n\n\t\t\t\taction._byClipCacheIndex = 0;\n\n\t\t\t\tactionsByClip[ clipUuid ] = actionsForClip;\n\n\t\t\t} else {\n\n\t\t\t\tvar knownActions = actionsForClip.knownActions;\n\n\t\t\t\taction._byClipCacheIndex = knownActions.length;\n\t\t\t\tknownActions.push( action );\n\n\t\t\t}\n\n\t\t\taction._cacheIndex = actions.length;\n\t\t\tactions.push( action );\n\n\t\t\tactionsForClip.actionByRoot[ rootUuid ] = action;\n\n\t\t},\n\n\t\t_removeInactiveAction: function ( action ) {\n\n\t\t\tvar actions = this._actions,\n\t\t\t\tlastInactiveAction = actions[ actions.length - 1 ],\n\t\t\t\tcacheIndex = action._cacheIndex;\n\n\t\t\tlastInactiveAction._cacheIndex = cacheIndex;\n\t\t\tactions[ cacheIndex ] = lastInactiveAction;\n\t\t\tactions.pop();\n\n\t\t\taction._cacheIndex = null;\n\n\n\t\t\tvar clipUuid = action._clip.uuid,\n\t\t\t\tactionsByClip = this._actionsByClip,\n\t\t\t\tactionsForClip = actionsByClip[ clipUuid ],\n\t\t\t\tknownActionsForClip = actionsForClip.knownActions,\n\n\t\t\t\tlastKnownAction =\n\t\t\t\t\tknownActionsForClip[ knownActionsForClip.length - 1 ],\n\n\t\t\t\tbyClipCacheIndex = action._byClipCacheIndex;\n\n\t\t\tlastKnownAction._byClipCacheIndex = byClipCacheIndex;\n\t\t\tknownActionsForClip[ byClipCacheIndex ] = lastKnownAction;\n\t\t\tknownActionsForClip.pop();\n\n\t\t\taction._byClipCacheIndex = null;\n\n\n\t\t\tvar actionByRoot = actionsForClip.actionByRoot,\n\t\t\t\trootUuid = ( action._localRoot || this._root ).uuid;\n\n\t\t\tdelete actionByRoot[ rootUuid ];\n\n\t\t\tif ( knownActionsForClip.length === 0 ) {\n\n\t\t\t\tdelete actionsByClip[ clipUuid ];\n\n\t\t\t}\n\n\t\t\tthis._removeInactiveBindingsForAction( action );\n\n\t\t},\n\n\t\t_removeInactiveBindingsForAction: function ( action ) {\n\n\t\t\tvar bindings = action._propertyBindings;\n\t\t\tfor ( var i = 0, n = bindings.length; i !== n; ++ i ) {\n\n\t\t\t\tvar binding = bindings[ i ];\n\n\t\t\t\tif ( -- binding.referenceCount === 0 ) {\n\n\t\t\t\t\tthis._removeInactiveBinding( binding );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t},\n\n\t\t_lendAction: function ( action ) {\n\n\t\t\t\u002F\u002F [ active actions | inactive actions ]\n\t\t\t\u002F\u002F [ active actions \u003E| inactive actions ]\n\t\t\t\u002F\u002F s a\n\t\t\t\u002F\u002F \u003C-swap-\u003E\n\t\t\t\u002F\u002F a s\n\n\t\t\tvar actions = this._actions,\n\t\t\t\tprevIndex = action._cacheIndex,\n\n\t\t\t\tlastActiveIndex = this._nActiveActions ++,\n\n\t\t\t\tfirstInactiveAction = actions[ lastActiveIndex ];\n\n\t\t\taction._cacheIndex = lastActiveIndex;\n\t\t\tactions[ lastActiveIndex ] = action;\n\n\t\t\tfirstInactiveAction._cacheIndex = prevIndex;\n\t\t\tactions[ prevIndex ] = firstInactiveAction;\n\n\t\t},\n\n\t\t_takeBackAction: function ( action ) {\n\n\t\t\t\u002F\u002F [ active actions | inactive actions ]\n\t\t\t\u002F\u002F [ active actions |\u003C inactive actions ]\n\t\t\t\u002F\u002F a s\n\t\t\t\u002F\u002F \u003C-swap-\u003E\n\t\t\t\u002F\u002F s a\n\n\t\t\tvar actions = this._actions,\n\t\t\t\tprevIndex = action._cacheIndex,\n\n\t\t\t\tfirstInactiveIndex = -- this._nActiveActions,\n\n\t\t\t\tlastActiveAction = actions[ firstInactiveIndex ];\n\n\t\t\taction._cacheIndex = firstInactiveIndex;\n\t\t\tactions[ firstInactiveIndex ] = action;\n\n\t\t\tlastActiveAction._cacheIndex = prevIndex;\n\t\t\tactions[ prevIndex ] = lastActiveAction;\n\n\t\t},\n\n\t\t\u002F\u002F Memory management for PropertyMixer objects\n\n\t\t_addInactiveBinding: function ( binding, rootUuid, trackName ) {\n\n\t\t\tvar bindingsByRoot = this._bindingsByRootAndName,\n\t\t\t\tbindingByName = bindingsByRoot[ rootUuid ],\n\n\t\t\t\tbindings = this._bindings;\n\n\t\t\tif ( bindingByName === undefined ) {\n\n\t\t\t\tbindingByName = {};\n\t\t\t\tbindingsByRoot[ rootUuid ] = bindingByName;\n\n\t\t\t}\n\n\t\t\tbindingByName[ trackName ] = binding;\n\n\t\t\tbinding._cacheIndex = bindings.length;\n\t\t\tbindings.push( binding );\n\n\t\t},\n\n\t\t_removeInactiveBinding: function ( binding ) {\n\n\t\t\tvar bindings = this._bindings,\n\t\t\t\tpropBinding = binding.binding,\n\t\t\t\trootUuid = propBinding.rootNode.uuid,\n\t\t\t\ttrackName = propBinding.path,\n\t\t\t\tbindingsByRoot = this._bindingsByRootAndName,\n\t\t\t\tbindingByName = bindingsByRoot[ rootUuid ],\n\n\t\t\t\tlastInactiveBinding = bindings[ bindings.length - 1 ],\n\t\t\t\tcacheIndex = binding._cacheIndex;\n\n\t\t\tlastInactiveBinding._cacheIndex = cacheIndex;\n\t\t\tbindings[ cacheIndex ] = lastInactiveBinding;\n\t\t\tbindings.pop();\n\n\t\t\tdelete bindingByName[ trackName ];\n\n\t\t\tremove_empty_map: {\n\n\t\t\t\tfor ( var _ in bindingByName ) break remove_empty_map; \u002F\u002F eslint-disable-line no-unused-vars\n\n\t\t\t\tdelete bindingsByRoot[ rootUuid ];\n\n\t\t\t}\n\n\t\t},\n\n\t\t_lendBinding: function ( binding ) {\n\n\t\t\tvar bindings = this._bindings,\n\t\t\t\tprevIndex = binding._cacheIndex,\n\n\t\t\t\tlastActiveIndex = this._nActiveBindings ++,\n\n\t\t\t\tfirstInactiveBinding = bindings[ lastActiveIndex ];\n\n\t\t\tbinding._cacheIndex = lastActiveIndex;\n\t\t\tbindings[ lastActiveIndex ] = binding;\n\n\t\t\tfirstInactiveBinding._cacheIndex = prevIndex;\n\t\t\tbindings[ prevIndex ] = firstInactiveBinding;\n\n\t\t},\n\n\t\t_takeBackBinding: function ( binding ) {\n\n\t\t\tvar bindings = this._bindings,\n\t\t\t\tprevIndex = binding._cacheIndex,\n\n\t\t\t\tfirstInactiveIndex = -- this._nActiveBindings,\n\n\t\t\t\tlastActiveBinding = bindings[ firstInactiveIndex ];\n\n\t\t\tbinding._cacheIndex = firstInactiveIndex;\n\t\t\tbindings[ firstInactiveIndex ] = binding;\n\n\t\t\tlastActiveBinding._cacheIndex = prevIndex;\n\t\t\tbindings[ prevIndex ] = lastActiveBinding;\n\n\t\t},\n\n\n\t\t\u002F\u002F Memory management of Interpolants for weight and time scale\n\n\t\t_lendControlInterpolant: function () {\n\n\t\t\tvar interpolants = this._controlInterpolants,\n\t\t\t\tlastActiveIndex = this._nActiveControlInterpolants ++,\n\t\t\t\tinterpolant = interpolants[ lastActiveIndex ];\n\n\t\t\tif ( interpolant === undefined ) {\n\n\t\t\t\tinterpolant = new LinearInterpolant(\n\t\t\t\t\tnew Float32Array( 2 ), new Float32Array( 2 ),\n\t\t\t\t\t1, this._controlInterpolantsResultBuffer );\n\n\t\t\t\tinterpolant.__cacheIndex = lastActiveIndex;\n\t\t\t\tinterpolants[ lastActiveIndex ] = interpolant;\n\n\t\t\t}\n\n\t\t\treturn interpolant;\n\n\t\t},\n\n\t\t_takeBackControlInterpolant: function ( interpolant ) {\n\n\t\t\tvar interpolants = this._controlInterpolants,\n\t\t\t\tprevIndex = interpolant.__cacheIndex,\n\n\t\t\t\tfirstInactiveIndex = -- this._nActiveControlInterpolants,\n\n\t\t\t\tlastActiveInterpolant = interpolants[ firstInactiveIndex ];\n\n\t\t\tinterpolant.__cacheIndex = firstInactiveIndex;\n\t\t\tinterpolants[ firstInactiveIndex ] = interpolant;\n\n\t\t\tlastActiveInterpolant.__cacheIndex = prevIndex;\n\t\t\tinterpolants[ prevIndex ] = lastActiveInterpolant;\n\n\t\t},\n\n\t\t_controlInterpolantsResultBuffer: new Float32Array( 1 ),\n\n\t\t\u002F\u002F return an action for a clip optionally using a custom root target\n\t\t\u002F\u002F object (this method allocates a lot of dynamic memory in case a\n\t\t\u002F\u002F previously unknown clip\u002Froot combination is specified)\n\t\tclipAction: function ( clip, optionalRoot ) {\n\n\t\t\tvar root = optionalRoot || this._root,\n\t\t\t\trootUuid = root.uuid,\n\n\t\t\t\tclipObject = typeof clip === 'string' ?\n\t\t\t\t\tAnimationClip.findByName( root, clip ) : clip,\n\n\t\t\t\tclipUuid = clipObject !== null ? clipObject.uuid : clip,\n\n\t\t\t\tactionsForClip = this._actionsByClip[ clipUuid ],\n\t\t\t\tprototypeAction = null;\n\n\t\t\tif ( actionsForClip !== undefined ) {\n\n\t\t\t\tvar existingAction =\n\t\t\t\t\t\tactionsForClip.actionByRoot[ rootUuid ];\n\n\t\t\t\tif ( existingAction !== undefined ) {\n\n\t\t\t\t\treturn existingAction;\n\n\t\t\t\t}\n\n\t\t\t\t\u002F\u002F we know the clip, so we don't have to parse all\n\t\t\t\t\u002F\u002F the bindings again but can just copy\n\t\t\t\tprototypeAction = actionsForClip.knownActions[ 0 ];\n\n\t\t\t\t\u002F\u002F also, take the clip from the prototype action\n\t\t\t\tif ( clipObject === null )\n\t\t\t\t\tclipObject = prototypeAction._clip;\n\n\t\t\t}\n\n\t\t\t\u002F\u002F clip must be known when specified via string\n\t\t\tif ( clipObject === null ) return null;\n\n\t\t\t\u002F\u002F allocate all resources required to run it\n\t\t\tvar newAction = new AnimationAction( this, clipObject, optionalRoot );\n\n\t\t\tthis._bindAction( newAction, prototypeAction );\n\n\t\t\t\u002F\u002F and make the action known to the memory manager\n\t\t\tthis._addInactiveAction( newAction, clipUuid, rootUuid );\n\n\t\t\treturn newAction;\n\n\t\t},\n\n\t\t\u002F\u002F get an existing action\n\t\texistingAction: function ( clip, optionalRoot ) {\n\n\t\t\tvar root = optionalRoot || this._root,\n\t\t\t\trootUuid = root.uuid,\n\n\t\t\t\tclipObject = typeof clip === 'string' ?\n\t\t\t\t\tAnimationClip.findByName( root, clip ) : clip,\n\n\t\t\t\tclipUuid = clipObject ? clipObject.uuid : clip,\n\n\t\t\t\tactionsForClip = this._actionsByClip[ clipUuid ];\n\n\t\t\tif ( actionsForClip !== undefined ) {\n\n\t\t\t\treturn actionsForClip.actionByRoot[ rootUuid ] || null;\n\n\t\t\t}\n\n\t\t\treturn null;\n\n\t\t},\n\n\t\t\u002F\u002F deactivates all previously scheduled actions\n\t\tstopAllAction: function () {\n\n\t\t\tvar actions = this._actions,\n\t\t\t\tnActions = this._nActiveActions,\n\t\t\t\tbindings = this._bindings,\n\t\t\t\tnBindings = this._nActiveBindings;\n\n\t\t\tthis._nActiveActions = 0;\n\t\t\tthis._nActiveBindings = 0;\n\n\t\t\tfor ( var i = 0; i !== nActions; ++ i ) {\n\n\t\t\t\tactions[ i ].reset();\n\n\t\t\t}\n\n\t\t\tfor ( var i = 0; i !== nBindings; ++ i ) {\n\n\t\t\t\tbindings[ i ].useCount = 0;\n\n\t\t\t}\n\n\t\t\treturn this;\n\n\t\t},\n\n\t\t\u002F\u002F advance the time and update apply the animation\n\t\tupdate: function ( deltaTime ) {\n\n\t\t\tdeltaTime *= this.timeScale;\n\n\t\t\tvar actions = this._actions,\n\t\t\t\tnActions = this._nActiveActions,\n\n\t\t\t\ttime = this.time += deltaTime,\n\t\t\t\ttimeDirection = Math.sign( deltaTime ),\n\n\t\t\t\taccuIndex = this._accuIndex ^= 1;\n\n\t\t\t\u002F\u002F run active actions\n\n\t\t\tfor ( var i = 0; i !== nActions; ++ i ) {\n\n\t\t\t\tvar action = actions[ i ];\n\n\t\t\t\taction._update( time, deltaTime, timeDirection, accuIndex );\n\n\t\t\t}\n\n\t\t\t\u002F\u002F update scene graph\n\n\t\t\tvar bindings = this._bindings,\n\t\t\t\tnBindings = this._nActiveBindings;\n\n\t\t\tfor ( var i = 0; i !== nBindings; ++ i ) {\n\n\t\t\t\tbindings[ i ].apply( accuIndex );\n\n\t\t\t}\n\n\t\t\treturn this;\n\n\t\t},\n\n\t\t\u002F\u002F return this mixer's root target object\n\t\tgetRoot: function () {\n\n\t\t\treturn this._root;\n\n\t\t},\n\n\t\t\u002F\u002F free all resources specific to a particular clip\n\t\tuncacheClip: function ( clip ) {\n\n\t\t\tvar actions = this._actions,\n\t\t\t\tclipUuid = clip.uuid,\n\t\t\t\tactionsByClip = this._actionsByClip,\n\t\t\t\tactionsForClip = actionsByClip[ clipUuid ];\n\n\t\t\tif ( actionsForClip !== undefined ) {\n\n\t\t\t\t\u002F\u002F note: just calling _removeInactiveAction would mess up the\n\t\t\t\t\u002F\u002F iteration state and also require updating the state we can\n\t\t\t\t\u002F\u002F just throw away\n\n\t\t\t\tvar actionsToRemove = actionsForClip.knownActions;\n\n\t\t\t\tfor ( var i = 0, n = actionsToRemove.length; i !== n; ++ i ) {\n\n\t\t\t\t\tvar action = actionsToRemove[ i ];\n\n\t\t\t\t\tthis._deactivateAction( action );\n\n\t\t\t\t\tvar cacheIndex = action._cacheIndex,\n\t\t\t\t\t\tlastInactiveAction = actions[ actions.length - 1 ];\n\n\t\t\t\t\taction._cacheIndex = null;\n\t\t\t\t\taction._byClipCacheIndex = null;\n\n\t\t\t\t\tlastInactiveAction._cacheIndex = cacheIndex;\n\t\t\t\t\tactions[ cacheIndex ] = lastInactiveAction;\n\t\t\t\t\tactions.pop();\n\n\t\t\t\t\tthis._removeInactiveBindingsForAction( action );\n\n\t\t\t\t}\n\n\t\t\t\tdelete actionsByClip[ clipUuid ];\n\n\t\t\t}\n\n\t\t},\n\n\t\t\u002F\u002F free all resources specific to a particular root target object\n\t\tuncacheRoot: function ( root ) {\n\n\t\t\tvar rootUuid = root.uuid,\n\t\t\t\tactionsByClip = this._actionsByClip;\n\n\t\t\tfor ( var clipUuid in actionsByClip ) {\n\n\t\t\t\tvar actionByRoot = actionsByClip[ clipUuid ].actionByRoot,\n\t\t\t\t\taction = actionByRoot[ rootUuid ];\n\n\t\t\t\tif ( action !== undefined ) {\n\n\t\t\t\t\tthis._deactivateAction( action );\n\t\t\t\t\tthis._removeInactiveAction( action );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tvar bindingsByRoot = this._bindingsByRootAndName,\n\t\t\t\tbindingByName = bindingsByRoot[ rootUuid ];\n\n\t\t\tif ( bindingByName !== undefined ) {\n\n\t\t\t\tfor ( var trackName in bindingByName ) {\n\n\t\t\t\t\tvar binding = bindingByName[ trackName ];\n\t\t\t\t\tbinding.restoreOriginalState();\n\t\t\t\t\tthis._removeInactiveBinding( binding );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t},\n\n\t\t\u002F\u002F remove a targeted clip from the cache\n\t\tuncacheAction: function ( clip, optionalRoot ) {\n\n\t\t\tvar action = this.existingAction( clip, optionalRoot );\n\n\t\t\tif ( action !== null ) {\n\n\t\t\t\tthis._deactivateAction( action );\n\t\t\t\tthis._removeInactiveAction( action );\n\n\t\t\t}\n\n\t\t}\n\n\t} );\n\n\t\u002F**\n\t * @author mrdoob \u002F http:\u002F\u002Fmrdoob.com\u002F\n\t *\u002F\n\n\tfunction Uniform( value ) {\n\n\t\tif ( typeof value === 'string' ) {\n\n\t\t\tconsole.warn( 'THREE.Uniform: Type parameter is no longer needed.' );\n\t\t\tvalue = arguments[ 1 ];\n\n\t\t}\n\n\t\tthis.value = value;\n\n\t}\n\n\tUniform.prototype.clone = function () {\n\n\t\treturn new Uniform( this.value.clone === undefined ? this.value : this.value.clone() );\n\n\t};\n\n\t\u002F**\n\t * @author benaadams \u002F https:\u002F\u002Ftwitter.com\u002Fben_a_adams\n\t *\u002F\n\n\tfunction InstancedBufferGeometry() {\n\n\t\tBufferGeometry.call( this );\n\n\t\tthis.type = 'InstancedBufferGeometry';\n\t\tthis.maxInstancedCount = undefined;\n\n\t}\n\n\tInstancedBufferGeometry.prototype = Object.assign( Object.create( BufferGeometry.prototype ), {\n\n\t\tconstructor: InstancedBufferGeometry,\n\n\t\tisInstancedBufferGeometry: true,\n\n\t\tcopy: function ( source ) {\n\n\t\t\tBufferGeometry.prototype.copy.call( this, source );\n\n\t\t\tthis.maxInstancedCount = source.maxInstancedCount;\n\n\t\t\treturn this;\n\n\t\t},\n\n\t\tclone: function () {\n\n\t\t\treturn new this.constructor().copy( this );\n\n\t\t}\n\n\t} );\n\n\t\u002F**\n\t * @author benaadams \u002F https:\u002F\u002Ftwitter.com\u002Fben_a_adams\n\t *\u002F\n\n\tfunction InstancedInterleavedBuffer( array, stride, meshPerAttribute ) {\n\n\t\tInterleavedBuffer.call( this, array, stride );\n\n\t\tthis.meshPerAttribute = meshPerAttribute || 1;\n\n\t}\n\n\tInstancedInterleavedBuffer.prototype = Object.assign( Object.create( InterleavedBuffer.prototype ), {\n\n\t\tconstructor: InstancedInterleavedBuffer,\n\n\t\tisInstancedInterleavedBuffer: true,\n\n\t\tcopy: function ( source ) {\n\n\t\t\tInterleavedBuffer.prototype.copy.call( this, source );\n\n\t\t\tthis.meshPerAttribute = source.meshPerAttribute;\n\n\t\t\treturn this;\n\n\t\t}\n\n\t} );\n\n\t\u002F**\n\t * @author benaadams \u002F https:\u002F\u002Ftwitter.com\u002Fben_a_adams\n\t *\u002F\n\n\tfunction InstancedBufferAttribute( array, itemSize, normalized, meshPerAttribute ) {\n\n\t\tif ( typeof ( normalized ) === 'number' ) {\n\n\t\t\tmeshPerAttribute = normalized;\n\n\t\t\tnormalized = false;\n\n\t\t\tconsole.error( 'THREE.InstancedBufferAttribute: The constructor now expects normalized as the third argument.' );\n\n\t\t}\n\n\t\tBufferAttribute.call( this, array, itemSize, normalized );\n\n\t\tthis.meshPerAttribute = meshPerAttribute || 1;\n\n\t}\n\n\tInstancedBufferAttribute.prototype = Object.assign( Object.create( BufferAttribute.prototype ), {\n\n\t\tconstructor: InstancedBufferAttribute,\n\n\t\tisInstancedBufferAttribute: true,\n\n\t\tcopy: function ( source ) {\n\n\t\t\tBufferAttribute.prototype.copy.call( this, source );\n\n\t\t\tthis.meshPerAttribute = source.meshPerAttribute;\n\n\t\t\treturn this;\n\n\t\t}\n\n\t} );\n\n\t\u002F**\n\t * @author mrdoob \u002F http:\u002F\u002Fmrdoob.com\u002F\n\t * @author bhouston \u002F http:\u002F\u002Fclara.io\u002F\n\t * @author stephomi \u002F http:\u002F\u002Fstephaneginier.com\u002F\n\t *\u002F\n\n\tfunction Raycaster( origin, direction, near, far ) {\n\n\t\tthis.ray = new Ray( origin, direction );\n\t\t\u002F\u002F direction is assumed to be normalized (for accurate distance calculations)\n\n\t\tthis.near = near || 0;\n\t\tthis.far = far || Infinity;\n\n\t\tthis.params = {\n\t\t\tMesh: {},\n\t\t\tLine: {},\n\t\t\tLOD: {},\n\t\t\tPoints: { threshold: 1 },\n\t\t\tSprite: {}\n\t\t};\n\n\t\tObject.defineProperties( this.params, {\n\t\t\tPointCloud: {\n\t\t\t\tget: function () {\n\n\t\t\t\t\tconsole.warn( 'THREE.Raycaster: params.PointCloud has been renamed to params.Points.' );\n\t\t\t\t\treturn this.Points;\n\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\n\t}\n\n\tfunction ascSort( a, b ) {\n\n\t\treturn a.distance - b.distance;\n\n\t}\n\n\tfunction intersectObject( object, raycaster, intersects, recursive ) {\n\n\t\tif ( object.visible === false ) return;\n\n\t\tobject.raycast( raycaster, intersects );\n\n\t\tif ( recursive === true ) {\n\n\t\t\tvar children = object.children;\n\n\t\t\tfor ( var i = 0, l = children.length; i \u003C l; i ++ ) {\n\n\t\t\t\tintersectObject( children[ i ], raycaster, intersects, true );\n\n\t\t\t}\n\n\t\t}\n\n\t}\n\n\tObject.assign( Raycaster.prototype, {\n\n\t\tlinePrecision: 1,\n\n\t\tset: function ( origin, direction ) {\n\n\t\t\t\u002F\u002F direction is assumed to be normalized (for accurate distance calculations)\n\n\t\t\tthis.ray.set( origin, direction );\n\n\t\t},\n\n\t\tsetFromCamera: function ( coords, camera ) {\n\n\t\t\tif ( ( camera && camera.isPerspectiveCamera ) ) {\n\n\t\t\t\tthis.ray.origin.setFromMatrixPosition( camera.matrixWorld );\n\t\t\t\tthis.ray.direction.set( coords.x, coords.y, 0.5 ).unproject( camera ).sub( this.ray.origin ).normalize();\n\n\t\t\t} else if ( ( camera && camera.isOrthographicCamera ) ) {\n\n\t\t\t\tthis.ray.origin.set( coords.x, coords.y, ( camera.near + camera.far ) \u002F ( camera.near - camera.far ) ).unproject( camera ); \u002F\u002F set origin in plane of camera\n\t\t\t\tthis.ray.direction.set( 0, 0, - 1 ).transformDirection( camera.matrixWorld );\n\n\t\t\t} else {\n\n\t\t\t\tconsole.error( 'THREE.Raycaster: Unsupported camera type.' );\n\n\t\t\t}\n\n\t\t},\n\n\t\tintersectObject: function ( object, recursive, optionalTarget ) {\n\n\t\t\tvar intersects = optionalTarget || [];\n\n\t\t\tintersectObject( object, this, intersects, recursive );\n\n\t\t\tintersects.sort( ascSort );\n\n\t\t\treturn intersects;\n\n\t\t},\n\n\t\tintersectObjects: function ( objects, recursive, optionalTarget ) {\n\n\t\t\tvar intersects = optionalTarget || [];\n\n\t\t\tif ( Array.isArray( objects ) === false ) {\n\n\t\t\t\tconsole.warn( 'THREE.Raycaster.intersectObjects: objects is not an Array.' );\n\t\t\t\treturn intersects;\n\n\t\t\t}\n\n\t\t\tfor ( var i = 0, l = objects.length; i \u003C l; i ++ ) {\n\n\t\t\t\tintersectObject( objects[ i ], this, intersects, recursive );\n\n\t\t\t}\n\n\t\t\tintersects.sort( ascSort );\n\n\t\t\treturn intersects;\n\n\t\t}\n\n\t} );\n\n\t\u002F**\n\t * @author bhouston \u002F http:\u002F\u002Fclara.io\n\t * @author WestLangley \u002F http:\u002F\u002Fgithub.com\u002FWestLangley\n\t *\n\t * Ref: https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FSpherical_coordinate_system\n\t *\n\t * The polar angle (phi) is measured from the positive y-axis. The positive y-axis is up.\n\t * The azimuthal angle (theta) is measured from the positive z-axiz.\n\t *\u002F\n\n\tfunction Spherical( radius, phi, theta ) {\n\n\t\tthis.radius = ( radius !== undefined ) ? radius : 1.0;\n\t\tthis.phi = ( phi !== undefined ) ? phi : 0; \u002F\u002F polar angle\n\t\tthis.theta = ( theta !== undefined ) ? theta : 0; \u002F\u002F azimuthal angle\n\n\t\treturn this;\n\n\t}\n\n\tObject.assign( Spherical.prototype, {\n\n\t\tset: function ( radius, phi, theta ) {\n\n\t\t\tthis.radius = radius;\n\t\t\tthis.phi = phi;\n\t\t\tthis.theta = theta;\n\n\t\t\treturn this;\n\n\t\t},\n\n\t\tclone: function () {\n\n\t\t\treturn new this.constructor().copy( this );\n\n\t\t},\n\n\t\tcopy: function ( other ) {\n\n\t\t\tthis.radius = other.radius;\n\t\t\tthis.phi = other.phi;\n\t\t\tthis.theta = other.theta;\n\n\t\t\treturn this;\n\n\t\t},\n\n\t\t\u002F\u002F restrict phi to be betwee EPS and PI-EPS\n\t\tmakeSafe: function () {\n\n\t\t\tvar EPS = 0.000001;\n\t\t\tthis.phi = Math.max( EPS, Math.min( Math.PI - EPS, this.phi ) );\n\n\t\t\treturn this;\n\n\t\t},\n\n\t\tsetFromVector3: function ( v ) {\n\n\t\t\treturn this.setFromCartesianCoords( v.x, v.y, v.z );\n\n\t\t},\n\n\t\tsetFromCartesianCoords: function ( x, y, z ) {\n\n\t\t\tthis.radius = Math.sqrt( x * x + y * y + z * z );\n\n\t\t\tif ( this.radius === 0 ) {\n\n\t\t\t\tthis.theta = 0;\n\t\t\t\tthis.phi = 0;\n\n\t\t\t} else {\n\n\t\t\t\tthis.theta = Math.atan2( x, z );\n\t\t\t\tthis.phi = Math.acos( _Math.clamp( y \u002F this.radius, - 1, 1 ) );\n\n\t\t\t}\n\n\t\t\treturn this;\n\n\t\t}\n\n\t} );\n\n\t\u002F**\n\t * @author Mugen87 \u002F https:\u002F\u002Fgithub.com\u002FMugen87\n\t *\n\t * Ref: https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FCylindrical_coordinate_system\n\t *\n\t *\u002F\n\n\tfunction Cylindrical( radius, theta, y ) {\n\n\t\tthis.radius = ( radius !== undefined ) ? radius : 1.0; \u002F\u002F distance from the origin to a point in the x-z plane\n\t\tthis.theta = ( theta !== undefined ) ? theta : 0; \u002F\u002F counterclockwise angle in the x-z plane measured in radians from the positive z-axis\n\t\tthis.y = ( y !== undefined ) ? y : 0; \u002F\u002F height above the x-z plane\n\n\t\treturn this;\n\n\t}\n\n\tObject.assign( Cylindrical.prototype, {\n\n\t\tset: function ( radius, theta, y ) {\n\n\t\t\tthis.radius = radius;\n\t\t\tthis.theta = theta;\n\t\t\tthis.y = y;\n\n\t\t\treturn this;\n\n\t\t},\n\n\t\tclone: function () {\n\n\t\t\treturn new this.constructor().copy( this );\n\n\t\t},\n\n\t\tcopy: function ( other ) {\n\n\t\t\tthis.radius = other.radius;\n\t\t\tthis.theta = other.theta;\n\t\t\tthis.y = other.y;\n\n\t\t\treturn this;\n\n\t\t},\n\n\t\tsetFromVector3: function ( v ) {\n\n\t\t\treturn this.setFromCartesianCoords( v.x, v.y, v.z );\n\n\t\t},\n\n\t\tsetFromCartesianCoords: function ( x, y, z ) {\n\n\t\t\tthis.radius = Math.sqrt( x * x + z * z );\n\t\t\tthis.theta = Math.atan2( x, z );\n\t\t\tthis.y = y;\n\n\t\t\treturn this;\n\n\t\t}\n\n\t} );\n\n\t\u002F**\n\t * @author bhouston \u002F http:\u002F\u002Fclara.io\n\t *\u002F\n\n\tfunction Box2( min, max ) {\n\n\t\tthis.min = ( min !== undefined ) ? min : new Vector2( + Infinity, + Infinity );\n\t\tthis.max = ( max !== undefined ) ? max : new Vector2( - Infinity, - Infinity );\n\n\t}\n\n\tObject.assign( Box2.prototype, {\n\n\t\tset: function ( min, max ) {\n\n\t\t\tthis.min.copy( min );\n\t\t\tthis.max.copy( max );\n\n\t\t\treturn this;\n\n\t\t},\n\n\t\tsetFromPoints: function ( points ) {\n\n\t\t\tthis.makeEmpty();\n\n\t\t\tfor ( var i = 0, il = points.length; i \u003C il; i ++ ) {\n\n\t\t\t\tthis.expandByPoint( points[ i ] );\n\n\t\t\t}\n\n\t\t\treturn this;\n\n\t\t},\n\n\t\tsetFromCenterAndSize: function () {\n\n\t\t\tvar v1 = new Vector2();\n\n\t\t\treturn function setFromCenterAndSize( center, size ) {\n\n\t\t\t\tvar halfSize = v1.copy( size ).multiplyScalar( 0.5 );\n\t\t\t\tthis.min.copy( center ).sub( halfSize );\n\t\t\t\tthis.max.copy( center ).add( halfSize );\n\n\t\t\t\treturn this;\n\n\t\t\t};\n\n\t\t}(),\n\n\t\tclone: function () {\n\n\t\t\treturn new this.constructor().copy( this );\n\n\t\t},\n\n\t\tcopy: function ( box ) {\n\n\t\t\tthis.min.copy( box.min );\n\t\t\tthis.max.copy( box.max );\n\n\t\t\treturn this;\n\n\t\t},\n\n\t\tmakeEmpty: function () {\n\n\t\t\tthis.min.x = this.min.y = + Infinity;\n\t\t\tthis.max.x = this.max.y = - Infinity;\n\n\t\t\treturn this;\n\n\t\t},\n\n\t\tisEmpty: function () {\n\n\t\t\t\u002F\u002F this is a more robust check for empty than ( volume \u003C= 0 ) because volume can get positive with two negative axes\n\n\t\t\treturn ( this.max.x \u003C this.min.x ) || ( this.max.y \u003C this.min.y );\n\n\t\t},\n\n\t\tgetCenter: function ( target ) {\n\n\t\t\tif ( target === undefined ) {\n\n\t\t\t\tconsole.warn( 'THREE.Box2: .getCenter() target is now required' );\n\t\t\t\ttarget = new Vector2();\n\n\t\t\t}\n\n\t\t\treturn this.isEmpty() ? target.set( 0, 0 ) : target.addVectors( this.min, this.max ).multiplyScalar( 0.5 );\n\n\t\t},\n\n\t\tgetSize: function ( target ) {\n\n\t\t\tif ( target === undefined ) {\n\n\t\t\t\tconsole.warn( 'THREE.Box2: .getSize() target is now required' );\n\t\t\t\ttarget = new Vector2();\n\n\t\t\t}\n\n\t\t\treturn this.isEmpty() ? target.set( 0, 0 ) : target.subVectors( this.max, this.min );\n\n\t\t},\n\n\t\texpandByPoint: function ( point ) {\n\n\t\t\tthis.min.min( point );\n\t\t\tthis.max.max( point );\n\n\t\t\treturn this;\n\n\t\t},\n\n\t\texpandByVector: function ( vector ) {\n\n\t\t\tthis.min.sub( vector );\n\t\t\tthis.max.add( vector );\n\n\t\t\treturn this;\n\n\t\t},\n\n\t\texpandByScalar: function ( scalar ) {\n\n\t\t\tthis.min.addScalar( - scalar );\n\t\t\tthis.max.addScalar( scalar );\n\n\t\t\treturn this;\n\n\t\t},\n\n\t\tcontainsPoint: function ( point ) {\n\n\t\t\treturn point.x \u003C this.min.x || point.x \u003E this.max.x ||\n\t\t\t\tpoint.y \u003C this.min.y || point.y \u003E this.max.y ? false : true;\n\n\t\t},\n\n\t\tcontainsBox: function ( box ) {\n\n\t\t\treturn this.min.x \u003C= box.min.x && box.max.x \u003C= this.max.x &&\n\t\t\t\tthis.min.y \u003C= box.min.y && box.max.y \u003C= this.max.y;\n\n\t\t},\n\n\t\tgetParameter: function ( point, target ) {\n\n\t\t\t\u002F\u002F This can potentially have a divide by zero if the box\n\t\t\t\u002F\u002F has a size dimension of 0.\n\n\t\t\tif ( target === undefined ) {\n\n\t\t\t\tconsole.warn( 'THREE.Box2: .getParameter() target is now required' );\n\t\t\t\ttarget = new Vector2();\n\n\t\t\t}\n\n\t\t\treturn target.set(\n\t\t\t\t( point.x - this.min.x ) \u002F ( this.max.x - this.min.x ),\n\t\t\t\t( point.y - this.min.y ) \u002F ( this.max.y - this.min.y )\n\t\t\t);\n\n\t\t},\n\n\t\tintersectsBox: function ( box ) {\n\n\t\t\t\u002F\u002F using 4 splitting planes to rule out intersections\n\n\t\t\treturn box.max.x \u003C this.min.x || box.min.x \u003E this.max.x ||\n\t\t\t\tbox.max.y \u003C this.min.y || box.min.y \u003E this.max.y ? false : true;\n\n\t\t},\n\n\t\tclampPoint: function ( point, target ) {\n\n\t\t\tif ( target === undefined ) {\n\n\t\t\t\tconsole.warn( 'THREE.Box2: .clampPoint() target is now required' );\n\t\t\t\ttarget = new Vector2();\n\n\t\t\t}\n\n\t\t\treturn target.copy( point ).clamp( this.min, this.max );\n\n\t\t},\n\n\t\tdistanceToPoint: function () {\n\n\t\t\tvar v1 = new Vector2();\n\n\t\t\treturn function distanceToPoint( point ) {\n\n\t\t\t\tvar clampedPoint = v1.copy( point ).clamp( this.min, this.max );\n\t\t\t\treturn clampedPoint.sub( point ).length();\n\n\t\t\t};\n\n\t\t}(),\n\n\t\tintersect: function ( box ) {\n\n\t\t\tthis.min.max( box.min );\n\t\t\tthis.max.min( box.max );\n\n\t\t\treturn this;\n\n\t\t},\n\n\t\tunion: function ( box ) {\n\n\t\t\tthis.min.min( box.min );\n\t\t\tthis.max.max( box.max );\n\n\t\t\treturn this;\n\n\t\t},\n\n\t\ttranslate: function ( offset ) {\n\n\t\t\tthis.min.add( offset );\n\t\t\tthis.max.add( offset );\n\n\t\t\treturn this;\n\n\t\t},\n\n\t\tequals: function ( box ) {\n\n\t\t\treturn box.min.equals( this.min ) && box.max.equals( this.max );\n\n\t\t}\n\n\t} );\n\n\t\u002F**\n\t * @author bhouston \u002F http:\u002F\u002Fclara.io\n\t *\u002F\n\n\tfunction Line3( start, end ) {\n\n\t\tthis.start = ( start !== undefined ) ? start : new Vector3();\n\t\tthis.end = ( end !== undefined ) ? end : new Vector3();\n\n\t}\n\n\tObject.assign( Line3.prototype, {\n\n\t\tset: function ( start, end ) {\n\n\t\t\tthis.start.copy( start );\n\t\t\tthis.end.copy( end );\n\n\t\t\treturn this;\n\n\t\t},\n\n\t\tclone: function () {\n\n\t\t\treturn new this.constructor().copy( this );\n\n\t\t},\n\n\t\tcopy: function ( line ) {\n\n\t\t\tthis.start.copy( line.start );\n\t\t\tthis.end.copy( line.end );\n\n\t\t\treturn this;\n\n\t\t},\n\n\t\tgetCenter: function ( target ) {\n\n\t\t\tif ( target === undefined ) {\n\n\t\t\t\tconsole.warn( 'THREE.Line3: .getCenter() target is now required' );\n\t\t\t\ttarget = new Vector3();\n\n\t\t\t}\n\n\t\t\treturn target.addVectors( this.start, this.end ).multiplyScalar( 0.5 );\n\n\t\t},\n\n\t\tdelta: function ( target ) {\n\n\t\t\tif ( target === undefined ) {\n\n\t\t\t\tconsole.warn( 'THREE.Line3: .delta() target is now required' );\n\t\t\t\ttarget = new Vector3();\n\n\t\t\t}\n\n\t\t\treturn target.subVectors( this.end, this.start );\n\n\t\t},\n\n\t\tdistanceSq: function () {\n\n\t\t\treturn this.start.distanceToSquared( this.end );\n\n\t\t},\n\n\t\tdistance: function () {\n\n\t\t\treturn this.start.distanceTo( this.end );\n\n\t\t},\n\n\t\tat: function ( t, target ) {\n\n\t\t\tif ( target === undefined ) {\n\n\t\t\t\tconsole.warn( 'THREE.Line3: .at() target is now required' );\n\t\t\t\ttarget = new Vector3();\n\n\t\t\t}\n\n\t\t\treturn this.delta( target ).multiplyScalar( t ).add( this.start );\n\n\t\t},\n\n\t\tclosestPointToPointParameter: function () {\n\n\t\t\tvar startP = new Vector3();\n\t\t\tvar startEnd = new Vector3();\n\n\t\t\treturn function closestPointToPointParameter( point, clampToLine ) {\n\n\t\t\t\tstartP.subVectors( point, this.start );\n\t\t\t\tstartEnd.subVectors( this.end, this.start );\n\n\t\t\t\tvar startEnd2 = startEnd.dot( startEnd );\n\t\t\t\tvar startEnd_startP = startEnd.dot( startP );\n\n\t\t\t\tvar t = startEnd_startP \u002F startEnd2;\n\n\t\t\t\tif ( clampToLine ) {\n\n\t\t\t\t\tt = _Math.clamp( t, 0, 1 );\n\n\t\t\t\t}\n\n\t\t\t\treturn t;\n\n\t\t\t};\n\n\t\t}(),\n\n\t\tclosestPointToPoint: function ( point, clampToLine, target ) {\n\n\t\t\tvar t = this.closestPointToPointParameter( point, clampToLine );\n\n\t\t\tif ( target === undefined ) {\n\n\t\t\t\tconsole.warn( 'THREE.Line3: .closestPointToPoint() target is now required' );\n\t\t\t\ttarget = new Vector3();\n\n\t\t\t}\n\n\t\t\treturn this.delta( target ).multiplyScalar( t ).add( this.start );\n\n\t\t},\n\n\t\tapplyMatrix4: function ( matrix ) {\n\n\t\t\tthis.start.applyMatrix4( matrix );\n\t\t\tthis.end.applyMatrix4( matrix );\n\n\t\t\treturn this;\n\n\t\t},\n\n\t\tequals: function ( line ) {\n\n\t\t\treturn line.start.equals( this.start ) && line.end.equals( this.end );\n\n\t\t}\n\n\t} );\n\n\t\u002F**\n\t * @author alteredq \u002F http:\u002F\u002Falteredqualia.com\u002F\n\t *\u002F\n\n\tfunction ImmediateRenderObject( material ) {\n\n\t\tObject3D.call( this );\n\n\t\tthis.material = material;\n\t\tthis.render = function ( \u002F* renderCallback *\u002F ) {};\n\n\t}\n\n\tImmediateRenderObject.prototype = Object.create( Object3D.prototype );\n\tImmediateRenderObject.prototype.constructor = ImmediateRenderObject;\n\n\tImmediateRenderObject.prototype.isImmediateRenderObject = true;\n\n\t\u002F**\n\t * @author mrdoob \u002F http:\u002F\u002Fmrdoob.com\u002F\n\t * @author WestLangley \u002F http:\u002F\u002Fgithub.com\u002FWestLangley\n\t *\u002F\n\n\tfunction VertexNormalsHelper( object, size, hex, linewidth ) {\n\n\t\tthis.object = object;\n\n\t\tthis.size = ( size !== undefined ) ? size : 1;\n\n\t\tvar color = ( hex !== undefined ) ? hex : 0xff0000;\n\n\t\tvar width = ( linewidth !== undefined ) ? linewidth : 1;\n\n\t\t\u002F\u002F\n\n\t\tvar nNormals = 0;\n\n\t\tvar objGeometry = this.object.geometry;\n\n\t\tif ( objGeometry && objGeometry.isGeometry ) {\n\n\t\t\tnNormals = objGeometry.faces.length * 3;\n\n\t\t} else if ( objGeometry && objGeometry.isBufferGeometry ) {\n\n\t\t\tnNormals = objGeometry.attributes.normal.count;\n\n\t\t}\n\n\t\t\u002F\u002F\n\n\t\tvar geometry = new BufferGeometry();\n\n\t\tvar positions = new Float32BufferAttribute( nNormals * 2 * 3, 3 );\n\n\t\tgeometry.addAttribute( 'position', positions );\n\n\t\tLineSegments.call( this, geometry, new LineBasicMaterial( { color: color, linewidth: width } ) );\n\n\t\t\u002F\u002F\n\n\t\tthis.matrixAutoUpdate = false;\n\n\t\tthis.update();\n\n\t}\n\n\tVertexNormalsHelper.prototype = Object.create( LineSegments.prototype );\n\tVertexNormalsHelper.prototype.constructor = VertexNormalsHelper;\n\n\tVertexNormalsHelper.prototype.update = ( function () {\n\n\t\tvar v1 = new Vector3();\n\t\tvar v2 = new Vector3();\n\t\tvar normalMatrix = new Matrix3();\n\n\t\treturn function update() {\n\n\t\t\tvar keys = [ 'a', 'b', 'c' ];\n\n\t\t\tthis.object.updateMatrixWorld( true );\n\n\t\t\tnormalMatrix.getNormalMatrix( this.object.matrixWorld );\n\n\t\t\tvar matrixWorld = this.object.matrixWorld;\n\n\t\t\tvar position = this.geometry.attributes.position;\n\n\t\t\t\u002F\u002F\n\n\t\t\tvar objGeometry = this.object.geometry;\n\n\t\t\tif ( objGeometry && objGeometry.isGeometry ) {\n\n\t\t\t\tvar vertices = objGeometry.vertices;\n\n\t\t\t\tvar faces = objGeometry.faces;\n\n\t\t\t\tvar idx = 0;\n\n\t\t\t\tfor ( var i = 0, l = faces.length; i \u003C l; i ++ ) {\n\n\t\t\t\t\tvar face = faces[ i ];\n\n\t\t\t\t\tfor ( var j = 0, jl = face.vertexNormals.length; j \u003C jl; j ++ ) {\n\n\t\t\t\t\t\tvar vertex = vertices[ face[ keys[ j ] ] ];\n\n\t\t\t\t\t\tvar normal = face.vertexNormals[ j ];\n\n\t\t\t\t\t\tv1.copy( vertex ).applyMatrix4( matrixWorld );\n\n\t\t\t\t\t\tv2.copy( normal ).applyMatrix3( normalMatrix ).normalize().multiplyScalar( this.size ).add( v1 );\n\n\t\t\t\t\t\tposition.setXYZ( idx, v1.x, v1.y, v1.z );\n\n\t\t\t\t\t\tidx = idx + 1;\n\n\t\t\t\t\t\tposition.setXYZ( idx, v2.x, v2.y, v2.z );\n\n\t\t\t\t\t\tidx = idx + 1;\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t} else if ( objGeometry && objGeometry.isBufferGeometry ) {\n\n\t\t\t\tvar objPos = objGeometry.attributes.position;\n\n\t\t\t\tvar objNorm = objGeometry.attributes.normal;\n\n\t\t\t\tvar idx = 0;\n\n\t\t\t\t\u002F\u002F for simplicity, ignore index and drawcalls, and render every normal\n\n\t\t\t\tfor ( var j = 0, jl = objPos.count; j \u003C jl; j ++ ) {\n\n\t\t\t\t\tv1.set( objPos.getX( j ), objPos.getY( j ), objPos.getZ( j ) ).applyMatrix4( matrixWorld );\n\n\t\t\t\t\tv2.set( objNorm.getX( j ), objNorm.getY( j ), objNorm.getZ( j ) );\n\n\t\t\t\t\tv2.applyMatrix3( normalMatrix ).normalize().multiplyScalar( this.size ).add( v1 );\n\n\t\t\t\t\tposition.setXYZ( idx, v1.x, v1.y, v1.z );\n\n\t\t\t\t\tidx = idx + 1;\n\n\t\t\t\t\tposition.setXYZ( idx, v2.x, v2.y, v2.z );\n\n\t\t\t\t\tidx = idx + 1;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tposition.needsUpdate = true;\n\n\t\t};\n\n\t}() );\n\n\t\u002F**\n\t * @author alteredq \u002F http:\u002F\u002Falteredqualia.com\u002F\n\t * @author mrdoob \u002F http:\u002F\u002Fmrdoob.com\u002F\n\t * @author WestLangley \u002F http:\u002F\u002Fgithub.com\u002FWestLangley\n\t *\u002F\n\n\tfunction SpotLightHelper( light, color ) {\n\n\t\tObject3D.call( this );\n\n\t\tthis.light = light;\n\t\tthis.light.updateMatrixWorld();\n\n\t\tthis.matrix = light.matrixWorld;\n\t\tthis.matrixAutoUpdate = false;\n\n\t\tthis.color = color;\n\n\t\tvar geometry = new BufferGeometry();\n\n\t\tvar positions = [\n\t\t\t0, 0, 0, \t0, 0, 1,\n\t\t\t0, 0, 0, \t1, 0, 1,\n\t\t\t0, 0, 0,\t- 1, 0, 1,\n\t\t\t0, 0, 0, \t0, 1, 1,\n\t\t\t0, 0, 0, \t0, - 1, 1\n\t\t];\n\n\t\tfor ( var i = 0, j = 1, l = 32; i \u003C l; i ++, j ++ ) {\n\n\t\t\tvar p1 = ( i \u002F l ) * Math.PI * 2;\n\t\t\tvar p2 = ( j \u002F l ) * Math.PI * 2;\n\n\t\t\tpositions.push(\n\t\t\t\tMath.cos( p1 ), Math.sin( p1 ), 1,\n\t\t\t\tMath.cos( p2 ), Math.sin( p2 ), 1\n\t\t\t);\n\n\t\t}\n\n\t\tgeometry.addAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );\n\n\t\tvar material = new LineBasicMaterial( { fog: false } );\n\n\t\tthis.cone = new LineSegments( geometry, material );\n\t\tthis.add( this.cone );\n\n\t\tthis.update();\n\n\t}\n\n\tSpotLightHelper.prototype = Object.create( Object3D.prototype );\n\tSpotLightHelper.prototype.constructor = SpotLightHelper;\n\n\tSpotLightHelper.prototype.dispose = function () {\n\n\t\tthis.cone.geometry.dispose();\n\t\tthis.cone.material.dispose();\n\n\t};\n\n\tSpotLightHelper.prototype.update = function () {\n\n\t\tvar vector = new Vector3();\n\n\t\treturn function update() {\n\n\t\t\tthis.light.updateMatrixWorld();\n\n\t\t\tvar coneLength = this.light.distance ? this.light.distance : 1000;\n\t\t\tvar coneWidth = coneLength * Math.tan( this.light.angle );\n\n\t\t\tthis.cone.scale.set( coneWidth, coneWidth, coneLength );\n\n\t\t\tvector.setFromMatrixPosition( this.light.target.matrixWorld );\n\n\t\t\tthis.cone.lookAt( vector );\n\n\t\t\tif ( this.color !== undefined ) {\n\n\t\t\t\tthis.cone.material.color.set( this.color );\n\n\t\t\t} else {\n\n\t\t\t\tthis.cone.material.color.copy( this.light.color );\n\n\t\t\t}\n\n\t\t};\n\n\t}();\n\n\t\u002F**\n\t * @author Sean Griffin \u002F http:\u002F\u002Ftwitter.com\u002Fsgrif\n\t * @author Michael Guerrero \u002F http:\u002F\u002Frealitymeltdown.com\n\t * @author mrdoob \u002F http:\u002F\u002Fmrdoob.com\u002F\n\t * @author ikerr \u002F http:\u002F\u002Fverold.com\n\t * @author Mugen87 \u002F https:\u002F\u002Fgithub.com\u002FMugen87\n\t *\u002F\n\n\tfunction getBoneList( object ) {\n\n\t\tvar boneList = [];\n\n\t\tif ( object && object.isBone ) {\n\n\t\t\tboneList.push( object );\n\n\t\t}\n\n\t\tfor ( var i = 0; i \u003C object.children.length; i ++ ) {\n\n\t\t\tboneList.push.apply( boneList, getBoneList( object.children[ i ] ) );\n\n\t\t}\n\n\t\treturn boneList;\n\n\t}\n\n\tfunction SkeletonHelper( object ) {\n\n\t\tvar bones = getBoneList( object );\n\n\t\tvar geometry = new BufferGeometry();\n\n\t\tvar vertices = [];\n\t\tvar colors = [];\n\n\t\tvar color1 = new Color( 0, 0, 1 );\n\t\tvar color2 = new Color( 0, 1, 0 );\n\n\t\tfor ( var i = 0; i \u003C bones.length; i ++ ) {\n\n\t\t\tvar bone = bones[ i ];\n\n\t\t\tif ( bone.parent && bone.parent.isBone ) {\n\n\t\t\t\tvertices.push( 0, 0, 0 );\n\t\t\t\tvertices.push( 0, 0, 0 );\n\t\t\t\tcolors.push( color1.r, color1.g, color1.b );\n\t\t\t\tcolors.push( color2.r, color2.g, color2.b );\n\n\t\t\t}\n\n\t\t}\n\n\t\tgeometry.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );\n\t\tgeometry.addAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );\n\n\t\tvar material = new LineBasicMaterial( { vertexColors: VertexColors, depthTest: false, depthWrite: false, transparent: true } );\n\n\t\tLineSegments.call( this, geometry, material );\n\n\t\tthis.root = object;\n\t\tthis.bones = bones;\n\n\t\tthis.matrix = object.matrixWorld;\n\t\tthis.matrixAutoUpdate = false;\n\n\t}\n\n\tSkeletonHelper.prototype = Object.create( LineSegments.prototype );\n\tSkeletonHelper.prototype.constructor = SkeletonHelper;\n\n\tSkeletonHelper.prototype.updateMatrixWorld = function () {\n\n\t\tvar vector = new Vector3();\n\n\t\tvar boneMatrix = new Matrix4();\n\t\tvar matrixWorldInv = new Matrix4();\n\n\t\treturn function updateMatrixWorld( force ) {\n\n\t\t\tvar bones = this.bones;\n\n\t\t\tvar geometry = this.geometry;\n\t\t\tvar position = geometry.getAttribute( 'position' );\n\n\t\t\tmatrixWorldInv.getInverse( this.root.matrixWorld );\n\n\t\t\tfor ( var i = 0, j = 0; i \u003C bones.length; i ++ ) {\n\n\t\t\t\tvar bone = bones[ i ];\n\n\t\t\t\tif ( bone.parent && bone.parent.isBone ) {\n\n\t\t\t\t\tboneMatrix.multiplyMatrices( matrixWorldInv, bone.matrixWorld );\n\t\t\t\t\tvector.setFromMatrixPosition( boneMatrix );\n\t\t\t\t\tposition.setXYZ( j, vector.x, vector.y, vector.z );\n\n\t\t\t\t\tboneMatrix.multiplyMatrices( matrixWorldInv, bone.parent.matrixWorld );\n\t\t\t\t\tvector.setFromMatrixPosition( boneMatrix );\n\t\t\t\t\tposition.setXYZ( j + 1, vector.x, vector.y, vector.z );\n\n\t\t\t\t\tj += 2;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tgeometry.getAttribute( 'position' ).needsUpdate = true;\n\n\t\t\tObject3D.prototype.updateMatrixWorld.call( this, force );\n\n\t\t};\n\n\t}();\n\n\t\u002F**\n\t * @author alteredq \u002F http:\u002F\u002Falteredqualia.com\u002F\n\t * @author mrdoob \u002F http:\u002F\u002Fmrdoob.com\u002F\n\t *\u002F\n\n\tfunction PointLightHelper( light, sphereSize, color ) {\n\n\t\tthis.light = light;\n\t\tthis.light.updateMatrixWorld();\n\n\t\tthis.color = color;\n\n\t\tvar geometry = new SphereBufferGeometry( sphereSize, 4, 2 );\n\t\tvar material = new MeshBasicMaterial( { wireframe: true, fog: false } );\n\n\t\tMesh.call( this, geometry, material );\n\n\t\tthis.matrix = this.light.matrixWorld;\n\t\tthis.matrixAutoUpdate = false;\n\n\t\tthis.update();\n\n\n\t\t\u002F*\n\t\tvar distanceGeometry = new THREE.IcosahedronBufferGeometry( 1, 2 );\n\t\tvar distanceMaterial = new THREE.MeshBasicMaterial( { color: hexColor, fog: false, wireframe: true, opacity: 0.1, transparent: true } );\n\n\t\tthis.lightSphere = new THREE.Mesh( bulbGeometry, bulbMaterial );\n\t\tthis.lightDistance = new THREE.Mesh( distanceGeometry, distanceMaterial );\n\n\t\tvar d = light.distance;\n\n\t\tif ( d === 0.0 ) {\n\n\t\t\tthis.lightDistance.visible = false;\n\n\t\t} else {\n\n\t\t\tthis.lightDistance.scale.set( d, d, d );\n\n\t\t}\n\n\t\tthis.add( this.lightDistance );\n\t\t*\u002F\n\n\t}\n\n\tPointLightHelper.prototype = Object.create( Mesh.prototype );\n\tPointLightHelper.prototype.constructor = PointLightHelper;\n\n\tPointLightHelper.prototype.dispose = function () {\n\n\t\tthis.geometry.dispose();\n\t\tthis.material.dispose();\n\n\t};\n\n\tPointLightHelper.prototype.update = function () {\n\n\t\tif ( this.color !== undefined ) {\n\n\t\t\tthis.material.color.set( this.color );\n\n\t\t} else {\n\n\t\t\tthis.material.color.copy( this.light.color );\n\n\t\t}\n\n\t\t\u002F*\n\t\tvar d = this.light.distance;\n\n\t\tif ( d === 0.0 ) {\n\n\t\t\tthis.lightDistance.visible = false;\n\n\t\t} else {\n\n\t\t\tthis.lightDistance.visible = true;\n\t\t\tthis.lightDistance.scale.set( d, d, d );\n\n\t\t}\n\t\t*\u002F\n\n\t};\n\n\t\u002F**\n\t * @author abelnation \u002F http:\u002F\u002Fgithub.com\u002Fabelnation\n\t * @author Mugen87 \u002F http:\u002F\u002Fgithub.com\u002FMugen87\n\t * @author WestLangley \u002F http:\u002F\u002Fgithub.com\u002FWestLangley\n\t *\n\t * This helper must be added as a child of the light\n\t *\u002F\n\n\tfunction RectAreaLightHelper( light, color ) {\n\n\t\tthis.type = 'RectAreaLightHelper';\n\n\t\tthis.light = light;\n\n\t\tthis.color = color; \u002F\u002F optional hardwired color for the helper\n\n\t\tvar positions = [ 1, 1, 0, - 1, 1, 0, - 1, - 1, 0, 1, - 1, 0, 1, 1, 0 ];\n\n\t\tvar geometry = new BufferGeometry();\n\t\tgeometry.addAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );\n\t\tgeometry.computeBoundingSphere();\n\n\t\tvar material = new LineBasicMaterial( { fog: false } );\n\n\t\tLine.call( this, geometry, material );\n\n\t\t\u002F\u002F\n\n\t\tvar positions2 = [ 1, 1, 0, - 1, 1, 0, - 1, - 1, 0, 1, 1, 0, - 1, - 1, 0, 1, - 1, 0 ];\n\n\t\tvar geometry2 = new BufferGeometry();\n\t\tgeometry2.addAttribute( 'position', new Float32BufferAttribute( positions2, 3 ) );\n\t\tgeometry2.computeBoundingSphere();\n\n\t\tthis.add( new Mesh( geometry2, new MeshBasicMaterial( { side: BackSide, fog: false } ) ) );\n\n\t\tthis.update();\n\n\t}\n\n\tRectAreaLightHelper.prototype = Object.create( Line.prototype );\n\tRectAreaLightHelper.prototype.constructor = RectAreaLightHelper;\n\n\tRectAreaLightHelper.prototype.update = function () {\n\n\t\tthis.scale.set( 0.5 * this.light.width, 0.5 * this.light.height, 1 );\n\n\t\tif ( this.color !== undefined ) {\n\n\t\t\tthis.material.color.set( this.color );\n\t\t\tthis.children[ 0 ].material.color.set( this.color );\n\n\t\t} else {\n\n\t\t\tthis.material.color.copy( this.light.color ).multiplyScalar( this.light.intensity );\n\n\t\t\t\u002F\u002F prevent hue shift\n\t\t\tvar c = this.material.color;\n\t\t\tvar max = Math.max( c.r, c.g, c.b );\n\t\t\tif ( max \u003E 1 ) c.multiplyScalar( 1 \u002F max );\n\n\t\t\tthis.children[ 0 ].material.color.copy( this.material.color );\n\n\t\t}\n\n\t};\n\n\tRectAreaLightHelper.prototype.dispose = function () {\n\n\t\tthis.geometry.dispose();\n\t\tthis.material.dispose();\n\t\tthis.children[ 0 ].geometry.dispose();\n\t\tthis.children[ 0 ].material.dispose();\n\n\t};\n\n\t\u002F**\n\t * @author alteredq \u002F http:\u002F\u002Falteredqualia.com\u002F\n\t * @author mrdoob \u002F http:\u002F\u002Fmrdoob.com\u002F\n\t * @author Mugen87 \u002F https:\u002F\u002Fgithub.com\u002FMugen87\n\t *\u002F\n\n\tfunction HemisphereLightHelper( light, size, color ) {\n\n\t\tObject3D.call( this );\n\n\t\tthis.light = light;\n\t\tthis.light.updateMatrixWorld();\n\n\t\tthis.matrix = light.matrixWorld;\n\t\tthis.matrixAutoUpdate = false;\n\n\t\tthis.color = color;\n\n\t\tvar geometry = new OctahedronBufferGeometry( size );\n\t\tgeometry.rotateY( Math.PI * 0.5 );\n\n\t\tthis.material = new MeshBasicMaterial( { wireframe: true, fog: false } );\n\t\tif ( this.color === undefined ) this.material.vertexColors = VertexColors;\n\n\t\tvar position = geometry.getAttribute( 'position' );\n\t\tvar colors = new Float32Array( position.count * 3 );\n\n\t\tgeometry.addAttribute( 'color', new BufferAttribute( colors, 3 ) );\n\n\t\tthis.add( new Mesh( geometry, this.material ) );\n\n\t\tthis.update();\n\n\t}\n\n\tHemisphereLightHelper.prototype = Object.create( Object3D.prototype );\n\tHemisphereLightHelper.prototype.constructor = HemisphereLightHelper;\n\n\tHemisphereLightHelper.prototype.dispose = function () {\n\n\t\tthis.children[ 0 ].geometry.dispose();\n\t\tthis.children[ 0 ].material.dispose();\n\n\t};\n\n\tHemisphereLightHelper.prototype.update = function () {\n\n\t\tvar vector = new Vector3();\n\n\t\tvar color1 = new Color();\n\t\tvar color2 = new Color();\n\n\t\treturn function update() {\n\n\t\t\tvar mesh = this.children[ 0 ];\n\n\t\t\tif ( this.color !== undefined ) {\n\n\t\t\t\tthis.material.color.set( this.color );\n\n\t\t\t} else {\n\n\t\t\t\tvar colors = mesh.geometry.getAttribute( 'color' );\n\n\t\t\t\tcolor1.copy( this.light.color );\n\t\t\t\tcolor2.copy( this.light.groundColor );\n\n\t\t\t\tfor ( var i = 0, l = colors.count; i \u003C l; i ++ ) {\n\n\t\t\t\t\tvar color = ( i \u003C ( l \u002F 2 ) ) ? color1 : color2;\n\n\t\t\t\t\tcolors.setXYZ( i, color.r, color.g, color.b );\n\n\t\t\t\t}\n\n\t\t\t\tcolors.needsUpdate = true;\n\n\t\t\t}\n\n\t\t\tmesh.lookAt( vector.setFromMatrixPosition( this.light.matrixWorld ).negate() );\n\n\t\t};\n\n\t}();\n\n\t\u002F**\n\t * @author mrdoob \u002F http:\u002F\u002Fmrdoob.com\u002F\n\t *\u002F\n\n\tfunction GridHelper( size, divisions, color1, color2 ) {\n\n\t\tsize = size || 10;\n\t\tdivisions = divisions || 10;\n\t\tcolor1 = new Color( color1 !== undefined ? color1 : 0x444444 );\n\t\tcolor2 = new Color( color2 !== undefined ? color2 : 0x888888 );\n\n\t\tvar center = divisions \u002F 2;\n\t\tvar step = size \u002F divisions;\n\t\tvar halfSize = size \u002F 2;\n\n\t\tvar vertices = [], colors = [];\n\n\t\tfor ( var i = 0, j = 0, k = - halfSize; i \u003C= divisions; i ++, k += step ) {\n\n\t\t\tvertices.push( - halfSize, 0, k, halfSize, 0, k );\n\t\t\tvertices.push( k, 0, - halfSize, k, 0, halfSize );\n\n\t\t\tvar color = i === center ? color1 : color2;\n\n\t\t\tcolor.toArray( colors, j ); j += 3;\n\t\t\tcolor.toArray( colors, j ); j += 3;\n\t\t\tcolor.toArray( colors, j ); j += 3;\n\t\t\tcolor.toArray( colors, j ); j += 3;\n\n\t\t}\n\n\t\tvar geometry = new BufferGeometry();\n\t\tgeometry.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );\n\t\tgeometry.addAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );\n\n\t\tvar material = new LineBasicMaterial( { vertexColors: VertexColors } );\n\n\t\tLineSegments.call( this, geometry, material );\n\n\t}\n\n\tGridHelper.prototype = Object.create( LineSegments.prototype );\n\tGridHelper.prototype.constructor = GridHelper;\n\n\t\u002F**\n\t * @author mrdoob \u002F http:\u002F\u002Fmrdoob.com\u002F\n\t * @author Mugen87 \u002F http:\u002F\u002Fgithub.com\u002FMugen87\n\t * @author Hectate \u002F http:\u002F\u002Fwww.github.com\u002FHectate\n\t *\u002F\n\n\tfunction PolarGridHelper( radius, radials, circles, divisions, color1, color2 ) {\n\n\t\tradius = radius || 10;\n\t\tradials = radials || 16;\n\t\tcircles = circles || 8;\n\t\tdivisions = divisions || 64;\n\t\tcolor1 = new Color( color1 !== undefined ? color1 : 0x444444 );\n\t\tcolor2 = new Color( color2 !== undefined ? color2 : 0x888888 );\n\n\t\tvar vertices = [];\n\t\tvar colors = [];\n\n\t\tvar x, z;\n\t\tvar v, i, j, r, color;\n\n\t\t\u002F\u002F create the radials\n\n\t\tfor ( i = 0; i \u003C= radials; i ++ ) {\n\n\t\t\tv = ( i \u002F radials ) * ( Math.PI * 2 );\n\n\t\t\tx = Math.sin( v ) * radius;\n\t\t\tz = Math.cos( v ) * radius;\n\n\t\t\tvertices.push( 0, 0, 0 );\n\t\t\tvertices.push( x, 0, z );\n\n\t\t\tcolor = ( i & 1 ) ? color1 : color2;\n\n\t\t\tcolors.push( color.r, color.g, color.b );\n\t\t\tcolors.push( color.r, color.g, color.b );\n\n\t\t}\n\n\t\t\u002F\u002F create the circles\n\n\t\tfor ( i = 0; i \u003C= circles; i ++ ) {\n\n\t\t\tcolor = ( i & 1 ) ? color1 : color2;\n\n\t\t\tr = radius - ( radius \u002F circles * i );\n\n\t\t\tfor ( j = 0; j \u003C divisions; j ++ ) {\n\n\t\t\t\t\u002F\u002F first vertex\n\n\t\t\t\tv = ( j \u002F divisions ) * ( Math.PI * 2 );\n\n\t\t\t\tx = Math.sin( v ) * r;\n\t\t\t\tz = Math.cos( v ) * r;\n\n\t\t\t\tvertices.push( x, 0, z );\n\t\t\t\tcolors.push( color.r, color.g, color.b );\n\n\t\t\t\t\u002F\u002F second vertex\n\n\t\t\t\tv = ( ( j + 1 ) \u002F divisions ) * ( Math.PI * 2 );\n\n\t\t\t\tx = Math.sin( v ) * r;\n\t\t\t\tz = Math.cos( v ) * r;\n\n\t\t\t\tvertices.push( x, 0, z );\n\t\t\t\tcolors.push( color.r, color.g, color.b );\n\n\t\t\t}\n\n\t\t}\n\n\t\tvar geometry = new BufferGeometry();\n\t\tgeometry.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );\n\t\tgeometry.addAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );\n\n\t\tvar material = new LineBasicMaterial( { vertexColors: VertexColors } );\n\n\t\tLineSegments.call( this, geometry, material );\n\n\t}\n\n\tPolarGridHelper.prototype = Object.create( LineSegments.prototype );\n\tPolarGridHelper.prototype.constructor = PolarGridHelper;\n\n\t\u002F**\n\t * @author Mugen87 \u002F http:\u002F\u002Fgithub.com\u002FMugen87\n\t *\u002F\n\n\tfunction PositionalAudioHelper( audio, range, divisionsInnerAngle, divisionsOuterAngle ) {\n\n\t\tthis.audio = audio;\n\t\tthis.range = range || 1;\n\t\tthis.divisionsInnerAngle = divisionsInnerAngle || 16;\n\t\tthis.divisionsOuterAngle = divisionsOuterAngle || 2;\n\n\t\tvar geometry = new BufferGeometry();\n\t\tvar divisions = this.divisionsInnerAngle + this.divisionsOuterAngle * 2;\n\t\tvar positions = new Float32Array( ( divisions * 3 + 3 ) * 3 );\n\t\tgeometry.addAttribute( 'position', new BufferAttribute( positions, 3 ) );\n\n\t\tvar materialInnerAngle = new LineBasicMaterial( { color: 0x00ff00 } );\n\t\tvar materialOuterAngle = new LineBasicMaterial( { color: 0xffff00 } );\n\n\t\tLine.call( this, geometry, [ materialOuterAngle, materialInnerAngle ] );\n\n\t\tthis.update();\n\n\t}\n\n\tPositionalAudioHelper.prototype = Object.create( Line.prototype );\n\tPositionalAudioHelper.prototype.constructor = PositionalAudioHelper;\n\n\tPositionalAudioHelper.prototype.update = function () {\n\n\t\tvar audio = this.audio;\n\t\tvar range = this.range;\n\t\tvar divisionsInnerAngle = this.divisionsInnerAngle;\n\t\tvar divisionsOuterAngle = this.divisionsOuterAngle;\n\n\t\tvar coneInnerAngle = _Math.degToRad( audio.panner.coneInnerAngle );\n\t\tvar coneOuterAngle = _Math.degToRad( audio.panner.coneOuterAngle );\n\n\t\tvar halfConeInnerAngle = coneInnerAngle \u002F 2;\n\t\tvar halfConeOuterAngle = coneOuterAngle \u002F 2;\n\n\t\tvar start = 0;\n\t\tvar count = 0;\n\t\tvar i, stride;\n\n\t\tvar geometry = this.geometry;\n\t\tvar positionAttribute = geometry.attributes.position;\n\n\t\tgeometry.clearGroups();\n\n\t\t\u002F\u002F\n\n\t\tfunction generateSegment( from, to, divisions, materialIndex ) {\n\n\t\t\tvar step = ( to - from ) \u002F divisions;\n\n\t\t\tpositionAttribute.setXYZ( start, 0, 0, 0 );\n\t\t\tcount ++;\n\n\t\t\tfor ( i = from; i \u003C to; i += step ) {\n\n\t\t\t\tstride = start + count;\n\n\t\t\t\tpositionAttribute.setXYZ( stride, Math.sin( i ) * range, 0, Math.cos( i ) * range );\n\t\t\t\tpositionAttribute.setXYZ( stride + 1, Math.sin( Math.min( i + step, to ) ) * range, 0, Math.cos( Math.min( i + step, to ) ) * range );\n\t\t\t\tpositionAttribute.setXYZ( stride + 2, 0, 0, 0 );\n\n\t\t\t\tcount += 3;\n\n\t\t\t}\n\n\t\t\tgeometry.addGroup( start, count, materialIndex );\n\n\t\t\tstart += count;\n\t\t\tcount = 0;\n\n\t\t}\n\n\t\t\u002F\u002F\n\n\t\tgenerateSegment( - halfConeOuterAngle, - halfConeInnerAngle, divisionsOuterAngle, 0 );\n\t\tgenerateSegment( - halfConeInnerAngle, halfConeInnerAngle, divisionsInnerAngle, 1 );\n\t\tgenerateSegment( halfConeInnerAngle, halfConeOuterAngle, divisionsOuterAngle, 0 );\n\n\t\t\u002F\u002F\n\n\t\tpositionAttribute.needsUpdate = true;\n\n\t\tif ( coneInnerAngle === coneOuterAngle ) this.material[ 0 ].visible = false;\n\n\t};\n\n\tPositionalAudioHelper.prototype.dispose = function () {\n\n\t\tthis.geometry.dispose();\n\t\tthis.material[ 0 ].dispose();\n\t\tthis.material[ 1 ].dispose();\n\n\t};\n\n\t\u002F**\n\t * @author mrdoob \u002F http:\u002F\u002Fmrdoob.com\u002F\n\t * @author WestLangley \u002F http:\u002F\u002Fgithub.com\u002FWestLangley\n\t *\u002F\n\n\tfunction FaceNormalsHelper( object, size, hex, linewidth ) {\n\n\t\t\u002F\u002F FaceNormalsHelper only supports THREE.Geometry\n\n\t\tthis.object = object;\n\n\t\tthis.size = ( size !== undefined ) ? size : 1;\n\n\t\tvar color = ( hex !== undefined ) ? hex : 0xffff00;\n\n\t\tvar width = ( linewidth !== undefined ) ? linewidth : 1;\n\n\t\t\u002F\u002F\n\n\t\tvar nNormals = 0;\n\n\t\tvar objGeometry = this.object.geometry;\n\n\t\tif ( objGeometry && objGeometry.isGeometry ) {\n\n\t\t\tnNormals = objGeometry.faces.length;\n\n\t\t} else {\n\n\t\t\tconsole.warn( 'THREE.FaceNormalsHelper: only THREE.Geometry is supported. Use THREE.VertexNormalsHelper, instead.' );\n\n\t\t}\n\n\t\t\u002F\u002F\n\n\t\tvar geometry = new BufferGeometry();\n\n\t\tvar positions = new Float32BufferAttribute( nNormals * 2 * 3, 3 );\n\n\t\tgeometry.addAttribute( 'position', positions );\n\n\t\tLineSegments.call( this, geometry, new LineBasicMaterial( { color: color, linewidth: width } ) );\n\n\t\t\u002F\u002F\n\n\t\tthis.matrixAutoUpdate = false;\n\t\tthis.update();\n\n\t}\n\n\tFaceNormalsHelper.prototype = Object.create( LineSegments.prototype );\n\tFaceNormalsHelper.prototype.constructor = FaceNormalsHelper;\n\n\tFaceNormalsHelper.prototype.update = ( function () {\n\n\t\tvar v1 = new Vector3();\n\t\tvar v2 = new Vector3();\n\t\tvar normalMatrix = new Matrix3();\n\n\t\treturn function update() {\n\n\t\t\tthis.object.updateMatrixWorld( true );\n\n\t\t\tnormalMatrix.getNormalMatrix( this.object.matrixWorld );\n\n\t\t\tvar matrixWorld = this.object.matrixWorld;\n\n\t\t\tvar position = this.geometry.attributes.position;\n\n\t\t\t\u002F\u002F\n\n\t\t\tvar objGeometry = this.object.geometry;\n\n\t\t\tvar vertices = objGeometry.vertices;\n\n\t\t\tvar faces = objGeometry.faces;\n\n\t\t\tvar idx = 0;\n\n\t\t\tfor ( var i = 0, l = faces.length; i \u003C l; i ++ ) {\n\n\t\t\t\tvar face = faces[ i ];\n\n\t\t\t\tvar normal = face.normal;\n\n\t\t\t\tv1.copy( vertices[ face.a ] )\n\t\t\t\t\t.add( vertices[ face.b ] )\n\t\t\t\t\t.add( vertices[ face.c ] )\n\t\t\t\t\t.divideScalar( 3 )\n\t\t\t\t\t.applyMatrix4( matrixWorld );\n\n\t\t\t\tv2.copy( normal ).applyMatrix3( normalMatrix ).normalize().multiplyScalar( this.size ).add( v1 );\n\n\t\t\t\tposition.setXYZ( idx, v1.x, v1.y, v1.z );\n\n\t\t\t\tidx = idx + 1;\n\n\t\t\t\tposition.setXYZ( idx, v2.x, v2.y, v2.z );\n\n\t\t\t\tidx = idx + 1;\n\n\t\t\t}\n\n\t\t\tposition.needsUpdate = true;\n\n\t\t};\n\n\t}() );\n\n\t\u002F**\n\t * @author alteredq \u002F http:\u002F\u002Falteredqualia.com\u002F\n\t * @author mrdoob \u002F http:\u002F\u002Fmrdoob.com\u002F\n\t * @author WestLangley \u002F http:\u002F\u002Fgithub.com\u002FWestLangley\n\t *\u002F\n\n\tfunction DirectionalLightHelper( light, size, color ) {\n\n\t\tObject3D.call( this );\n\n\t\tthis.light = light;\n\t\tthis.light.updateMatrixWorld();\n\n\t\tthis.matrix = light.matrixWorld;\n\t\tthis.matrixAutoUpdate = false;\n\n\t\tthis.color = color;\n\n\t\tif ( size === undefined ) size = 1;\n\n\t\tvar geometry = new BufferGeometry();\n\t\tgeometry.addAttribute( 'position', new Float32BufferAttribute( [\n\t\t\t- size, size, 0,\n\t\t\tsize, size, 0,\n\t\t\tsize, - size, 0,\n\t\t\t- size, - size, 0,\n\t\t\t- size, size, 0\n\t\t], 3 ) );\n\n\t\tvar material = new LineBasicMaterial( { fog: false } );\n\n\t\tthis.lightPlane = new Line( geometry, material );\n\t\tthis.add( this.lightPlane );\n\n\t\tgeometry = new BufferGeometry();\n\t\tgeometry.addAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 0, 1 ], 3 ) );\n\n\t\tthis.targetLine = new Line( geometry, material );\n\t\tthis.add( this.targetLine );\n\n\t\tthis.update();\n\n\t}\n\n\tDirectionalLightHelper.prototype = Object.create( Object3D.prototype );\n\tDirectionalLightHelper.prototype.constructor = DirectionalLightHelper;\n\n\tDirectionalLightHelper.prototype.dispose = function () {\n\n\t\tthis.lightPlane.geometry.dispose();\n\t\tthis.lightPlane.material.dispose();\n\t\tthis.targetLine.geometry.dispose();\n\t\tthis.targetLine.material.dispose();\n\n\t};\n\n\tDirectionalLightHelper.prototype.update = function () {\n\n\t\tvar v1 = new Vector3();\n\t\tvar v2 = new Vector3();\n\t\tvar v3 = new Vector3();\n\n\t\treturn function update() {\n\n\t\t\tv1.setFromMatrixPosition( this.light.matrixWorld );\n\t\t\tv2.setFromMatrixPosition( this.light.target.matrixWorld );\n\t\t\tv3.subVectors( v2, v1 );\n\n\t\t\tthis.lightPlane.lookAt( v2 );\n\n\t\t\tif ( this.color !== undefined ) {\n\n\t\t\t\tthis.lightPlane.material.color.set( this.color );\n\t\t\t\tthis.targetLine.material.color.set( this.color );\n\n\t\t\t} else {\n\n\t\t\t\tthis.lightPlane.material.color.copy( this.light.color );\n\t\t\t\tthis.targetLine.material.color.copy( this.light.color );\n\n\t\t\t}\n\n\t\t\tthis.targetLine.lookAt( v2 );\n\t\t\tthis.targetLine.scale.z = v3.length();\n\n\t\t};\n\n\t}();\n\n\t\u002F**\n\t * @author alteredq \u002F http:\u002F\u002Falteredqualia.com\u002F\n\t * @author Mugen87 \u002F https:\u002F\u002Fgithub.com\u002FMugen87\n\t *\n\t *\t- shows frustum, line of sight and up of the camera\n\t *\t- suitable for fast updates\n\t * \t- based on frustum visualization in lightgl.js shadowmap example\n\t *\t\thttp:\u002F\u002Fevanw.github.com\u002Flightgl.js\u002Ftests\u002Fshadowmap.html\n\t *\u002F\n\n\tfunction CameraHelper( camera ) {\n\n\t\tvar geometry = new BufferGeometry();\n\t\tvar material = new LineBasicMaterial( { color: 0xffffff, vertexColors: FaceColors } );\n\n\t\tvar vertices = [];\n\t\tvar colors = [];\n\n\t\tvar pointMap = {};\n\n\t\t\u002F\u002F colors\n\n\t\tvar colorFrustum = new Color( 0xffaa00 );\n\t\tvar colorCone = new Color( 0xff0000 );\n\t\tvar colorUp = new Color( 0x00aaff );\n\t\tvar colorTarget = new Color( 0xffffff );\n\t\tvar colorCross = new Color( 0x333333 );\n\n\t\t\u002F\u002F near\n\n\t\taddLine( 'n1', 'n2', colorFrustum );\n\t\taddLine( 'n2', 'n4', colorFrustum );\n\t\taddLine( 'n4', 'n3', colorFrustum );\n\t\taddLine( 'n3', 'n1', colorFrustum );\n\n\t\t\u002F\u002F far\n\n\t\taddLine( 'f1', 'f2', colorFrustum );\n\t\taddLine( 'f2', 'f4', colorFrustum );\n\t\taddLine( 'f4', 'f3', colorFrustum );\n\t\taddLine( 'f3', 'f1', colorFrustum );\n\n\t\t\u002F\u002F sides\n\n\t\taddLine( 'n1', 'f1', colorFrustum );\n\t\taddLine( 'n2', 'f2', colorFrustum );\n\t\taddLine( 'n3', 'f3', colorFrustum );\n\t\taddLine( 'n4', 'f4', colorFrustum );\n\n\t\t\u002F\u002F cone\n\n\t\taddLine( 'p', 'n1', colorCone );\n\t\taddLine( 'p', 'n2', colorCone );\n\t\taddLine( 'p', 'n3', colorCone );\n\t\taddLine( 'p', 'n4', colorCone );\n\n\t\t\u002F\u002F up\n\n\t\taddLine( 'u1', 'u2', colorUp );\n\t\taddLine( 'u2', 'u3', colorUp );\n\t\taddLine( 'u3', 'u1', colorUp );\n\n\t\t\u002F\u002F target\n\n\t\taddLine( 'c', 't', colorTarget );\n\t\taddLine( 'p', 'c', colorCross );\n\n\t\t\u002F\u002F cross\n\n\t\taddLine( 'cn1', 'cn2', colorCross );\n\t\taddLine( 'cn3', 'cn4', colorCross );\n\n\t\taddLine( 'cf1', 'cf2', colorCross );\n\t\taddLine( 'cf3', 'cf4', colorCross );\n\n\t\tfunction addLine( a, b, color ) {\n\n\t\t\taddPoint( a, color );\n\t\t\taddPoint( b, color );\n\n\t\t}\n\n\t\tfunction addPoint( id, color ) {\n\n\t\t\tvertices.push( 0, 0, 0 );\n\t\t\tcolors.push( color.r, color.g, color.b );\n\n\t\t\tif ( pointMap[ id ] === undefined ) {\n\n\t\t\t\tpointMap[ id ] = [];\n\n\t\t\t}\n\n\t\t\tpointMap[ id ].push( ( vertices.length \u002F 3 ) - 1 );\n\n\t\t}\n\n\t\tgeometry.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );\n\t\tgeometry.addAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );\n\n\t\tLineSegments.call( this, geometry, material );\n\n\t\tthis.camera = camera;\n\t\tif ( this.camera.updateProjectionMatrix ) this.camera.updateProjectionMatrix();\n\n\t\tthis.matrix = camera.matrixWorld;\n\t\tthis.matrixAutoUpdate = false;\n\n\t\tthis.pointMap = pointMap;\n\n\t\tthis.update();\n\n\t}\n\n\tCameraHelper.prototype = Object.create( LineSegments.prototype );\n\tCameraHelper.prototype.constructor = CameraHelper;\n\n\tCameraHelper.prototype.update = function () {\n\n\t\tvar geometry, pointMap;\n\n\t\tvar vector = new Vector3();\n\t\tvar camera = new Camera();\n\n\t\tfunction setPoint( point, x, y, z ) {\n\n\t\t\tvector.set( x, y, z ).unproject( camera );\n\n\t\t\tvar points = pointMap[ point ];\n\n\t\t\tif ( points !== undefined ) {\n\n\t\t\t\tvar position = geometry.getAttribute( 'position' );\n\n\t\t\t\tfor ( var i = 0, l = points.length; i \u003C l; i ++ ) {\n\n\t\t\t\t\tposition.setXYZ( points[ i ], vector.x, vector.y, vector.z );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\treturn function update() {\n\n\t\t\tgeometry = this.geometry;\n\t\t\tpointMap = this.pointMap;\n\n\t\t\tvar w = 1, h = 1;\n\n\t\t\t\u002F\u002F we need just camera projection matrix\n\t\t\t\u002F\u002F world matrix must be identity\n\n\t\t\tcamera.projectionMatrix.copy( this.camera.projectionMatrix );\n\n\t\t\t\u002F\u002F center \u002F target\n\n\t\t\tsetPoint( 'c', 0, 0, - 1 );\n\t\t\tsetPoint( 't', 0, 0, 1 );\n\n\t\t\t\u002F\u002F near\n\n\t\t\tsetPoint( 'n1', - w, - h, - 1 );\n\t\t\tsetPoint( 'n2', w, - h, - 1 );\n\t\t\tsetPoint( 'n3', - w, h, - 1 );\n\t\t\tsetPoint( 'n4', w, h, - 1 );\n\n\t\t\t\u002F\u002F far\n\n\t\t\tsetPoint( 'f1', - w, - h, 1 );\n\t\t\tsetPoint( 'f2', w, - h, 1 );\n\t\t\tsetPoint( 'f3', - w, h, 1 );\n\t\t\tsetPoint( 'f4', w, h, 1 );\n\n\t\t\t\u002F\u002F up\n\n\t\t\tsetPoint( 'u1', w * 0.7, h * 1.1, - 1 );\n\t\t\tsetPoint( 'u2', - w * 0.7, h * 1.1, - 1 );\n\t\t\tsetPoint( 'u3', 0, h * 2, - 1 );\n\n\t\t\t\u002F\u002F cross\n\n\t\t\tsetPoint( 'cf1', - w, 0, 1 );\n\t\t\tsetPoint( 'cf2', w, 0, 1 );\n\t\t\tsetPoint( 'cf3', 0, - h, 1 );\n\t\t\tsetPoint( 'cf4', 0, h, 1 );\n\n\t\t\tsetPoint( 'cn1', - w, 0, - 1 );\n\t\t\tsetPoint( 'cn2', w, 0, - 1 );\n\t\t\tsetPoint( 'cn3', 0, - h, - 1 );\n\t\t\tsetPoint( 'cn4', 0, h, - 1 );\n\n\t\t\tgeometry.getAttribute( 'position' ).needsUpdate = true;\n\n\t\t};\n\n\t}();\n\n\t\u002F**\n\t * @author mrdoob \u002F http:\u002F\u002Fmrdoob.com\u002F\n\t * @author Mugen87 \u002F http:\u002F\u002Fgithub.com\u002FMugen87\n\t *\u002F\n\n\tfunction BoxHelper( object, color ) {\n\n\t\tthis.object = object;\n\n\t\tif ( color === undefined ) color = 0xffff00;\n\n\t\tvar 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 ] );\n\t\tvar positions = new Float32Array( 8 * 3 );\n\n\t\tvar geometry = new BufferGeometry();\n\t\tgeometry.setIndex( new BufferAttribute( indices, 1 ) );\n\t\tgeometry.addAttribute( 'position', new BufferAttribute( positions, 3 ) );\n\n\t\tLineSegments.call( this, geometry, new LineBasicMaterial( { color: color } ) );\n\n\t\tthis.matrixAutoUpdate = false;\n\n\t\tthis.update();\n\n\t}\n\n\tBoxHelper.prototype = Object.create( LineSegments.prototype );\n\tBoxHelper.prototype.constructor = BoxHelper;\n\n\tBoxHelper.prototype.update = ( function () {\n\n\t\tvar box = new Box3();\n\n\t\treturn function update( object ) {\n\n\t\t\tif ( object !== undefined ) {\n\n\t\t\t\tconsole.warn( 'THREE.BoxHelper: .update() has no longer arguments.' );\n\n\t\t\t}\n\n\t\t\tif ( this.object !== undefined ) {\n\n\t\t\t\tbox.setFromObject( this.object );\n\n\t\t\t}\n\n\t\t\tif ( box.isEmpty() ) return;\n\n\t\t\tvar min = box.min;\n\t\t\tvar max = box.max;\n\n\t\t\t\u002F*\n\t\t\t 5____4\n\t\t\t1\u002F___0\u002F|\n\t\t\t| 6__|_7\n\t\t\t2\u002F___3\u002F\n\n\t\t\t0: max.x, max.y, max.z\n\t\t\t1: min.x, max.y, max.z\n\t\t\t2: min.x, min.y, max.z\n\t\t\t3: max.x, min.y, max.z\n\t\t\t4: max.x, max.y, min.z\n\t\t\t5: min.x, max.y, min.z\n\t\t\t6: min.x, min.y, min.z\n\t\t\t7: max.x, min.y, min.z\n\t\t\t*\u002F\n\n\t\t\tvar position = this.geometry.attributes.position;\n\t\t\tvar array = position.array;\n\n\t\t\tarray[ 0 ] = max.x; array[ 1 ] = max.y; array[ 2 ] = max.z;\n\t\t\tarray[ 3 ] = min.x; array[ 4 ] = max.y; array[ 5 ] = max.z;\n\t\t\tarray[ 6 ] = min.x; array[ 7 ] = min.y; array[ 8 ] = max.z;\n\t\t\tarray[ 9 ] = max.x; array[ 10 ] = min.y; array[ 11 ] = max.z;\n\t\t\tarray[ 12 ] = max.x; array[ 13 ] = max.y; array[ 14 ] = min.z;\n\t\t\tarray[ 15 ] = min.x; array[ 16 ] = max.y; array[ 17 ] = min.z;\n\t\t\tarray[ 18 ] = min.x; array[ 19 ] = min.y; array[ 20 ] = min.z;\n\t\t\tarray[ 21 ] = max.x; array[ 22 ] = min.y; array[ 23 ] = min.z;\n\n\t\t\tposition.needsUpdate = true;\n\n\t\t\tthis.geometry.computeBoundingSphere();\n\n\t\t};\n\n\t} )();\n\n\tBoxHelper.prototype.setFromObject = function ( object ) {\n\n\t\tthis.object = object;\n\t\tthis.update();\n\n\t\treturn this;\n\n\t};\n\n\tBoxHelper.prototype.copy = function ( source ) {\n\n\t\tLineSegments.prototype.copy.call( this, source );\n\n\t\tthis.object = source.object;\n\n\t\treturn this;\n\n\t};\n\n\tBoxHelper.prototype.clone = function () {\n\n\t\treturn new this.constructor().copy( this );\n\n\t};\n\n\t\u002F**\n\t * @author WestLangley \u002F http:\u002F\u002Fgithub.com\u002FWestLangley\n\t *\u002F\n\n\tfunction Box3Helper( box, hex ) {\n\n\t\tthis.type = 'Box3Helper';\n\n\t\tthis.box = box;\n\n\t\tvar color = ( hex !== undefined ) ? hex : 0xffff00;\n\n\t\tvar 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 ] );\n\n\t\tvar 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 ];\n\n\t\tvar geometry = new BufferGeometry();\n\n\t\tgeometry.setIndex( new BufferAttribute( indices, 1 ) );\n\n\t\tgeometry.addAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );\n\n\t\tLineSegments.call( this, geometry, new LineBasicMaterial( { color: color } ) );\n\n\t\tthis.geometry.computeBoundingSphere();\n\n\t}\n\n\tBox3Helper.prototype = Object.create( LineSegments.prototype );\n\tBox3Helper.prototype.constructor = Box3Helper;\n\n\tBox3Helper.prototype.updateMatrixWorld = function ( force ) {\n\n\t\tvar box = this.box;\n\n\t\tif ( box.isEmpty() ) return;\n\n\t\tbox.getCenter( this.position );\n\n\t\tbox.getSize( this.scale );\n\n\t\tthis.scale.multiplyScalar( 0.5 );\n\n\t\tObject3D.prototype.updateMatrixWorld.call( this, force );\n\n\t};\n\n\t\u002F**\n\t * @author WestLangley \u002F http:\u002F\u002Fgithub.com\u002FWestLangley\n\t *\u002F\n\n\tfunction PlaneHelper( plane, size, hex ) {\n\n\t\tthis.type = 'PlaneHelper';\n\n\t\tthis.plane = plane;\n\n\t\tthis.size = ( size === undefined ) ? 1 : size;\n\n\t\tvar color = ( hex !== undefined ) ? hex : 0xffff00;\n\n\t\tvar 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 ];\n\n\t\tvar geometry = new BufferGeometry();\n\t\tgeometry.addAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );\n\t\tgeometry.computeBoundingSphere();\n\n\t\tLine.call( this, geometry, new LineBasicMaterial( { color: color } ) );\n\n\t\t\u002F\u002F\n\n\t\tvar positions2 = [ 1, 1, 1, - 1, 1, 1, - 1, - 1, 1, 1, 1, 1, - 1, - 1, 1, 1, - 1, 1 ];\n\n\t\tvar geometry2 = new BufferGeometry();\n\t\tgeometry2.addAttribute( 'position', new Float32BufferAttribute( positions2, 3 ) );\n\t\tgeometry2.computeBoundingSphere();\n\n\t\tthis.add( new Mesh( geometry2, new MeshBasicMaterial( { color: color, opacity: 0.2, transparent: true, depthWrite: false } ) ) );\n\n\t}\n\n\tPlaneHelper.prototype = Object.create( Line.prototype );\n\tPlaneHelper.prototype.constructor = PlaneHelper;\n\n\tPlaneHelper.prototype.updateMatrixWorld = function ( force ) {\n\n\t\tvar scale = - this.plane.constant;\n\n\t\tif ( Math.abs( scale ) \u003C 1e-8 ) scale = 1e-8; \u002F\u002F sign does not matter\n\n\t\tthis.scale.set( 0.5 * this.size, 0.5 * this.size, scale );\n\n\t\tthis.children[ 0 ].material.side = ( scale \u003C 0 ) ? BackSide : FrontSide; \u002F\u002F renderer flips side when determinant \u003C 0; flipping not wanted here\n\n\t\tthis.lookAt( this.plane.normal );\n\n\t\tObject3D.prototype.updateMatrixWorld.call( this, force );\n\n\t};\n\n\t\u002F**\n\t * @author WestLangley \u002F http:\u002F\u002Fgithub.com\u002FWestLangley\n\t * @author zz85 \u002F http:\u002F\u002Fgithub.com\u002Fzz85\n\t * @author bhouston \u002F http:\u002F\u002Fclara.io\n\t *\n\t * Creates an arrow for visualizing directions\n\t *\n\t * Parameters:\n\t * dir - Vector3\n\t * origin - Vector3\n\t * length - Number\n\t * color - color in hex value\n\t * headLength - Number\n\t * headWidth - Number\n\t *\u002F\n\n\tvar lineGeometry, coneGeometry;\n\n\tfunction ArrowHelper( dir, origin, length, color, headLength, headWidth ) {\n\n\t\t\u002F\u002F dir is assumed to be normalized\n\n\t\tObject3D.call( this );\n\n\t\tif ( dir === undefined ) dir = new Vector3( 0, 0, 1 );\n\t\tif ( origin === undefined ) origin = new Vector3( 0, 0, 0 );\n\t\tif ( length === undefined ) length = 1;\n\t\tif ( color === undefined ) color = 0xffff00;\n\t\tif ( headLength === undefined ) headLength = 0.2 * length;\n\t\tif ( headWidth === undefined ) headWidth = 0.2 * headLength;\n\n\t\tif ( lineGeometry === undefined ) {\n\n\t\t\tlineGeometry = new BufferGeometry();\n\t\t\tlineGeometry.addAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 1, 0 ], 3 ) );\n\n\t\t\tconeGeometry = new CylinderBufferGeometry( 0, 0.5, 1, 5, 1 );\n\t\t\tconeGeometry.translate( 0, - 0.5, 0 );\n\n\t\t}\n\n\t\tthis.position.copy( origin );\n\n\t\tthis.line = new Line( lineGeometry, new LineBasicMaterial( { color: color } ) );\n\t\tthis.line.matrixAutoUpdate = false;\n\t\tthis.add( this.line );\n\n\t\tthis.cone = new Mesh( coneGeometry, new MeshBasicMaterial( { color: color } ) );\n\t\tthis.cone.matrixAutoUpdate = false;\n\t\tthis.add( this.cone );\n\n\t\tthis.setDirection( dir );\n\t\tthis.setLength( length, headLength, headWidth );\n\n\t}\n\n\tArrowHelper.prototype = Object.create( Object3D.prototype );\n\tArrowHelper.prototype.constructor = ArrowHelper;\n\n\tArrowHelper.prototype.setDirection = ( function () {\n\n\t\tvar axis = new Vector3();\n\t\tvar radians;\n\n\t\treturn function setDirection( dir ) {\n\n\t\t\t\u002F\u002F dir is assumed to be normalized\n\n\t\t\tif ( dir.y \u003E 0.99999 ) {\n\n\t\t\t\tthis.quaternion.set( 0, 0, 0, 1 );\n\n\t\t\t} else if ( dir.y \u003C - 0.99999 ) {\n\n\t\t\t\tthis.quaternion.set( 1, 0, 0, 0 );\n\n\t\t\t} else {\n\n\t\t\t\taxis.set( dir.z, 0, - dir.x ).normalize();\n\n\t\t\t\tradians = Math.acos( dir.y );\n\n\t\t\t\tthis.quaternion.setFromAxisAngle( axis, radians );\n\n\t\t\t}\n\n\t\t};\n\n\t}() );\n\n\tArrowHelper.prototype.setLength = function ( length, headLength, headWidth ) {\n\n\t\tif ( headLength === undefined ) headLength = 0.2 * length;\n\t\tif ( headWidth === undefined ) headWidth = 0.2 * headLength;\n\n\t\tthis.line.scale.set( 1, Math.max( 0, length - headLength ), 1 );\n\t\tthis.line.updateMatrix();\n\n\t\tthis.cone.scale.set( headWidth, headLength, headWidth );\n\t\tthis.cone.position.y = length;\n\t\tthis.cone.updateMatrix();\n\n\t};\n\n\tArrowHelper.prototype.setColor = function ( color ) {\n\n\t\tthis.line.material.color.copy( color );\n\t\tthis.cone.material.color.copy( color );\n\n\t};\n\n\tArrowHelper.prototype.copy = function ( source ) {\n\n\t\tObject3D.prototype.copy.call( this, source, false );\n\n\t\tthis.line.copy( source.line );\n\t\tthis.cone.copy( source.cone );\n\n\t\treturn this;\n\n\t};\n\n\tArrowHelper.prototype.clone = function () {\n\n\t\treturn new this.constructor().copy( this );\n\n\t};\n\n\t\u002F**\n\t * @author sroucheray \u002F http:\u002F\u002Fsroucheray.org\u002F\n\t * @author mrdoob \u002F http:\u002F\u002Fmrdoob.com\u002F\n\t *\u002F\n\n\tfunction AxesHelper( size ) {\n\n\t\tsize = size || 1;\n\n\t\tvar vertices = [\n\t\t\t0, 0, 0,\tsize, 0, 0,\n\t\t\t0, 0, 0,\t0, size, 0,\n\t\t\t0, 0, 0,\t0, 0, size\n\t\t];\n\n\t\tvar colors = [\n\t\t\t1, 0, 0,\t1, 0.6, 0,\n\t\t\t0, 1, 0,\t0.6, 1, 0,\n\t\t\t0, 0, 1,\t0, 0.6, 1\n\t\t];\n\n\t\tvar geometry = new BufferGeometry();\n\t\tgeometry.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );\n\t\tgeometry.addAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );\n\n\t\tvar material = new LineBasicMaterial( { vertexColors: VertexColors } );\n\n\t\tLineSegments.call( this, geometry, material );\n\n\t}\n\n\tAxesHelper.prototype = Object.create( LineSegments.prototype );\n\tAxesHelper.prototype.constructor = AxesHelper;\n\n\t\u002F**\n\t * @author mrdoob \u002F http:\u002F\u002Fmrdoob.com\u002F\n\t *\u002F\n\n\tfunction Face4( a, b, c, d, normal, color, materialIndex ) {\n\n\t\tconsole.warn( 'THREE.Face4 has been removed. A THREE.Face3 will be created instead.' );\n\t\treturn new Face3( a, b, c, normal, color, materialIndex );\n\n\t}\n\n\tvar LineStrip = 0;\n\n\tvar LinePieces = 1;\n\n\tfunction MeshFaceMaterial( materials ) {\n\n\t\tconsole.warn( 'THREE.MeshFaceMaterial has been removed. Use an Array instead.' );\n\t\treturn materials;\n\n\t}\n\n\tfunction MultiMaterial( materials ) {\n\n\t\tif ( materials === undefined ) materials = [];\n\n\t\tconsole.warn( 'THREE.MultiMaterial has been removed. Use an Array instead.' );\n\t\tmaterials.isMultiMaterial = true;\n\t\tmaterials.materials = materials;\n\t\tmaterials.clone = function () {\n\n\t\t\treturn materials.slice();\n\n\t\t};\n\t\treturn materials;\n\n\t}\n\n\tfunction PointCloud( geometry, material ) {\n\n\t\tconsole.warn( 'THREE.PointCloud has been renamed to THREE.Points.' );\n\t\treturn new Points( geometry, material );\n\n\t}\n\n\tfunction Particle( material ) {\n\n\t\tconsole.warn( 'THREE.Particle has been renamed to THREE.Sprite.' );\n\t\treturn new Sprite( material );\n\n\t}\n\n\tfunction ParticleSystem( geometry, material ) {\n\n\t\tconsole.warn( 'THREE.ParticleSystem has been renamed to THREE.Points.' );\n\t\treturn new Points( geometry, material );\n\n\t}\n\n\tfunction PointCloudMaterial( parameters ) {\n\n\t\tconsole.warn( 'THREE.PointCloudMaterial has been renamed to THREE.PointsMaterial.' );\n\t\treturn new PointsMaterial( parameters );\n\n\t}\n\n\tfunction ParticleBasicMaterial( parameters ) {\n\n\t\tconsole.warn( 'THREE.ParticleBasicMaterial has been renamed to THREE.PointsMaterial.' );\n\t\treturn new PointsMaterial( parameters );\n\n\t}\n\n\tfunction ParticleSystemMaterial( parameters ) {\n\n\t\tconsole.warn( 'THREE.ParticleSystemMaterial has been renamed to THREE.PointsMaterial.' );\n\t\treturn new PointsMaterial( parameters );\n\n\t}\n\n\tfunction Vertex( x, y, z ) {\n\n\t\tconsole.warn( 'THREE.Vertex has been removed. Use THREE.Vector3 instead.' );\n\t\treturn new Vector3( x, y, z );\n\n\t}\n\n\t\u002F\u002F\n\n\tfunction DynamicBufferAttribute( array, itemSize ) {\n\n\t\tconsole.warn( 'THREE.DynamicBufferAttribute has been removed. Use new THREE.BufferAttribute().setDynamic( true ) instead.' );\n\t\treturn new BufferAttribute( array, itemSize ).setDynamic( true );\n\n\t}\n\n\tfunction Int8Attribute( array, itemSize ) {\n\n\t\tconsole.warn( 'THREE.Int8Attribute has been removed. Use new THREE.Int8BufferAttribute() instead.' );\n\t\treturn new Int8BufferAttribute( array, itemSize );\n\n\t}\n\n\tfunction Uint8Attribute( array, itemSize ) {\n\n\t\tconsole.warn( 'THREE.Uint8Attribute has been removed. Use new THREE.Uint8BufferAttribute() instead.' );\n\t\treturn new Uint8BufferAttribute( array, itemSize );\n\n\t}\n\n\tfunction Uint8ClampedAttribute( array, itemSize ) {\n\n\t\tconsole.warn( 'THREE.Uint8ClampedAttribute has been removed. Use new THREE.Uint8ClampedBufferAttribute() instead.' );\n\t\treturn new Uint8ClampedBufferAttribute( array, itemSize );\n\n\t}\n\n\tfunction Int16Attribute( array, itemSize ) {\n\n\t\tconsole.warn( 'THREE.Int16Attribute has been removed. Use new THREE.Int16BufferAttribute() instead.' );\n\t\treturn new Int16BufferAttribute( array, itemSize );\n\n\t}\n\n\tfunction Uint16Attribute( array, itemSize ) {\n\n\t\tconsole.warn( 'THREE.Uint16Attribute has been removed. Use new THREE.Uint16BufferAttribute() instead.' );\n\t\treturn new Uint16BufferAttribute( array, itemSize );\n\n\t}\n\n\tfunction Int32Attribute( array, itemSize ) {\n\n\t\tconsole.warn( 'THREE.Int32Attribute has been removed. Use new THREE.Int32BufferAttribute() instead.' );\n\t\treturn new Int32BufferAttribute( array, itemSize );\n\n\t}\n\n\tfunction Uint32Attribute( array, itemSize ) {\n\n\t\tconsole.warn( 'THREE.Uint32Attribute has been removed. Use new THREE.Uint32BufferAttribute() instead.' );\n\t\treturn new Uint32BufferAttribute( array, itemSize );\n\n\t}\n\n\tfunction Float32Attribute( array, itemSize ) {\n\n\t\tconsole.warn( 'THREE.Float32Attribute has been removed. Use new THREE.Float32BufferAttribute() instead.' );\n\t\treturn new Float32BufferAttribute( array, itemSize );\n\n\t}\n\n\tfunction Float64Attribute( array, itemSize ) {\n\n\t\tconsole.warn( 'THREE.Float64Attribute has been removed. Use new THREE.Float64BufferAttribute() instead.' );\n\t\treturn new Float64BufferAttribute( array, itemSize );\n\n\t}\n\n\t\u002F\u002F\n\n\tCurve.create = function ( construct, getPoint ) {\n\n\t\tconsole.log( 'THREE.Curve.create() has been deprecated' );\n\n\t\tconstruct.prototype = Object.create( Curve.prototype );\n\t\tconstruct.prototype.constructor = construct;\n\t\tconstruct.prototype.getPoint = getPoint;\n\n\t\treturn construct;\n\n\t};\n\n\t\u002F\u002F\n\n\tObject.assign( CurvePath.prototype, {\n\n\t\tcreatePointsGeometry: function ( divisions ) {\n\n\t\t\tconsole.warn( 'THREE.CurvePath: .createPointsGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.' );\n\n\t\t\t\u002F\u002F generate geometry from path points (for Line or Points objects)\n\n\t\t\tvar pts = this.getPoints( divisions );\n\t\t\treturn this.createGeometry( pts );\n\n\t\t},\n\n\t\tcreateSpacedPointsGeometry: function ( divisions ) {\n\n\t\t\tconsole.warn( 'THREE.CurvePath: .createSpacedPointsGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.' );\n\n\t\t\t\u002F\u002F generate geometry from equidistant sampling along the path\n\n\t\t\tvar pts = this.getSpacedPoints( divisions );\n\t\t\treturn this.createGeometry( pts );\n\n\t\t},\n\n\t\tcreateGeometry: function ( points ) {\n\n\t\t\tconsole.warn( 'THREE.CurvePath: .createGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.' );\n\n\t\t\tvar geometry = new Geometry();\n\n\t\t\tfor ( var i = 0, l = points.length; i \u003C l; i ++ ) {\n\n\t\t\t\tvar point = points[ i ];\n\t\t\t\tgeometry.vertices.push( new Vector3( point.x, point.y, point.z || 0 ) );\n\n\t\t\t}\n\n\t\t\treturn geometry;\n\n\t\t}\n\n\t} );\n\n\t\u002F\u002F\n\n\tObject.assign( Path.prototype, {\n\n\t\tfromPoints: function ( points ) {\n\n\t\t\tconsole.warn( 'THREE.Path: .fromPoints() has been renamed to .setFromPoints().' );\n\t\t\tthis.setFromPoints( points );\n\n\t\t}\n\n\t} );\n\n\t\u002F\u002F\n\n\tfunction ClosedSplineCurve3( points ) {\n\n\t\tconsole.warn( 'THREE.ClosedSplineCurve3 has been deprecated. Use THREE.CatmullRomCurve3 instead.' );\n\n\t\tCatmullRomCurve3.call( this, points );\n\t\tthis.type = 'catmullrom';\n\t\tthis.closed = true;\n\n\t}\n\n\tClosedSplineCurve3.prototype = Object.create( CatmullRomCurve3.prototype );\n\n\t\u002F\u002F\n\n\tfunction SplineCurve3( points ) {\n\n\t\tconsole.warn( 'THREE.SplineCurve3 has been deprecated. Use THREE.CatmullRomCurve3 instead.' );\n\n\t\tCatmullRomCurve3.call( this, points );\n\t\tthis.type = 'catmullrom';\n\n\t}\n\n\tSplineCurve3.prototype = Object.create( CatmullRomCurve3.prototype );\n\n\t\u002F\u002F\n\n\tfunction Spline( points ) {\n\n\t\tconsole.warn( 'THREE.Spline has been removed. Use THREE.CatmullRomCurve3 instead.' );\n\n\t\tCatmullRomCurve3.call( this, points );\n\t\tthis.type = 'catmullrom';\n\n\t}\n\n\tSpline.prototype = Object.create( CatmullRomCurve3.prototype );\n\n\tObject.assign( Spline.prototype, {\n\n\t\tinitFromArray: function ( \u002F* a *\u002F ) {\n\n\t\t\tconsole.error( 'THREE.Spline: .initFromArray() has been removed.' );\n\n\t\t},\n\t\tgetControlPointsArray: function ( \u002F* optionalTarget *\u002F ) {\n\n\t\t\tconsole.error( 'THREE.Spline: .getControlPointsArray() has been removed.' );\n\n\t\t},\n\t\treparametrizeByArcLength: function ( \u002F* samplingCoef *\u002F ) {\n\n\t\t\tconsole.error( 'THREE.Spline: .reparametrizeByArcLength() has been removed.' );\n\n\t\t}\n\n\t} );\n\n\t\u002F\u002F\n\n\tfunction AxisHelper( size ) {\n\n\t\tconsole.warn( 'THREE.AxisHelper has been renamed to THREE.AxesHelper.' );\n\t\treturn new AxesHelper( size );\n\n\t}\n\n\tfunction BoundingBoxHelper( object, color ) {\n\n\t\tconsole.warn( 'THREE.BoundingBoxHelper has been deprecated. Creating a THREE.BoxHelper instead.' );\n\t\treturn new BoxHelper( object, color );\n\n\t}\n\n\tfunction EdgesHelper( object, hex ) {\n\n\t\tconsole.warn( 'THREE.EdgesHelper has been removed. Use THREE.EdgesGeometry instead.' );\n\t\treturn new LineSegments( new EdgesGeometry( object.geometry ), new LineBasicMaterial( { color: hex !== undefined ? hex : 0xffffff } ) );\n\n\t}\n\n\tGridHelper.prototype.setColors = function () {\n\n\t\tconsole.error( 'THREE.GridHelper: setColors() has been deprecated, pass them in the constructor instead.' );\n\n\t};\n\n\tSkeletonHelper.prototype.update = function () {\n\n\t\tconsole.error( 'THREE.SkeletonHelper: update() no longer needs to be called.' );\n\n\t};\n\n\tfunction WireframeHelper( object, hex ) {\n\n\t\tconsole.warn( 'THREE.WireframeHelper has been removed. Use THREE.WireframeGeometry instead.' );\n\t\treturn new LineSegments( new WireframeGeometry( object.geometry ), new LineBasicMaterial( { color: hex !== undefined ? hex : 0xffffff } ) );\n\n\t}\n\n\t\u002F\u002F\n\n\tObject.assign( Loader.prototype, {\n\n\t\textractUrlBase: function ( url ) {\n\n\t\t\tconsole.warn( 'THREE.Loader: .extractUrlBase() has been deprecated. Use THREE.LoaderUtils.extractUrlBase() instead.' );\n\t\t\treturn LoaderUtils.extractUrlBase( url );\n\n\t\t}\n\n\t} );\n\n\tfunction XHRLoader( manager ) {\n\n\t\tconsole.warn( 'THREE.XHRLoader has been renamed to THREE.FileLoader.' );\n\t\treturn new FileLoader( manager );\n\n\t}\n\n\tfunction BinaryTextureLoader( manager ) {\n\n\t\tconsole.warn( 'THREE.BinaryTextureLoader has been renamed to THREE.DataTextureLoader.' );\n\t\treturn new DataTextureLoader( manager );\n\n\t}\n\n\tObject.assign( ObjectLoader.prototype, {\n\n\t\tsetTexturePath: function ( value ) {\n\n\t\t\tconsole.warn( 'THREE.ObjectLoader: .setTexturePath() has been renamed to .setResourcePath().' );\n\t\t\treturn this.setResourcePath( value );\n\n\t\t}\n\n\t} );\n\n\t\u002F\u002F\n\n\tObject.assign( Box2.prototype, {\n\n\t\tcenter: function ( optionalTarget ) {\n\n\t\t\tconsole.warn( 'THREE.Box2: .center() has been renamed to .getCenter().' );\n\t\t\treturn this.getCenter( optionalTarget );\n\n\t\t},\n\t\tempty: function () {\n\n\t\t\tconsole.warn( 'THREE.Box2: .empty() has been renamed to .isEmpty().' );\n\t\t\treturn this.isEmpty();\n\n\t\t},\n\t\tisIntersectionBox: function ( box ) {\n\n\t\t\tconsole.warn( 'THREE.Box2: .isIntersectionBox() has been renamed to .intersectsBox().' );\n\t\t\treturn this.intersectsBox( box );\n\n\t\t},\n\t\tsize: function ( optionalTarget ) {\n\n\t\t\tconsole.warn( 'THREE.Box2: .size() has been renamed to .getSize().' );\n\t\t\treturn this.getSize( optionalTarget );\n\n\t\t}\n\t} );\n\n\tObject.assign( Box3.prototype, {\n\n\t\tcenter: function ( optionalTarget ) {\n\n\t\t\tconsole.warn( 'THREE.Box3: .center() has been renamed to .getCenter().' );\n\t\t\treturn this.getCenter( optionalTarget );\n\n\t\t},\n\t\tempty: function () {\n\n\t\t\tconsole.warn( 'THREE.Box3: .empty() has been renamed to .isEmpty().' );\n\t\t\treturn this.isEmpty();\n\n\t\t},\n\t\tisIntersectionBox: function ( box ) {\n\n\t\t\tconsole.warn( 'THREE.Box3: .isIntersectionBox() has been renamed to .intersectsBox().' );\n\t\t\treturn this.intersectsBox( box );\n\n\t\t},\n\t\tisIntersectionSphere: function ( sphere ) {\n\n\t\t\tconsole.warn( 'THREE.Box3: .isIntersectionSphere() has been renamed to .intersectsSphere().' );\n\t\t\treturn this.intersectsSphere( sphere );\n\n\t\t},\n\t\tsize: function ( optionalTarget ) {\n\n\t\t\tconsole.warn( 'THREE.Box3: .size() has been renamed to .getSize().' );\n\t\t\treturn this.getSize( optionalTarget );\n\n\t\t}\n\t} );\n\n\tLine3.prototype.center = function ( optionalTarget ) {\n\n\t\tconsole.warn( 'THREE.Line3: .center() has been renamed to .getCenter().' );\n\t\treturn this.getCenter( optionalTarget );\n\n\t};\n\n\tObject.assign( _Math, {\n\n\t\trandom16: function () {\n\n\t\t\tconsole.warn( 'THREE.Math: .random16() has been deprecated. Use Math.random() instead.' );\n\t\t\treturn Math.random();\n\n\t\t},\n\n\t\tnearestPowerOfTwo: function ( value ) {\n\n\t\t\tconsole.warn( 'THREE.Math: .nearestPowerOfTwo() has been renamed to .floorPowerOfTwo().' );\n\t\t\treturn _Math.floorPowerOfTwo( value );\n\n\t\t},\n\n\t\tnextPowerOfTwo: function ( value ) {\n\n\t\t\tconsole.warn( 'THREE.Math: .nextPowerOfTwo() has been renamed to .ceilPowerOfTwo().' );\n\t\t\treturn _Math.ceilPowerOfTwo( value );\n\n\t\t}\n\n\t} );\n\n\tObject.assign( Matrix3.prototype, {\n\n\t\tflattenToArrayOffset: function ( array, offset ) {\n\n\t\t\tconsole.warn( \"THREE.Matrix3: .flattenToArrayOffset() has been deprecated. Use .toArray() instead.\" );\n\t\t\treturn this.toArray( array, offset );\n\n\t\t},\n\t\tmultiplyVector3: function ( vector ) {\n\n\t\t\tconsole.warn( 'THREE.Matrix3: .multiplyVector3() has been removed. Use vector.applyMatrix3( matrix ) instead.' );\n\t\t\treturn vector.applyMatrix3( this );\n\n\t\t},\n\t\tmultiplyVector3Array: function ( \u002F* a *\u002F ) {\n\n\t\t\tconsole.error( 'THREE.Matrix3: .multiplyVector3Array() has been removed.' );\n\n\t\t},\n\t\tapplyToBuffer: function ( buffer \u002F*, offset, length *\u002F ) {\n\n\t\t\tconsole.warn( 'THREE.Matrix3: .applyToBuffer() has been removed. Use matrix.applyToBufferAttribute( attribute ) instead.' );\n\t\t\treturn this.applyToBufferAttribute( buffer );\n\n\t\t},\n\t\tapplyToVector3Array: function ( \u002F* array, offset, length *\u002F ) {\n\n\t\t\tconsole.error( 'THREE.Matrix3: .applyToVector3Array() has been removed.' );\n\n\t\t}\n\n\t} );\n\n\tObject.assign( Matrix4.prototype, {\n\n\t\textractPosition: function ( m ) {\n\n\t\t\tconsole.warn( 'THREE.Matrix4: .extractPosition() has been renamed to .copyPosition().' );\n\t\t\treturn this.copyPosition( m );\n\n\t\t},\n\t\tflattenToArrayOffset: function ( array, offset ) {\n\n\t\t\tconsole.warn( \"THREE.Matrix4: .flattenToArrayOffset() has been deprecated. Use .toArray() instead.\" );\n\t\t\treturn this.toArray( array, offset );\n\n\t\t},\n\t\tgetPosition: function () {\n\n\t\t\tvar v1;\n\n\t\t\treturn function getPosition() {\n\n\t\t\t\tif ( v1 === undefined ) v1 = new Vector3();\n\t\t\t\tconsole.warn( 'THREE.Matrix4: .getPosition() has been removed. Use Vector3.setFromMatrixPosition( matrix ) instead.' );\n\t\t\t\treturn v1.setFromMatrixColumn( this, 3 );\n\n\t\t\t};\n\n\t\t}(),\n\t\tsetRotationFromQuaternion: function ( q ) {\n\n\t\t\tconsole.warn( 'THREE.Matrix4: .setRotationFromQuaternion() has been renamed to .makeRotationFromQuaternion().' );\n\t\t\treturn this.makeRotationFromQuaternion( q );\n\n\t\t},\n\t\tmultiplyToArray: function () {\n\n\t\t\tconsole.warn( 'THREE.Matrix4: .multiplyToArray() has been removed.' );\n\n\t\t},\n\t\tmultiplyVector3: function ( vector ) {\n\n\t\t\tconsole.warn( 'THREE.Matrix4: .multiplyVector3() has been removed. Use vector.applyMatrix4( matrix ) instead.' );\n\t\t\treturn vector.applyMatrix4( this );\n\n\t\t},\n\t\tmultiplyVector4: function ( vector ) {\n\n\t\t\tconsole.warn( 'THREE.Matrix4: .multiplyVector4() has been removed. Use vector.applyMatrix4( matrix ) instead.' );\n\t\t\treturn vector.applyMatrix4( this );\n\n\t\t},\n\t\tmultiplyVector3Array: function ( \u002F* a *\u002F ) {\n\n\t\t\tconsole.error( 'THREE.Matrix4: .multiplyVector3Array() has been removed.' );\n\n\t\t},\n\t\trotateAxis: function ( v ) {\n\n\t\t\tconsole.warn( 'THREE.Matrix4: .rotateAxis() has been removed. Use Vector3.transformDirection( matrix ) instead.' );\n\t\t\tv.transformDirection( this );\n\n\t\t},\n\t\tcrossVector: function ( vector ) {\n\n\t\t\tconsole.warn( 'THREE.Matrix4: .crossVector() has been removed. Use vector.applyMatrix4( matrix ) instead.' );\n\t\t\treturn vector.applyMatrix4( this );\n\n\t\t},\n\t\ttranslate: function () {\n\n\t\t\tconsole.error( 'THREE.Matrix4: .translate() has been removed.' );\n\n\t\t},\n\t\trotateX: function () {\n\n\t\t\tconsole.error( 'THREE.Matrix4: .rotateX() has been removed.' );\n\n\t\t},\n\t\trotateY: function () {\n\n\t\t\tconsole.error( 'THREE.Matrix4: .rotateY() has been removed.' );\n\n\t\t},\n\t\trotateZ: function () {\n\n\t\t\tconsole.error( 'THREE.Matrix4: .rotateZ() has been removed.' );\n\n\t\t},\n\t\trotateByAxis: function () {\n\n\t\t\tconsole.error( 'THREE.Matrix4: .rotateByAxis() has been removed.' );\n\n\t\t},\n\t\tapplyToBuffer: function ( buffer \u002F*, offset, length *\u002F ) {\n\n\t\t\tconsole.warn( 'THREE.Matrix4: .applyToBuffer() has been removed. Use matrix.applyToBufferAttribute( attribute ) instead.' );\n\t\t\treturn this.applyToBufferAttribute( buffer );\n\n\t\t},\n\t\tapplyToVector3Array: function ( \u002F* array, offset, length *\u002F ) {\n\n\t\t\tconsole.error( 'THREE.Matrix4: .applyToVector3Array() has been removed.' );\n\n\t\t},\n\t\tmakeFrustum: function ( left, right, bottom, top, near, far ) {\n\n\t\t\tconsole.warn( 'THREE.Matrix4: .makeFrustum() has been removed. Use .makePerspective( left, right, top, bottom, near, far ) instead.' );\n\t\t\treturn this.makePerspective( left, right, top, bottom, near, far );\n\n\t\t}\n\n\t} );\n\n\tPlane.prototype.isIntersectionLine = function ( line ) {\n\n\t\tconsole.warn( 'THREE.Plane: .isIntersectionLine() has been renamed to .intersectsLine().' );\n\t\treturn this.intersectsLine( line );\n\n\t};\n\n\tQuaternion.prototype.multiplyVector3 = function ( vector ) {\n\n\t\tconsole.warn( 'THREE.Quaternion: .multiplyVector3() has been removed. Use is now vector.applyQuaternion( quaternion ) instead.' );\n\t\treturn vector.applyQuaternion( this );\n\n\t};\n\n\tObject.assign( Ray.prototype, {\n\n\t\tisIntersectionBox: function ( box ) {\n\n\t\t\tconsole.warn( 'THREE.Ray: .isIntersectionBox() has been renamed to .intersectsBox().' );\n\t\t\treturn this.intersectsBox( box );\n\n\t\t},\n\t\tisIntersectionPlane: function ( plane ) {\n\n\t\t\tconsole.warn( 'THREE.Ray: .isIntersectionPlane() has been renamed to .intersectsPlane().' );\n\t\t\treturn this.intersectsPlane( plane );\n\n\t\t},\n\t\tisIntersectionSphere: function ( sphere ) {\n\n\t\t\tconsole.warn( 'THREE.Ray: .isIntersectionSphere() has been renamed to .intersectsSphere().' );\n\t\t\treturn this.intersectsSphere( sphere );\n\n\t\t}\n\n\t} );\n\n\tObject.assign( Triangle.prototype, {\n\n\t\tarea: function () {\n\n\t\t\tconsole.warn( 'THREE.Triangle: .area() has been renamed to .getArea().' );\n\t\t\treturn this.getArea();\n\n\t\t},\n\t\tbarycoordFromPoint: function ( point, target ) {\n\n\t\t\tconsole.warn( 'THREE.Triangle: .barycoordFromPoint() has been renamed to .getBarycoord().' );\n\t\t\treturn this.getBarycoord( point, target );\n\n\t\t},\n\t\tmidpoint: function ( target ) {\n\n\t\t\tconsole.warn( 'THREE.Triangle: .midpoint() has been renamed to .getMidpoint().' );\n\t\t\treturn this.getMidpoint( target );\n\n\t\t},\n\t\tnormal: function ( target ) {\n\n\t\t\tconsole.warn( 'THREE.Triangle: .normal() has been renamed to .getNormal().' );\n\t\t\treturn this.getNormal( target );\n\n\t\t},\n\t\tplane: function ( target ) {\n\n\t\t\tconsole.warn( 'THREE.Triangle: .plane() has been renamed to .getPlane().' );\n\t\t\treturn this.getPlane( target );\n\n\t\t}\n\n\t} );\n\n\tObject.assign( Triangle, {\n\n\t\tbarycoordFromPoint: function ( point, a, b, c, target ) {\n\n\t\t\tconsole.warn( 'THREE.Triangle: .barycoordFromPoint() has been renamed to .getBarycoord().' );\n\t\t\treturn Triangle.getBarycoord( point, a, b, c, target );\n\n\t\t},\n\t\tnormal: function ( a, b, c, target ) {\n\n\t\t\tconsole.warn( 'THREE.Triangle: .normal() has been renamed to .getNormal().' );\n\t\t\treturn Triangle.getNormal( a, b, c, target );\n\n\t\t}\n\n\t} );\n\n\tObject.assign( Shape.prototype, {\n\n\t\textractAllPoints: function ( divisions ) {\n\n\t\t\tconsole.warn( 'THREE.Shape: .extractAllPoints() has been removed. Use .extractPoints() instead.' );\n\t\t\treturn this.extractPoints( divisions );\n\n\t\t},\n\t\textrude: function ( options ) {\n\n\t\t\tconsole.warn( 'THREE.Shape: .extrude() has been removed. Use ExtrudeGeometry() instead.' );\n\t\t\treturn new ExtrudeGeometry( this, options );\n\n\t\t},\n\t\tmakeGeometry: function ( options ) {\n\n\t\t\tconsole.warn( 'THREE.Shape: .makeGeometry() has been removed. Use ShapeGeometry() instead.' );\n\t\t\treturn new ShapeGeometry( this, options );\n\n\t\t}\n\n\t} );\n\n\tObject.assign( Vector2.prototype, {\n\n\t\tfromAttribute: function ( attribute, index, offset ) {\n\n\t\t\tconsole.warn( 'THREE.Vector2: .fromAttribute() has been renamed to .fromBufferAttribute().' );\n\t\t\treturn this.fromBufferAttribute( attribute, index, offset );\n\n\t\t},\n\t\tdistanceToManhattan: function ( v ) {\n\n\t\t\tconsole.warn( 'THREE.Vector2: .distanceToManhattan() has been renamed to .manhattanDistanceTo().' );\n\t\t\treturn this.manhattanDistanceTo( v );\n\n\t\t},\n\t\tlengthManhattan: function () {\n\n\t\t\tconsole.warn( 'THREE.Vector2: .lengthManhattan() has been renamed to .manhattanLength().' );\n\t\t\treturn this.manhattanLength();\n\n\t\t}\n\n\t} );\n\n\tObject.assign( Vector3.prototype, {\n\n\t\tsetEulerFromRotationMatrix: function () {\n\n\t\t\tconsole.error( 'THREE.Vector3: .setEulerFromRotationMatrix() has been removed. Use Euler.setFromRotationMatrix() instead.' );\n\n\t\t},\n\t\tsetEulerFromQuaternion: function () {\n\n\t\t\tconsole.error( 'THREE.Vector3: .setEulerFromQuaternion() has been removed. Use Euler.setFromQuaternion() instead.' );\n\n\t\t},\n\t\tgetPositionFromMatrix: function ( m ) {\n\n\t\t\tconsole.warn( 'THREE.Vector3: .getPositionFromMatrix() has been renamed to .setFromMatrixPosition().' );\n\t\t\treturn this.setFromMatrixPosition( m );\n\n\t\t},\n\t\tgetScaleFromMatrix: function ( m ) {\n\n\t\t\tconsole.warn( 'THREE.Vector3: .getScaleFromMatrix() has been renamed to .setFromMatrixScale().' );\n\t\t\treturn this.setFromMatrixScale( m );\n\n\t\t},\n\t\tgetColumnFromMatrix: function ( index, matrix ) {\n\n\t\t\tconsole.warn( 'THREE.Vector3: .getColumnFromMatrix() has been renamed to .setFromMatrixColumn().' );\n\t\t\treturn this.setFromMatrixColumn( matrix, index );\n\n\t\t},\n\t\tapplyProjection: function ( m ) {\n\n\t\t\tconsole.warn( 'THREE.Vector3: .applyProjection() has been removed. Use .applyMatrix4( m ) instead.' );\n\t\t\treturn this.applyMatrix4( m );\n\n\t\t},\n\t\tfromAttribute: function ( attribute, index, offset ) {\n\n\t\t\tconsole.warn( 'THREE.Vector3: .fromAttribute() has been renamed to .fromBufferAttribute().' );\n\t\t\treturn this.fromBufferAttribute( attribute, index, offset );\n\n\t\t},\n\t\tdistanceToManhattan: function ( v ) {\n\n\t\t\tconsole.warn( 'THREE.Vector3: .distanceToManhattan() has been renamed to .manhattanDistanceTo().' );\n\t\t\treturn this.manhattanDistanceTo( v );\n\n\t\t},\n\t\tlengthManhattan: function () {\n\n\t\t\tconsole.warn( 'THREE.Vector3: .lengthManhattan() has been renamed to .manhattanLength().' );\n\t\t\treturn this.manhattanLength();\n\n\t\t}\n\n\t} );\n\n\tObject.assign( Vector4.prototype, {\n\n\t\tfromAttribute: function ( attribute, index, offset ) {\n\n\t\t\tconsole.warn( 'THREE.Vector4: .fromAttribute() has been renamed to .fromBufferAttribute().' );\n\t\t\treturn this.fromBufferAttribute( attribute, index, offset );\n\n\t\t},\n\t\tlengthManhattan: function () {\n\n\t\t\tconsole.warn( 'THREE.Vector4: .lengthManhattan() has been renamed to .manhattanLength().' );\n\t\t\treturn this.manhattanLength();\n\n\t\t}\n\n\t} );\n\n\t\u002F\u002F\n\n\tObject.assign( Geometry.prototype, {\n\n\t\tcomputeTangents: function () {\n\n\t\t\tconsole.error( 'THREE.Geometry: .computeTangents() has been removed.' );\n\n\t\t},\n\t\tcomputeLineDistances: function () {\n\n\t\t\tconsole.error( 'THREE.Geometry: .computeLineDistances() has been removed. Use THREE.Line.computeLineDistances() instead.' );\n\n\t\t}\n\n\t} );\n\n\tObject.assign( Object3D.prototype, {\n\n\t\tgetChildByName: function ( name ) {\n\n\t\t\tconsole.warn( 'THREE.Object3D: .getChildByName() has been renamed to .getObjectByName().' );\n\t\t\treturn this.getObjectByName( name );\n\n\t\t},\n\t\trenderDepth: function () {\n\n\t\t\tconsole.warn( 'THREE.Object3D: .renderDepth has been removed. Use .renderOrder, instead.' );\n\n\t\t},\n\t\ttranslate: function ( distance, axis ) {\n\n\t\t\tconsole.warn( 'THREE.Object3D: .translate() has been removed. Use .translateOnAxis( axis, distance ) instead.' );\n\t\t\treturn this.translateOnAxis( axis, distance );\n\n\t\t},\n\t\tgetWorldRotation: function () {\n\n\t\t\tconsole.error( 'THREE.Object3D: .getWorldRotation() has been removed. Use THREE.Object3D.getWorldQuaternion( target ) instead.' );\n\n\t\t}\n\n\t} );\n\n\tObject.defineProperties( Object3D.prototype, {\n\n\t\teulerOrder: {\n\t\t\tget: function () {\n\n\t\t\t\tconsole.warn( 'THREE.Object3D: .eulerOrder is now .rotation.order.' );\n\t\t\t\treturn this.rotation.order;\n\n\t\t\t},\n\t\t\tset: function ( value ) {\n\n\t\t\t\tconsole.warn( 'THREE.Object3D: .eulerOrder is now .rotation.order.' );\n\t\t\t\tthis.rotation.order = value;\n\n\t\t\t}\n\t\t},\n\t\tuseQuaternion: {\n\t\t\tget: function () {\n\n\t\t\t\tconsole.warn( 'THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.' );\n\n\t\t\t},\n\t\t\tset: function () {\n\n\t\t\t\tconsole.warn( 'THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.' );\n\n\t\t\t}\n\t\t}\n\n\t} );\n\n\tObject.defineProperties( LOD.prototype, {\n\n\t\tobjects: {\n\t\t\tget: function () {\n\n\t\t\t\tconsole.warn( 'THREE.LOD: .objects has been renamed to .levels.' );\n\t\t\t\treturn this.levels;\n\n\t\t\t}\n\t\t}\n\n\t} );\n\n\tObject.defineProperty( Skeleton.prototype, 'useVertexTexture', {\n\n\t\tget: function () {\n\n\t\t\tconsole.warn( 'THREE.Skeleton: useVertexTexture has been removed.' );\n\n\t\t},\n\t\tset: function () {\n\n\t\t\tconsole.warn( 'THREE.Skeleton: useVertexTexture has been removed.' );\n\n\t\t}\n\n\t} );\n\n\tSkinnedMesh.prototype.initBones = function () {\n\n\t\tconsole.error( 'THREE.SkinnedMesh: initBones() has been removed.' );\n\n\t};\n\n\tObject.defineProperty( Curve.prototype, '__arcLengthDivisions', {\n\n\t\tget: function () {\n\n\t\t\tconsole.warn( 'THREE.Curve: .__arcLengthDivisions is now .arcLengthDivisions.' );\n\t\t\treturn this.arcLengthDivisions;\n\n\t\t},\n\t\tset: function ( value ) {\n\n\t\t\tconsole.warn( 'THREE.Curve: .__arcLengthDivisions is now .arcLengthDivisions.' );\n\t\t\tthis.arcLengthDivisions = value;\n\n\t\t}\n\n\t} );\n\n\t\u002F\u002F\n\n\tPerspectiveCamera.prototype.setLens = function ( focalLength, filmGauge ) {\n\n\t\tconsole.warn( \"THREE.PerspectiveCamera.setLens is deprecated. \" +\n\t\t\t\t\"Use .setFocalLength and .filmGauge for a photographic setup.\" );\n\n\t\tif ( filmGauge !== undefined ) this.filmGauge = filmGauge;\n\t\tthis.setFocalLength( focalLength );\n\n\t};\n\n\t\u002F\u002F\n\n\tObject.defineProperties( Light.prototype, {\n\t\tonlyShadow: {\n\t\t\tset: function () {\n\n\t\t\t\tconsole.warn( 'THREE.Light: .onlyShadow has been removed.' );\n\n\t\t\t}\n\t\t},\n\t\tshadowCameraFov: {\n\t\t\tset: function ( value ) {\n\n\t\t\t\tconsole.warn( 'THREE.Light: .shadowCameraFov is now .shadow.camera.fov.' );\n\t\t\t\tthis.shadow.camera.fov = value;\n\n\t\t\t}\n\t\t},\n\t\tshadowCameraLeft: {\n\t\t\tset: function ( value ) {\n\n\t\t\t\tconsole.warn( 'THREE.Light: .shadowCameraLeft is now .shadow.camera.left.' );\n\t\t\t\tthis.shadow.camera.left = value;\n\n\t\t\t}\n\t\t},\n\t\tshadowCameraRight: {\n\t\t\tset: function ( value ) {\n\n\t\t\t\tconsole.warn( 'THREE.Light: .shadowCameraRight is now .shadow.camera.right.' );\n\t\t\t\tthis.shadow.camera.right = value;\n\n\t\t\t}\n\t\t},\n\t\tshadowCameraTop: {\n\t\t\tset: function ( value ) {\n\n\t\t\t\tconsole.warn( 'THREE.Light: .shadowCameraTop is now .shadow.camera.top.' );\n\t\t\t\tthis.shadow.camera.top = value;\n\n\t\t\t}\n\t\t},\n\t\tshadowCameraBottom: {\n\t\t\tset: function ( value ) {\n\n\t\t\t\tconsole.warn( 'THREE.Light: .shadowCameraBottom is now .shadow.camera.bottom.' );\n\t\t\t\tthis.shadow.camera.bottom = value;\n\n\t\t\t}\n\t\t},\n\t\tshadowCameraNear: {\n\t\t\tset: function ( value ) {\n\n\t\t\t\tconsole.warn( 'THREE.Light: .shadowCameraNear is now .shadow.camera.near.' );\n\t\t\t\tthis.shadow.camera.near = value;\n\n\t\t\t}\n\t\t},\n\t\tshadowCameraFar: {\n\t\t\tset: function ( value ) {\n\n\t\t\t\tconsole.warn( 'THREE.Light: .shadowCameraFar is now .shadow.camera.far.' );\n\t\t\t\tthis.shadow.camera.far = value;\n\n\t\t\t}\n\t\t},\n\t\tshadowCameraVisible: {\n\t\t\tset: function () {\n\n\t\t\t\tconsole.warn( 'THREE.Light: .shadowCameraVisible has been removed. Use new THREE.CameraHelper( light.shadow.camera ) instead.' );\n\n\t\t\t}\n\t\t},\n\t\tshadowBias: {\n\t\t\tset: function ( value ) {\n\n\t\t\t\tconsole.warn( 'THREE.Light: .shadowBias is now .shadow.bias.' );\n\t\t\t\tthis.shadow.bias = value;\n\n\t\t\t}\n\t\t},\n\t\tshadowDarkness: {\n\t\t\tset: function () {\n\n\t\t\t\tconsole.warn( 'THREE.Light: .shadowDarkness has been removed.' );\n\n\t\t\t}\n\t\t},\n\t\tshadowMapWidth: {\n\t\t\tset: function ( value ) {\n\n\t\t\t\tconsole.warn( 'THREE.Light: .shadowMapWidth is now .shadow.mapSize.width.' );\n\t\t\t\tthis.shadow.mapSize.width = value;\n\n\t\t\t}\n\t\t},\n\t\tshadowMapHeight: {\n\t\t\tset: function ( value ) {\n\n\t\t\t\tconsole.warn( 'THREE.Light: .shadowMapHeight is now .shadow.mapSize.height.' );\n\t\t\t\tthis.shadow.mapSize.height = value;\n\n\t\t\t}\n\t\t}\n\t} );\n\n\t\u002F\u002F\n\n\tObject.defineProperties( BufferAttribute.prototype, {\n\n\t\tlength: {\n\t\t\tget: function () {\n\n\t\t\t\tconsole.warn( 'THREE.BufferAttribute: .length has been deprecated. Use .count instead.' );\n\t\t\t\treturn this.array.length;\n\n\t\t\t}\n\t\t},\n\t\tcopyIndicesArray: function ( \u002F* indices *\u002F ) {\n\n\t\t\tconsole.error( 'THREE.BufferAttribute: .copyIndicesArray() has been removed.' );\n\n\t\t}\n\n\t} );\n\n\tObject.assign( BufferGeometry.prototype, {\n\n\t\taddIndex: function ( index ) {\n\n\t\t\tconsole.warn( 'THREE.BufferGeometry: .addIndex() has been renamed to .setIndex().' );\n\t\t\tthis.setIndex( index );\n\n\t\t},\n\t\taddDrawCall: function ( start, count, indexOffset ) {\n\n\t\t\tif ( indexOffset !== undefined ) {\n\n\t\t\t\tconsole.warn( 'THREE.BufferGeometry: .addDrawCall() no longer supports indexOffset.' );\n\n\t\t\t}\n\t\t\tconsole.warn( 'THREE.BufferGeometry: .addDrawCall() is now .addGroup().' );\n\t\t\tthis.addGroup( start, count );\n\n\t\t},\n\t\tclearDrawCalls: function () {\n\n\t\t\tconsole.warn( 'THREE.BufferGeometry: .clearDrawCalls() is now .clearGroups().' );\n\t\t\tthis.clearGroups();\n\n\t\t},\n\t\tcomputeTangents: function () {\n\n\t\t\tconsole.warn( 'THREE.BufferGeometry: .computeTangents() has been removed.' );\n\n\t\t},\n\t\tcomputeOffsets: function () {\n\n\t\t\tconsole.warn( 'THREE.BufferGeometry: .computeOffsets() has been removed.' );\n\n\t\t}\n\n\t} );\n\n\tObject.defineProperties( BufferGeometry.prototype, {\n\n\t\tdrawcalls: {\n\t\t\tget: function () {\n\n\t\t\t\tconsole.error( 'THREE.BufferGeometry: .drawcalls has been renamed to .groups.' );\n\t\t\t\treturn this.groups;\n\n\t\t\t}\n\t\t},\n\t\toffsets: {\n\t\t\tget: function () {\n\n\t\t\t\tconsole.warn( 'THREE.BufferGeometry: .offsets has been renamed to .groups.' );\n\t\t\t\treturn this.groups;\n\n\t\t\t}\n\t\t}\n\n\t} );\n\n\t\u002F\u002F\n\n\tObject.assign( ExtrudeBufferGeometry.prototype, {\n\n\t\tgetArrays: function () {\n\n\t\t\tconsole.error( 'THREE.ExtrudeBufferGeometry: .getArrays() has been removed.' );\n\n\t\t},\n\n\t\taddShapeList: function () {\n\n\t\t\tconsole.error( 'THREE.ExtrudeBufferGeometry: .addShapeList() has been removed.' );\n\n\t\t},\n\n\t\taddShape: function () {\n\n\t\t\tconsole.error( 'THREE.ExtrudeBufferGeometry: .addShape() has been removed.' );\n\n\t\t}\n\n\t} );\n\n\t\u002F\u002F\n\n\tObject.defineProperties( Uniform.prototype, {\n\n\t\tdynamic: {\n\t\t\tset: function () {\n\n\t\t\t\tconsole.warn( 'THREE.Uniform: .dynamic has been removed. Use object.onBeforeRender() instead.' );\n\n\t\t\t}\n\t\t},\n\t\tonUpdate: {\n\t\t\tvalue: function () {\n\n\t\t\t\tconsole.warn( 'THREE.Uniform: .onUpdate() has been removed. Use object.onBeforeRender() instead.' );\n\t\t\t\treturn this;\n\n\t\t\t}\n\t\t}\n\n\t} );\n\n\t\u002F\u002F\n\n\tObject.defineProperties( Material.prototype, {\n\n\t\twrapAround: {\n\t\t\tget: function () {\n\n\t\t\t\tconsole.warn( 'THREE.Material: .wrapAround has been removed.' );\n\n\t\t\t},\n\t\t\tset: function () {\n\n\t\t\t\tconsole.warn( 'THREE.Material: .wrapAround has been removed.' );\n\n\t\t\t}\n\t\t},\n\n\t\toverdraw: {\n\t\t\tget: function () {\n\n\t\t\t\tconsole.warn( 'THREE.Material: .overdraw has been removed.' );\n\n\t\t\t},\n\t\t\tset: function () {\n\n\t\t\t\tconsole.warn( 'THREE.Material: .overdraw has been removed.' );\n\n\t\t\t}\n\t\t},\n\n\t\twrapRGB: {\n\t\t\tget: function () {\n\n\t\t\t\tconsole.warn( 'THREE.Material: .wrapRGB has been removed.' );\n\t\t\t\treturn new Color();\n\n\t\t\t}\n\t\t},\n\n\t\tshading: {\n\t\t\tget: function () {\n\n\t\t\t\tconsole.error( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' );\n\n\t\t\t},\n\t\t\tset: function ( value ) {\n\n\t\t\t\tconsole.warn( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' );\n\t\t\t\tthis.flatShading = ( value === FlatShading );\n\n\t\t\t}\n\t\t}\n\n\t} );\n\n\tObject.defineProperties( MeshPhongMaterial.prototype, {\n\n\t\tmetal: {\n\t\t\tget: function () {\n\n\t\t\t\tconsole.warn( 'THREE.MeshPhongMaterial: .metal has been removed. Use THREE.MeshStandardMaterial instead.' );\n\t\t\t\treturn false;\n\n\t\t\t},\n\t\t\tset: function () {\n\n\t\t\t\tconsole.warn( 'THREE.MeshPhongMaterial: .metal has been removed. Use THREE.MeshStandardMaterial instead' );\n\n\t\t\t}\n\t\t}\n\n\t} );\n\n\tObject.defineProperties( ShaderMaterial.prototype, {\n\n\t\tderivatives: {\n\t\t\tget: function () {\n\n\t\t\t\tconsole.warn( 'THREE.ShaderMaterial: .derivatives has been moved to .extensions.derivatives.' );\n\t\t\t\treturn this.extensions.derivatives;\n\n\t\t\t},\n\t\t\tset: function ( value ) {\n\n\t\t\t\tconsole.warn( 'THREE. ShaderMaterial: .derivatives has been moved to .extensions.derivatives.' );\n\t\t\t\tthis.extensions.derivatives = value;\n\n\t\t\t}\n\t\t}\n\n\t} );\n\n\t\u002F\u002F\n\n\tObject.assign( WebGLRenderer.prototype, {\n\n\t\tclearTarget: function ( renderTarget, color, depth, stencil ) {\n\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .clearTarget() has been deprecated. Use .setRenderTarget() and .clear() instead.' );\n\t\t\tthis.setRenderTarget( renderTarget );\n\t\t\tthis.clear( color, depth, stencil );\n\n\t\t},\n\n\t\tanimate: function ( callback ) {\n\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .animate() is now .setAnimationLoop().' );\n\t\t\tthis.setAnimationLoop( callback );\n\n\t\t},\n\n\t\tgetCurrentRenderTarget: function () {\n\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .getCurrentRenderTarget() is now .getRenderTarget().' );\n\t\t\treturn this.getRenderTarget();\n\n\t\t},\n\n\t\tgetMaxAnisotropy: function () {\n\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .getMaxAnisotropy() is now .capabilities.getMaxAnisotropy().' );\n\t\t\treturn this.capabilities.getMaxAnisotropy();\n\n\t\t},\n\n\t\tgetPrecision: function () {\n\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .getPrecision() is now .capabilities.precision.' );\n\t\t\treturn this.capabilities.precision;\n\n\t\t},\n\n\t\tresetGLState: function () {\n\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .resetGLState() is now .state.reset().' );\n\t\t\treturn this.state.reset();\n\n\t\t},\n\n\t\tsupportsFloatTextures: function () {\n\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .supportsFloatTextures() is now .extensions.get( \\'OES_texture_float\\' ).' );\n\t\t\treturn this.extensions.get( 'OES_texture_float' );\n\n\t\t},\n\t\tsupportsHalfFloatTextures: function () {\n\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .supportsHalfFloatTextures() is now .extensions.get( \\'OES_texture_half_float\\' ).' );\n\t\t\treturn this.extensions.get( 'OES_texture_half_float' );\n\n\t\t},\n\t\tsupportsStandardDerivatives: function () {\n\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .supportsStandardDerivatives() is now .extensions.get( \\'OES_standard_derivatives\\' ).' );\n\t\t\treturn this.extensions.get( 'OES_standard_derivatives' );\n\n\t\t},\n\t\tsupportsCompressedTextureS3TC: function () {\n\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .supportsCompressedTextureS3TC() is now .extensions.get( \\'WEBGL_compressed_texture_s3tc\\' ).' );\n\t\t\treturn this.extensions.get( 'WEBGL_compressed_texture_s3tc' );\n\n\t\t},\n\t\tsupportsCompressedTexturePVRTC: function () {\n\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .supportsCompressedTexturePVRTC() is now .extensions.get( \\'WEBGL_compressed_texture_pvrtc\\' ).' );\n\t\t\treturn this.extensions.get( 'WEBGL_compressed_texture_pvrtc' );\n\n\t\t},\n\t\tsupportsBlendMinMax: function () {\n\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .supportsBlendMinMax() is now .extensions.get( \\'EXT_blend_minmax\\' ).' );\n\t\t\treturn this.extensions.get( 'EXT_blend_minmax' );\n\n\t\t},\n\t\tsupportsVertexTextures: function () {\n\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .supportsVertexTextures() is now .capabilities.vertexTextures.' );\n\t\t\treturn this.capabilities.vertexTextures;\n\n\t\t},\n\t\tsupportsInstancedArrays: function () {\n\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .supportsInstancedArrays() is now .extensions.get( \\'ANGLE_instanced_arrays\\' ).' );\n\t\t\treturn this.extensions.get( 'ANGLE_instanced_arrays' );\n\n\t\t},\n\t\tenableScissorTest: function ( boolean ) {\n\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .enableScissorTest() is now .setScissorTest().' );\n\t\t\tthis.setScissorTest( boolean );\n\n\t\t},\n\t\tinitMaterial: function () {\n\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .initMaterial() has been removed.' );\n\n\t\t},\n\t\taddPrePlugin: function () {\n\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .addPrePlugin() has been removed.' );\n\n\t\t},\n\t\taddPostPlugin: function () {\n\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .addPostPlugin() has been removed.' );\n\n\t\t},\n\t\tupdateShadowMap: function () {\n\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .updateShadowMap() has been removed.' );\n\n\t\t},\n\t\tsetFaceCulling: function () {\n\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .setFaceCulling() has been removed.' );\n\n\t\t}\n\n\t} );\n\n\tObject.defineProperties( WebGLRenderer.prototype, {\n\n\t\tshadowMapEnabled: {\n\t\t\tget: function () {\n\n\t\t\t\treturn this.shadowMap.enabled;\n\n\t\t\t},\n\t\t\tset: function ( value ) {\n\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: .shadowMapEnabled is now .shadowMap.enabled.' );\n\t\t\t\tthis.shadowMap.enabled = value;\n\n\t\t\t}\n\t\t},\n\t\tshadowMapType: {\n\t\t\tget: function () {\n\n\t\t\t\treturn this.shadowMap.type;\n\n\t\t\t},\n\t\t\tset: function ( value ) {\n\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: .shadowMapType is now .shadowMap.type.' );\n\t\t\t\tthis.shadowMap.type = value;\n\n\t\t\t}\n\t\t},\n\t\tshadowMapCullFace: {\n\t\t\tget: function () {\n\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: .shadowMapCullFace has been removed. Set Material.shadowSide instead.' );\n\t\t\t\treturn undefined;\n\n\t\t\t},\n\t\t\tset: function ( \u002F* value *\u002F ) {\n\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: .shadowMapCullFace has been removed. Set Material.shadowSide instead.' );\n\n\t\t\t}\n\t\t}\n\t} );\n\n\tObject.defineProperties( WebGLShadowMap.prototype, {\n\n\t\tcullFace: {\n\t\t\tget: function () {\n\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: .shadowMap.cullFace has been removed. Set Material.shadowSide instead.' );\n\t\t\t\treturn undefined;\n\n\t\t\t},\n\t\t\tset: function ( \u002F* cullFace *\u002F ) {\n\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: .shadowMap.cullFace has been removed. Set Material.shadowSide instead.' );\n\n\t\t\t}\n\t\t},\n\t\trenderReverseSided: {\n\t\t\tget: function () {\n\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: .shadowMap.renderReverseSided has been removed. Set Material.shadowSide instead.' );\n\t\t\t\treturn undefined;\n\n\t\t\t},\n\t\t\tset: function () {\n\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: .shadowMap.renderReverseSided has been removed. Set Material.shadowSide instead.' );\n\n\t\t\t}\n\t\t},\n\t\trenderSingleSided: {\n\t\t\tget: function () {\n\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: .shadowMap.renderSingleSided has been removed. Set Material.shadowSide instead.' );\n\t\t\t\treturn undefined;\n\n\t\t\t},\n\t\t\tset: function () {\n\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: .shadowMap.renderSingleSided has been removed. Set Material.shadowSide instead.' );\n\n\t\t\t}\n\t\t}\n\n\t} );\n\n\t\u002F\u002F\n\n\tObject.defineProperties( WebGLRenderTargetCube.prototype, {\n\n\t\tactiveCubeFace: {\n\t\t\tset: function ( \u002F* value *\u002F ) {\n\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTargetCube: .activeCubeFace has been removed. It is now the second parameter of WebGLRenderer.setRenderTarget().' );\n\n\t\t\t}\n\t\t},\n\t\tactiveMipMapLevel: {\n\t\t\tset: function ( \u002F* value *\u002F ) {\n\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTargetCube: .activeMipMapLevel has been removed. It is now the third parameter of WebGLRenderer.setRenderTarget().' );\n\n\t\t\t}\n\t\t}\n\n\t} );\n\n\t\u002F\u002F\n\n\tObject.defineProperties( WebGLRenderTarget.prototype, {\n\n\t\twrapS: {\n\t\t\tget: function () {\n\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .wrapS is now .texture.wrapS.' );\n\t\t\t\treturn this.texture.wrapS;\n\n\t\t\t},\n\t\t\tset: function ( value ) {\n\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .wrapS is now .texture.wrapS.' );\n\t\t\t\tthis.texture.wrapS = value;\n\n\t\t\t}\n\t\t},\n\t\twrapT: {\n\t\t\tget: function () {\n\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .wrapT is now .texture.wrapT.' );\n\t\t\t\treturn this.texture.wrapT;\n\n\t\t\t},\n\t\t\tset: function ( value ) {\n\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .wrapT is now .texture.wrapT.' );\n\t\t\t\tthis.texture.wrapT = value;\n\n\t\t\t}\n\t\t},\n\t\tmagFilter: {\n\t\t\tget: function () {\n\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .magFilter is now .texture.magFilter.' );\n\t\t\t\treturn this.texture.magFilter;\n\n\t\t\t},\n\t\t\tset: function ( value ) {\n\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .magFilter is now .texture.magFilter.' );\n\t\t\t\tthis.texture.magFilter = value;\n\n\t\t\t}\n\t\t},\n\t\tminFilter: {\n\t\t\tget: function () {\n\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .minFilter is now .texture.minFilter.' );\n\t\t\t\treturn this.texture.minFilter;\n\n\t\t\t},\n\t\t\tset: function ( value ) {\n\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .minFilter is now .texture.minFilter.' );\n\t\t\t\tthis.texture.minFilter = value;\n\n\t\t\t}\n\t\t},\n\t\tanisotropy: {\n\t\t\tget: function () {\n\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .anisotropy is now .texture.anisotropy.' );\n\t\t\t\treturn this.texture.anisotropy;\n\n\t\t\t},\n\t\t\tset: function ( value ) {\n\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .anisotropy is now .texture.anisotropy.' );\n\t\t\t\tthis.texture.anisotropy = value;\n\n\t\t\t}\n\t\t},\n\t\toffset: {\n\t\t\tget: function () {\n\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .offset is now .texture.offset.' );\n\t\t\t\treturn this.texture.offset;\n\n\t\t\t},\n\t\t\tset: function ( value ) {\n\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .offset is now .texture.offset.' );\n\t\t\t\tthis.texture.offset = value;\n\n\t\t\t}\n\t\t},\n\t\trepeat: {\n\t\t\tget: function () {\n\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .repeat is now .texture.repeat.' );\n\t\t\t\treturn this.texture.repeat;\n\n\t\t\t},\n\t\t\tset: function ( value ) {\n\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .repeat is now .texture.repeat.' );\n\t\t\t\tthis.texture.repeat = value;\n\n\t\t\t}\n\t\t},\n\t\tformat: {\n\t\t\tget: function () {\n\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .format is now .texture.format.' );\n\t\t\t\treturn this.texture.format;\n\n\t\t\t},\n\t\t\tset: function ( value ) {\n\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .format is now .texture.format.' );\n\t\t\t\tthis.texture.format = value;\n\n\t\t\t}\n\t\t},\n\t\ttype: {\n\t\t\tget: function () {\n\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .type is now .texture.type.' );\n\t\t\t\treturn this.texture.type;\n\n\t\t\t},\n\t\t\tset: function ( value ) {\n\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .type is now .texture.type.' );\n\t\t\t\tthis.texture.type = value;\n\n\t\t\t}\n\t\t},\n\t\tgenerateMipmaps: {\n\t\t\tget: function () {\n\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .generateMipmaps is now .texture.generateMipmaps.' );\n\t\t\t\treturn this.texture.generateMipmaps;\n\n\t\t\t},\n\t\t\tset: function ( value ) {\n\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .generateMipmaps is now .texture.generateMipmaps.' );\n\t\t\t\tthis.texture.generateMipmaps = value;\n\n\t\t\t}\n\t\t}\n\n\t} );\n\n\t\u002F\u002F\n\n\tObject.defineProperties( WebVRManager.prototype, {\n\n\t\tstanding: {\n\t\t\tset: function ( \u002F* value *\u002F ) {\n\n\t\t\t\tconsole.warn( 'THREE.WebVRManager: .standing has been removed.' );\n\n\t\t\t}\n\t\t},\n\t\tuserHeight: {\n\t\t\tset: function ( \u002F* value *\u002F ) {\n\n\t\t\t\tconsole.warn( 'THREE.WebVRManager: .userHeight has been removed.' );\n\n\t\t\t}\n\t\t}\n\n\t} );\n\n\t\u002F\u002F\n\n\tAudio.prototype.load = function ( file ) {\n\n\t\tconsole.warn( 'THREE.Audio: .load has been deprecated. Use THREE.AudioLoader instead.' );\n\t\tvar scope = this;\n\t\tvar audioLoader = new AudioLoader();\n\t\taudioLoader.load( file, function ( buffer ) {\n\n\t\t\tscope.setBuffer( buffer );\n\n\t\t} );\n\t\treturn this;\n\n\t};\n\n\tAudioAnalyser.prototype.getData = function () {\n\n\t\tconsole.warn( 'THREE.AudioAnalyser: .getData() is now .getFrequencyData().' );\n\t\treturn this.getFrequencyData();\n\n\t};\n\n\t\u002F\u002F\n\n\tCubeCamera.prototype.updateCubeMap = function ( renderer, scene ) {\n\n\t\tconsole.warn( 'THREE.CubeCamera: .updateCubeMap() is now .update().' );\n\t\treturn this.update( renderer, scene );\n\n\t};\n\n\t\u002F\u002F\n\n\tvar GeometryUtils = {\n\n\t\tmerge: function ( geometry1, geometry2, materialIndexOffset ) {\n\n\t\t\tconsole.warn( 'THREE.GeometryUtils: .merge() has been moved to Geometry. Use geometry.merge( geometry2, matrix, materialIndexOffset ) instead.' );\n\t\t\tvar matrix;\n\n\t\t\tif ( geometry2.isMesh ) {\n\n\t\t\t\tgeometry2.matrixAutoUpdate && geometry2.updateMatrix();\n\n\t\t\t\tmatrix = geometry2.matrix;\n\t\t\t\tgeometry2 = geometry2.geometry;\n\n\t\t\t}\n\n\t\t\tgeometry1.merge( geometry2, matrix, materialIndexOffset );\n\n\t\t},\n\n\t\tcenter: function ( geometry ) {\n\n\t\t\tconsole.warn( 'THREE.GeometryUtils: .center() has been moved to Geometry. Use geometry.center() instead.' );\n\t\t\treturn geometry.center();\n\n\t\t}\n\n\t};\n\n\tImageUtils.crossOrigin = undefined;\n\n\tImageUtils.loadTexture = function ( url, mapping, onLoad, onError ) {\n\n\t\tconsole.warn( 'THREE.ImageUtils.loadTexture has been deprecated. Use THREE.TextureLoader() instead.' );\n\n\t\tvar loader = new TextureLoader();\n\t\tloader.setCrossOrigin( this.crossOrigin );\n\n\t\tvar texture = loader.load( url, onLoad, undefined, onError );\n\n\t\tif ( mapping ) texture.mapping = mapping;\n\n\t\treturn texture;\n\n\t};\n\n\tImageUtils.loadTextureCube = function ( urls, mapping, onLoad, onError ) {\n\n\t\tconsole.warn( 'THREE.ImageUtils.loadTextureCube has been deprecated. Use THREE.CubeTextureLoader() instead.' );\n\n\t\tvar loader = new CubeTextureLoader();\n\t\tloader.setCrossOrigin( this.crossOrigin );\n\n\t\tvar texture = loader.load( urls, onLoad, undefined, onError );\n\n\t\tif ( mapping ) texture.mapping = mapping;\n\n\t\treturn texture;\n\n\t};\n\n\tImageUtils.loadCompressedTexture = function () {\n\n\t\tconsole.error( 'THREE.ImageUtils.loadCompressedTexture has been removed. Use THREE.DDSLoader instead.' );\n\n\t};\n\n\tImageUtils.loadCompressedTextureCube = function () {\n\n\t\tconsole.error( 'THREE.ImageUtils.loadCompressedTextureCube has been removed. Use THREE.DDSLoader instead.' );\n\n\t};\n\n\t\u002F\u002F\n\n\tfunction Projector() {\n\n\t\tconsole.error( 'THREE.Projector has been moved to \u002Fexamples\u002Fjs\u002Frenderers\u002FProjector.js.' );\n\n\t\tthis.projectVector = function ( vector, camera ) {\n\n\t\t\tconsole.warn( 'THREE.Projector: .projectVector() is now vector.project().' );\n\t\t\tvector.project( camera );\n\n\t\t};\n\n\t\tthis.unprojectVector = function ( vector, camera ) {\n\n\t\t\tconsole.warn( 'THREE.Projector: .unprojectVector() is now vector.unproject().' );\n\t\t\tvector.unproject( camera );\n\n\t\t};\n\n\t\tthis.pickingRay = function () {\n\n\t\t\tconsole.error( 'THREE.Projector: .pickingRay() is now raycaster.setFromCamera().' );\n\n\t\t};\n\n\t}\n\n\t\u002F\u002F\n\n\tfunction CanvasRenderer() {\n\n\t\tconsole.error( 'THREE.CanvasRenderer has been removed' );\n\n\t}\n\n\t\u002F\u002F\n\n\tfunction JSONLoader() {\n\n\t\tconsole.error( 'THREE.JSONLoader has been removed.' );\n\n\t}\n\n\t\u002F\u002F\n\n\tvar SceneUtils = {\n\n\t\tcreateMultiMaterialObject: function ( \u002F* geometry, materials *\u002F ) {\n\n\t\t\tconsole.error( 'THREE.SceneUtils has been moved to \u002Fexamples\u002Fjs\u002Futils\u002FSceneUtils.js' );\n\n\t\t},\n\n\t\tdetach: function ( \u002F* child, parent, scene *\u002F ) {\n\n\t\t\tconsole.error( 'THREE.SceneUtils has been moved to \u002Fexamples\u002Fjs\u002Futils\u002FSceneUtils.js' );\n\n\t\t},\n\n\t\tattach: function ( \u002F* child, scene, parent *\u002F ) {\n\n\t\t\tconsole.error( 'THREE.SceneUtils has been moved to \u002Fexamples\u002Fjs\u002Futils\u002FSceneUtils.js' );\n\n\t\t}\n\n\t};\n\n\t\u002F\u002F\n\n\tfunction LensFlare() {\n\n\t\tconsole.error( 'THREE.LensFlare has been moved to \u002Fexamples\u002Fjs\u002Fobjects\u002FLensflare.js' );\n\n\t}\n\n\texports.WebGLMultisampleRenderTarget = WebGLMultisampleRenderTarget;\n\texports.WebGLRenderTargetCube = WebGLRenderTargetCube;\n\texports.WebGLRenderTarget = WebGLRenderTarget;\n\texports.WebGLRenderer = WebGLRenderer;\n\texports.ShaderLib = ShaderLib;\n\texports.UniformsLib = UniformsLib;\n\texports.UniformsUtils = UniformsUtils;\n\texports.ShaderChunk = ShaderChunk;\n\texports.FogExp2 = FogExp2;\n\texports.Fog = Fog;\n\texports.Scene = Scene;\n\texports.Sprite = Sprite;\n\texports.LOD = LOD;\n\texports.SkinnedMesh = SkinnedMesh;\n\texports.Skeleton = Skeleton;\n\texports.Bone = Bone;\n\texports.Mesh = Mesh;\n\texports.LineSegments = LineSegments;\n\texports.LineLoop = LineLoop;\n\texports.Line = Line;\n\texports.Points = Points;\n\texports.Group = Group;\n\texports.VideoTexture = VideoTexture;\n\texports.DataTexture = DataTexture;\n\texports.DataTexture3D = DataTexture3D;\n\texports.CompressedTexture = CompressedTexture;\n\texports.CubeTexture = CubeTexture;\n\texports.CanvasTexture = CanvasTexture;\n\texports.DepthTexture = DepthTexture;\n\texports.Texture = Texture;\n\texports.AnimationLoader = AnimationLoader;\n\texports.CompressedTextureLoader = CompressedTextureLoader;\n\texports.DataTextureLoader = DataTextureLoader;\n\texports.CubeTextureLoader = CubeTextureLoader;\n\texports.TextureLoader = TextureLoader;\n\texports.ObjectLoader = ObjectLoader;\n\texports.MaterialLoader = MaterialLoader;\n\texports.BufferGeometryLoader = BufferGeometryLoader;\n\texports.DefaultLoadingManager = DefaultLoadingManager;\n\texports.LoadingManager = LoadingManager;\n\texports.ImageLoader = ImageLoader;\n\texports.ImageBitmapLoader = ImageBitmapLoader;\n\texports.FontLoader = FontLoader;\n\texports.FileLoader = FileLoader;\n\texports.Loader = Loader;\n\texports.LoaderUtils = LoaderUtils;\n\texports.Cache = Cache;\n\texports.AudioLoader = AudioLoader;\n\texports.SpotLightShadow = SpotLightShadow;\n\texports.SpotLight = SpotLight;\n\texports.PointLight = PointLight;\n\texports.RectAreaLight = RectAreaLight;\n\texports.HemisphereLight = HemisphereLight;\n\texports.DirectionalLightShadow = DirectionalLightShadow;\n\texports.DirectionalLight = DirectionalLight;\n\texports.AmbientLight = AmbientLight;\n\texports.LightShadow = LightShadow;\n\texports.Light = Light;\n\texports.StereoCamera = StereoCamera;\n\texports.PerspectiveCamera = PerspectiveCamera;\n\texports.OrthographicCamera = OrthographicCamera;\n\texports.CubeCamera = CubeCamera;\n\texports.ArrayCamera = ArrayCamera;\n\texports.Camera = Camera;\n\texports.AudioListener = AudioListener;\n\texports.PositionalAudio = PositionalAudio;\n\texports.AudioContext = AudioContext;\n\texports.AudioAnalyser = AudioAnalyser;\n\texports.Audio = Audio;\n\texports.VectorKeyframeTrack = VectorKeyframeTrack;\n\texports.StringKeyframeTrack = StringKeyframeTrack;\n\texports.QuaternionKeyframeTrack = QuaternionKeyframeTrack;\n\texports.NumberKeyframeTrack = NumberKeyframeTrack;\n\texports.ColorKeyframeTrack = ColorKeyframeTrack;\n\texports.BooleanKeyframeTrack = BooleanKeyframeTrack;\n\texports.PropertyMixer = PropertyMixer;\n\texports.PropertyBinding = PropertyBinding;\n\texports.KeyframeTrack = KeyframeTrack;\n\texports.AnimationUtils = AnimationUtils;\n\texports.AnimationObjectGroup = AnimationObjectGroup;\n\texports.AnimationMixer = AnimationMixer;\n\texports.AnimationClip = AnimationClip;\n\texports.Uniform = Uniform;\n\texports.InstancedBufferGeometry = InstancedBufferGeometry;\n\texports.BufferGeometry = BufferGeometry;\n\texports.Geometry = Geometry;\n\texports.InterleavedBufferAttribute = InterleavedBufferAttribute;\n\texports.InstancedInterleavedBuffer = InstancedInterleavedBuffer;\n\texports.InterleavedBuffer = InterleavedBuffer;\n\texports.InstancedBufferAttribute = InstancedBufferAttribute;\n\texports.Face3 = Face3;\n\texports.Object3D = Object3D;\n\texports.Raycaster = Raycaster;\n\texports.Layers = Layers;\n\texports.EventDispatcher = EventDispatcher;\n\texports.Clock = Clock;\n\texports.QuaternionLinearInterpolant = QuaternionLinearInterpolant;\n\texports.LinearInterpolant = LinearInterpolant;\n\texports.DiscreteInterpolant = DiscreteInterpolant;\n\texports.CubicInterpolant = CubicInterpolant;\n\texports.Interpolant = Interpolant;\n\texports.Triangle = Triangle;\n\texports.Math = _Math;\n\texports.Spherical = Spherical;\n\texports.Cylindrical = Cylindrical;\n\texports.Plane = Plane;\n\texports.Frustum = Frustum;\n\texports.Sphere = Sphere;\n\texports.Ray = Ray;\n\texports.Matrix4 = Matrix4;\n\texports.Matrix3 = Matrix3;\n\texports.Box3 = Box3;\n\texports.Box2 = Box2;\n\texports.Line3 = Line3;\n\texports.Euler = Euler;\n\texports.Vector4 = Vector4;\n\texports.Vector3 = Vector3;\n\texports.Vector2 = Vector2;\n\texports.Quaternion = Quaternion;\n\texports.Color = Color;\n\texports.ImmediateRenderObject = ImmediateRenderObject;\n\texports.VertexNormalsHelper = VertexNormalsHelper;\n\texports.SpotLightHelper = SpotLightHelper;\n\texports.SkeletonHelper = SkeletonHelper;\n\texports.PointLightHelper = PointLightHelper;\n\texports.RectAreaLightHelper = RectAreaLightHelper;\n\texports.HemisphereLightHelper = HemisphereLightHelper;\n\texports.GridHelper = GridHelper;\n\texports.PolarGridHelper = PolarGridHelper;\n\texports.PositionalAudioHelper = PositionalAudioHelper;\n\texports.FaceNormalsHelper = FaceNormalsHelper;\n\texports.DirectionalLightHelper = DirectionalLightHelper;\n\texports.CameraHelper = CameraHelper;\n\texports.BoxHelper = BoxHelper;\n\texports.Box3Helper = Box3Helper;\n\texports.PlaneHelper = PlaneHelper;\n\texports.ArrowHelper = ArrowHelper;\n\texports.AxesHelper = AxesHelper;\n\texports.Shape = Shape;\n\texports.Path = Path;\n\texports.ShapePath = ShapePath;\n\texports.Font = Font;\n\texports.CurvePath = CurvePath;\n\texports.Curve = Curve;\n\texports.ImageUtils = ImageUtils;\n\texports.ShapeUtils = ShapeUtils;\n\texports.WebGLUtils = WebGLUtils;\n\texports.WireframeGeometry = WireframeGeometry;\n\texports.ParametricGeometry = ParametricGeometry;\n\texports.ParametricBufferGeometry = ParametricBufferGeometry;\n\texports.TetrahedronGeometry = TetrahedronGeometry;\n\texports.TetrahedronBufferGeometry = TetrahedronBufferGeometry;\n\texports.OctahedronGeometry = OctahedronGeometry;\n\texports.OctahedronBufferGeometry = OctahedronBufferGeometry;\n\texports.IcosahedronGeometry = IcosahedronGeometry;\n\texports.IcosahedronBufferGeometry = IcosahedronBufferGeometry;\n\texports.DodecahedronGeometry = DodecahedronGeometry;\n\texports.DodecahedronBufferGeometry = DodecahedronBufferGeometry;\n\texports.PolyhedronGeometry = PolyhedronGeometry;\n\texports.PolyhedronBufferGeometry = PolyhedronBufferGeometry;\n\texports.TubeGeometry = TubeGeometry;\n\texports.TubeBufferGeometry = TubeBufferGeometry;\n\texports.TorusKnotGeometry = TorusKnotGeometry;\n\texports.TorusKnotBufferGeometry = TorusKnotBufferGeometry;\n\texports.TorusGeometry = TorusGeometry;\n\texports.TorusBufferGeometry = TorusBufferGeometry;\n\texports.TextGeometry = TextGeometry;\n\texports.TextBufferGeometry = TextBufferGeometry;\n\texports.SphereGeometry = SphereGeometry;\n\texports.SphereBufferGeometry = SphereBufferGeometry;\n\texports.RingGeometry = RingGeometry;\n\texports.RingBufferGeometry = RingBufferGeometry;\n\texports.PlaneGeometry = PlaneGeometry;\n\texports.PlaneBufferGeometry = PlaneBufferGeometry;\n\texports.LatheGeometry = LatheGeometry;\n\texports.LatheBufferGeometry = LatheBufferGeometry;\n\texports.ShapeGeometry = ShapeGeometry;\n\texports.ShapeBufferGeometry = ShapeBufferGeometry;\n\texports.ExtrudeGeometry = ExtrudeGeometry;\n\texports.ExtrudeBufferGeometry = ExtrudeBufferGeometry;\n\texports.EdgesGeometry = EdgesGeometry;\n\texports.ConeGeometry = ConeGeometry;\n\texports.ConeBufferGeometry = ConeBufferGeometry;\n\texports.CylinderGeometry = CylinderGeometry;\n\texports.CylinderBufferGeometry = CylinderBufferGeometry;\n\texports.CircleGeometry = CircleGeometry;\n\texports.CircleBufferGeometry = CircleBufferGeometry;\n\texports.BoxGeometry = BoxGeometry;\n\texports.CubeGeometry = BoxGeometry;\n\texports.BoxBufferGeometry = BoxBufferGeometry;\n\texports.ShadowMaterial = ShadowMaterial;\n\texports.SpriteMaterial = SpriteMaterial;\n\texports.RawShaderMaterial = RawShaderMaterial;\n\texports.ShaderMaterial = ShaderMaterial;\n\texports.PointsMaterial = PointsMaterial;\n\texports.MeshPhysicalMaterial = MeshPhysicalMaterial;\n\texports.MeshStandardMaterial = MeshStandardMaterial;\n\texports.MeshPhongMaterial = MeshPhongMaterial;\n\texports.MeshToonMaterial = MeshToonMaterial;\n\texports.MeshNormalMaterial = MeshNormalMaterial;\n\texports.MeshLambertMaterial = MeshLambertMaterial;\n\texports.MeshDepthMaterial = MeshDepthMaterial;\n\texports.MeshDistanceMaterial = MeshDistanceMaterial;\n\texports.MeshBasicMaterial = MeshBasicMaterial;\n\texports.MeshMatcapMaterial = MeshMatcapMaterial;\n\texports.LineDashedMaterial = LineDashedMaterial;\n\texports.LineBasicMaterial = LineBasicMaterial;\n\texports.Material = Material;\n\texports.Float64BufferAttribute = Float64BufferAttribute;\n\texports.Float32BufferAttribute = Float32BufferAttribute;\n\texports.Uint32BufferAttribute = Uint32BufferAttribute;\n\texports.Int32BufferAttribute = Int32BufferAttribute;\n\texports.Uint16BufferAttribute = Uint16BufferAttribute;\n\texports.Int16BufferAttribute = Int16BufferAttribute;\n\texports.Uint8ClampedBufferAttribute = Uint8ClampedBufferAttribute;\n\texports.Uint8BufferAttribute = Uint8BufferAttribute;\n\texports.Int8BufferAttribute = Int8BufferAttribute;\n\texports.BufferAttribute = BufferAttribute;\n\texports.ArcCurve = ArcCurve;\n\texports.CatmullRomCurve3 = CatmullRomCurve3;\n\texports.CubicBezierCurve = CubicBezierCurve;\n\texports.CubicBezierCurve3 = CubicBezierCurve3;\n\texports.EllipseCurve = EllipseCurve;\n\texports.LineCurve = LineCurve;\n\texports.LineCurve3 = LineCurve3;\n\texports.QuadraticBezierCurve = QuadraticBezierCurve;\n\texports.QuadraticBezierCurve3 = QuadraticBezierCurve3;\n\texports.SplineCurve = SplineCurve;\n\texports.REVISION = REVISION;\n\texports.MOUSE = MOUSE;\n\texports.CullFaceNone = CullFaceNone;\n\texports.CullFaceBack = CullFaceBack;\n\texports.CullFaceFront = CullFaceFront;\n\texports.CullFaceFrontBack = CullFaceFrontBack;\n\texports.FrontFaceDirectionCW = FrontFaceDirectionCW;\n\texports.FrontFaceDirectionCCW = FrontFaceDirectionCCW;\n\texports.BasicShadowMap = BasicShadowMap;\n\texports.PCFShadowMap = PCFShadowMap;\n\texports.PCFSoftShadowMap = PCFSoftShadowMap;\n\texports.FrontSide = FrontSide;\n\texports.BackSide = BackSide;\n\texports.DoubleSide = DoubleSide;\n\texports.FlatShading = FlatShading;\n\texports.SmoothShading = SmoothShading;\n\texports.NoColors = NoColors;\n\texports.FaceColors = FaceColors;\n\texports.VertexColors = VertexColors;\n\texports.NoBlending = NoBlending;\n\texports.NormalBlending = NormalBlending;\n\texports.AdditiveBlending = AdditiveBlending;\n\texports.SubtractiveBlending = SubtractiveBlending;\n\texports.MultiplyBlending = MultiplyBlending;\n\texports.CustomBlending = CustomBlending;\n\texports.AddEquation = AddEquation;\n\texports.SubtractEquation = SubtractEquation;\n\texports.ReverseSubtractEquation = ReverseSubtractEquation;\n\texports.MinEquation = MinEquation;\n\texports.MaxEquation = MaxEquation;\n\texports.ZeroFactor = ZeroFactor;\n\texports.OneFactor = OneFactor;\n\texports.SrcColorFactor = SrcColorFactor;\n\texports.OneMinusSrcColorFactor = OneMinusSrcColorFactor;\n\texports.SrcAlphaFactor = SrcAlphaFactor;\n\texports.OneMinusSrcAlphaFactor = OneMinusSrcAlphaFactor;\n\texports.DstAlphaFactor = DstAlphaFactor;\n\texports.OneMinusDstAlphaFactor = OneMinusDstAlphaFactor;\n\texports.DstColorFactor = DstColorFactor;\n\texports.OneMinusDstColorFactor = OneMinusDstColorFactor;\n\texports.SrcAlphaSaturateFactor = SrcAlphaSaturateFactor;\n\texports.NeverDepth = NeverDepth;\n\texports.AlwaysDepth = AlwaysDepth;\n\texports.LessDepth = LessDepth;\n\texports.LessEqualDepth = LessEqualDepth;\n\texports.EqualDepth = EqualDepth;\n\texports.GreaterEqualDepth = GreaterEqualDepth;\n\texports.GreaterDepth = GreaterDepth;\n\texports.NotEqualDepth = NotEqualDepth;\n\texports.MultiplyOperation = MultiplyOperation;\n\texports.MixOperation = MixOperation;\n\texports.AddOperation = AddOperation;\n\texports.NoToneMapping = NoToneMapping;\n\texports.LinearToneMapping = LinearToneMapping;\n\texports.ReinhardToneMapping = ReinhardToneMapping;\n\texports.Uncharted2ToneMapping = Uncharted2ToneMapping;\n\texports.CineonToneMapping = CineonToneMapping;\n\texports.ACESFilmicToneMapping = ACESFilmicToneMapping;\n\texports.UVMapping = UVMapping;\n\texports.CubeReflectionMapping = CubeReflectionMapping;\n\texports.CubeRefractionMapping = CubeRefractionMapping;\n\texports.EquirectangularReflectionMapping = EquirectangularReflectionMapping;\n\texports.EquirectangularRefractionMapping = EquirectangularRefractionMapping;\n\texports.SphericalReflectionMapping = SphericalReflectionMapping;\n\texports.CubeUVReflectionMapping = CubeUVReflectionMapping;\n\texports.CubeUVRefractionMapping = CubeUVRefractionMapping;\n\texports.RepeatWrapping = RepeatWrapping;\n\texports.ClampToEdgeWrapping = ClampToEdgeWrapping;\n\texports.MirroredRepeatWrapping = MirroredRepeatWrapping;\n\texports.NearestFilter = NearestFilter;\n\texports.NearestMipMapNearestFilter = NearestMipMapNearestFilter;\n\texports.NearestMipMapLinearFilter = NearestMipMapLinearFilter;\n\texports.LinearFilter = LinearFilter;\n\texports.LinearMipMapNearestFilter = LinearMipMapNearestFilter;\n\texports.LinearMipMapLinearFilter = LinearMipMapLinearFilter;\n\texports.UnsignedByteType = UnsignedByteType;\n\texports.ByteType = ByteType;\n\texports.ShortType = ShortType;\n\texports.UnsignedShortType = UnsignedShortType;\n\texports.IntType = IntType;\n\texports.UnsignedIntType = UnsignedIntType;\n\texports.FloatType = FloatType;\n\texports.HalfFloatType = HalfFloatType;\n\texports.UnsignedShort4444Type = UnsignedShort4444Type;\n\texports.UnsignedShort5551Type = UnsignedShort5551Type;\n\texports.UnsignedShort565Type = UnsignedShort565Type;\n\texports.UnsignedInt248Type = UnsignedInt248Type;\n\texports.AlphaFormat = AlphaFormat;\n\texports.RGBFormat = RGBFormat;\n\texports.RGBAFormat = RGBAFormat;\n\texports.LuminanceFormat = LuminanceFormat;\n\texports.LuminanceAlphaFormat = LuminanceAlphaFormat;\n\texports.RGBEFormat = RGBEFormat;\n\texports.DepthFormat = DepthFormat;\n\texports.DepthStencilFormat = DepthStencilFormat;\n\texports.RedFormat = RedFormat;\n\texports.RGB_S3TC_DXT1_Format = RGB_S3TC_DXT1_Format;\n\texports.RGBA_S3TC_DXT1_Format = RGBA_S3TC_DXT1_Format;\n\texports.RGBA_S3TC_DXT3_Format = RGBA_S3TC_DXT3_Format;\n\texports.RGBA_S3TC_DXT5_Format = RGBA_S3TC_DXT5_Format;\n\texports.RGB_PVRTC_4BPPV1_Format = RGB_PVRTC_4BPPV1_Format;\n\texports.RGB_PVRTC_2BPPV1_Format = RGB_PVRTC_2BPPV1_Format;\n\texports.RGBA_PVRTC_4BPPV1_Format = RGBA_PVRTC_4BPPV1_Format;\n\texports.RGBA_PVRTC_2BPPV1_Format = RGBA_PVRTC_2BPPV1_Format;\n\texports.RGB_ETC1_Format = RGB_ETC1_Format;\n\texports.RGBA_ASTC_4x4_Format = RGBA_ASTC_4x4_Format;\n\texports.RGBA_ASTC_5x4_Format = RGBA_ASTC_5x4_Format;\n\texports.RGBA_ASTC_5x5_Format = RGBA_ASTC_5x5_Format;\n\texports.RGBA_ASTC_6x5_Format = RGBA_ASTC_6x5_Format;\n\texports.RGBA_ASTC_6x6_Format = RGBA_ASTC_6x6_Format;\n\texports.RGBA_ASTC_8x5_Format = RGBA_ASTC_8x5_Format;\n\texports.RGBA_ASTC_8x6_Format = RGBA_ASTC_8x6_Format;\n\texports.RGBA_ASTC_8x8_Format = RGBA_ASTC_8x8_Format;\n\texports.RGBA_ASTC_10x5_Format = RGBA_ASTC_10x5_Format;\n\texports.RGBA_ASTC_10x6_Format = RGBA_ASTC_10x6_Format;\n\texports.RGBA_ASTC_10x8_Format = RGBA_ASTC_10x8_Format;\n\texports.RGBA_ASTC_10x10_Format = RGBA_ASTC_10x10_Format;\n\texports.RGBA_ASTC_12x10_Format = RGBA_ASTC_12x10_Format;\n\texports.RGBA_ASTC_12x12_Format = RGBA_ASTC_12x12_Format;\n\texports.LoopOnce = LoopOnce;\n\texports.LoopRepeat = LoopRepeat;\n\texports.LoopPingPong = LoopPingPong;\n\texports.InterpolateDiscrete = InterpolateDiscrete;\n\texports.InterpolateLinear = InterpolateLinear;\n\texports.InterpolateSmooth = InterpolateSmooth;\n\texports.ZeroCurvatureEnding = ZeroCurvatureEnding;\n\texports.ZeroSlopeEnding = ZeroSlopeEnding;\n\texports.WrapAroundEnding = WrapAroundEnding;\n\texports.TrianglesDrawMode = TrianglesDrawMode;\n\texports.TriangleStripDrawMode = TriangleStripDrawMode;\n\texports.TriangleFanDrawMode = TriangleFanDrawMode;\n\texports.LinearEncoding = LinearEncoding;\n\texports.sRGBEncoding = sRGBEncoding;\n\texports.GammaEncoding = GammaEncoding;\n\texports.RGBEEncoding = RGBEEncoding;\n\texports.LogLuvEncoding = LogLuvEncoding;\n\texports.RGBM7Encoding = RGBM7Encoding;\n\texports.RGBM16Encoding = RGBM16Encoding;\n\texports.RGBDEncoding = RGBDEncoding;\n\texports.BasicDepthPacking = BasicDepthPacking;\n\texports.RGBADepthPacking = RGBADepthPacking;\n\texports.TangentSpaceNormalMap = TangentSpaceNormalMap;\n\texports.ObjectSpaceNormalMap = ObjectSpaceNormalMap;\n\texports.Face4 = Face4;\n\texports.LineStrip = LineStrip;\n\texports.LinePieces = LinePieces;\n\texports.MeshFaceMaterial = MeshFaceMaterial;\n\texports.MultiMaterial = MultiMaterial;\n\texports.PointCloud = PointCloud;\n\texports.Particle = Particle;\n\texports.ParticleSystem = ParticleSystem;\n\texports.PointCloudMaterial = PointCloudMaterial;\n\texports.ParticleBasicMaterial = ParticleBasicMaterial;\n\texports.ParticleSystemMaterial = ParticleSystemMaterial;\n\texports.Vertex = Vertex;\n\texports.DynamicBufferAttribute = DynamicBufferAttribute;\n\texports.Int8Attribute = Int8Attribute;\n\texports.Uint8Attribute = Uint8Attribute;\n\texports.Uint8ClampedAttribute = Uint8ClampedAttribute;\n\texports.Int16Attribute = Int16Attribute;\n\texports.Uint16Attribute = Uint16Attribute;\n\texports.Int32Attribute = Int32Attribute;\n\texports.Uint32Attribute = Uint32Attribute;\n\texports.Float32Attribute = Float32Attribute;\n\texports.Float64Attribute = Float64Attribute;\n\texports.ClosedSplineCurve3 = ClosedSplineCurve3;\n\texports.SplineCurve3 = SplineCurve3;\n\texports.Spline = Spline;\n\texports.AxisHelper = AxisHelper;\n\texports.BoundingBoxHelper = BoundingBoxHelper;\n\texports.EdgesHelper = EdgesHelper;\n\texports.WireframeHelper = WireframeHelper;\n\texports.XHRLoader = XHRLoader;\n\texports.BinaryTextureLoader = BinaryTextureLoader;\n\texports.GeometryUtils = GeometryUtils;\n\texports.Projector = Projector;\n\texports.CanvasRenderer = CanvasRenderer;\n\texports.JSONLoader = JSONLoader;\n\texports.SceneUtils = SceneUtils;\n\texports.LensFlare = LensFlare;\n\n\tObject.defineProperty(exports, '__esModule', { value: true });\n\n}));\n","directory_shortid":"BJzTbcoD-P","id":"8c3cd017-0496-4862-8d84-5dbf50733227","inserted_at":"2020-08-05T03:39:49","is_binary":false,"shortid":"H10a-qjw-w","source_id":"3985691b-c62a-4f15-b163-88a57fd46675","title":"three.js","updated_at":"2020-08-05T03:39:49","upload_id":null},{"code":"\u002F**\n * @author Rich Tibbett \u002F https:\u002F\u002Fgithub.com\u002Frichtr\n * @author mrdoob \u002F http:\u002F\u002Fmrdoob.com\u002F\n * @author Tony Parisi \u002F http:\u002F\u002Fwww.tonyparisi.com\u002F\n * @author Takahiro \u002F https:\u002F\u002Fgithub.com\u002Ftakahirox\n * @author Don McCurdy \u002F https:\u002F\u002Fwww.donmccurdy.com\n *\u002F\n\nTHREE.GLTFLoader = ( function () {\n\n\tfunction GLTFLoader( manager ) {\n\n\t\tthis.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;\n\t\tthis.dracoLoader = null;\n\n\t}\n\n\tGLTFLoader.prototype = {\n\n\t\tconstructor: GLTFLoader,\n\n\t\tcrossOrigin: 'anonymous',\n\n\t\tload: function ( url, onLoad, onProgress, onError ) {\n\n\t\t\tvar scope = this;\n\n\t\t\tvar resourcePath;\n\n\t\t\tif ( this.resourcePath !== undefined ) {\n\n\t\t\t\tresourcePath = this.resourcePath;\n\n\t\t\t} else if ( this.path !== undefined ) {\n\n\t\t\t\tresourcePath = this.path;\n\n\t\t\t} else {\n\n\t\t\t\tresourcePath = THREE.LoaderUtils.extractUrlBase( url );\n\n\t\t\t}\n\n\t\t\t\u002F\u002F Tells the LoadingManager to track an extra item, which resolves after\n\t\t\t\u002F\u002F the model is fully loaded. This means the count of items loaded will\n\t\t\t\u002F\u002F be incorrect, but ensures manager.onLoad() does not fire early.\n\t\t\tscope.manager.itemStart( url );\n\n\t\t\tvar _onError = function ( e ) {\n\n\t\t\t\tif ( onError ) {\n\n\t\t\t\t\tonError( e );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tconsole.error( e );\n\n\t\t\t\t}\n\n\t\t\t\tscope.manager.itemError( url );\n\t\t\t\tscope.manager.itemEnd( url );\n\n\t\t\t};\n\n\t\t\tvar loader = new THREE.FileLoader( scope.manager );\n\n\t\t\tloader.setPath( this.path );\n\t\t\tloader.setResponseType( 'arraybuffer' );\n\n\t\t\tloader.load( url, function ( data ) {\n\n\t\t\t\ttry {\n\n\t\t\t\t\tscope.parse( data, resourcePath, function ( gltf ) {\n\n\t\t\t\t\t\tonLoad( gltf );\n\n\t\t\t\t\t\tscope.manager.itemEnd( url );\n\n\t\t\t\t\t}, _onError );\n\n\t\t\t\t} catch ( e ) {\n\n\t\t\t\t\t_onError( e );\n\n\t\t\t\t}\n\n\t\t\t}, onProgress, _onError );\n\n\t\t},\n\n\t\tsetCrossOrigin: function ( value ) {\n\n\t\t\tthis.crossOrigin = value;\n\t\t\treturn this;\n\n\t\t},\n\n\t\tsetPath: function ( value ) {\n\n\t\t\tthis.path = value;\n\t\t\treturn this;\n\n\t\t},\n\n\t\tsetResourcePath: function ( value ) {\n\n\t\t\tthis.resourcePath = value;\n\t\t\treturn this;\n\n\t\t},\n\n\t\tsetDRACOLoader: function ( dracoLoader ) {\n\n\t\t\tthis.dracoLoader = dracoLoader;\n\t\t\treturn this;\n\n\t\t},\n\n\t\tparse: function ( data, path, onLoad, onError ) {\n\n\t\t\tvar content;\n\t\t\tvar extensions = {};\n\n\t\t\tif ( typeof data === 'string' ) {\n\n\t\t\t\tcontent = data;\n\n\t\t\t} else {\n\n\t\t\t\tvar magic = THREE.LoaderUtils.decodeText( new Uint8Array( data, 0, 4 ) );\n\n\t\t\t\tif ( magic === BINARY_EXTENSION_HEADER_MAGIC ) {\n\n\t\t\t\t\ttry {\n\n\t\t\t\t\t\textensions[ EXTENSIONS.KHR_BINARY_GLTF ] = new GLTFBinaryExtension( data );\n\n\t\t\t\t\t} catch ( error ) {\n\n\t\t\t\t\t\tif ( onError ) onError( error );\n\t\t\t\t\t\treturn;\n\n\t\t\t\t\t}\n\n\t\t\t\t\tcontent = extensions[ EXTENSIONS.KHR_BINARY_GLTF ].content;\n\n\t\t\t\t} else {\n\n\t\t\t\t\tcontent = THREE.LoaderUtils.decodeText( new Uint8Array( data ) );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tvar json = JSON.parse( content );\n\n\t\t\tif ( json.asset === undefined || json.asset.version[ 0 ] \u003C 2 ) {\n\n\t\t\t\tif ( onError ) onError( new Error( 'THREE.GLTFLoader: Unsupported asset. glTF versions \u003E=2.0 are supported. Use LegacyGLTFLoader instead.' ) );\n\t\t\t\treturn;\n\n\t\t\t}\n\n\t\t\tif ( json.extensionsUsed ) {\n\n\t\t\t\tfor ( var i = 0; i \u003C json.extensionsUsed.length; ++ i ) {\n\n\t\t\t\t\tvar extensionName = json.extensionsUsed[ i ];\n\t\t\t\t\tvar extensionsRequired = json.extensionsRequired || [];\n\n\t\t\t\t\tswitch ( extensionName ) {\n\n\t\t\t\t\t\tcase EXTENSIONS.KHR_LIGHTS_PUNCTUAL:\n\t\t\t\t\t\t\textensions[ extensionName ] = new GLTFLightsExtension( json );\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase EXTENSIONS.KHR_MATERIALS_UNLIT:\n\t\t\t\t\t\t\textensions[ extensionName ] = new GLTFMaterialsUnlitExtension( json );\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS:\n\t\t\t\t\t\t\textensions[ extensionName ] = new GLTFMaterialsPbrSpecularGlossinessExtension( json );\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase EXTENSIONS.KHR_DRACO_MESH_COMPRESSION:\n\t\t\t\t\t\t\textensions[ extensionName ] = new GLTFDracoMeshCompressionExtension( json, this.dracoLoader );\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase EXTENSIONS.MSFT_TEXTURE_DDS:\n\t\t\t\t\t\t\textensions[ EXTENSIONS.MSFT_TEXTURE_DDS ] = new GLTFTextureDDSExtension();\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase EXTENSIONS.KHR_TEXTURE_TRANSFORM:\n\t\t\t\t\t\t\textensions[ EXTENSIONS.KHR_TEXTURE_TRANSFORM ] = new GLTFTextureTransformExtension( json );\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tdefault:\n\n\t\t\t\t\t\t\tif ( extensionsRequired.indexOf( extensionName ) \u003E= 0 ) {\n\n\t\t\t\t\t\t\t\tconsole.warn( 'THREE.GLTFLoader: Unknown extension \"' + extensionName + '\".' );\n\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tvar parser = new GLTFParser( json, extensions, {\n\n\t\t\t\tpath: path || this.resourcePath || '',\n\t\t\t\tcrossOrigin: this.crossOrigin,\n\t\t\t\tmanager: this.manager\n\n\t\t\t} );\n\n\t\t\tparser.parse( function ( scene, scenes, cameras, animations, json ) {\n\n\t\t\t\tvar glTF = {\n\t\t\t\t\tscene: scene,\n\t\t\t\t\tscenes: scenes,\n\t\t\t\t\tcameras: cameras,\n\t\t\t\t\tanimations: animations,\n\t\t\t\t\tasset: json.asset,\n\t\t\t\t\tparser: parser,\n\t\t\t\t\tuserData: {}\n\t\t\t\t};\n\n\t\t\t\taddUnknownExtensionsToUserData( extensions, glTF, json );\n\n\t\t\t\tonLoad( glTF );\n\n\t\t\t}, onError );\n\n\t\t}\n\n\t};\n\n\t\u002F* GLTFREGISTRY *\u002F\n\n\tfunction GLTFRegistry() {\n\n\t\tvar objects = {};\n\n\t\treturn\t{\n\n\t\t\tget: function ( key ) {\n\n\t\t\t\treturn objects[ key ];\n\n\t\t\t},\n\n\t\t\tadd: function ( key, object ) {\n\n\t\t\t\tobjects[ key ] = object;\n\n\t\t\t},\n\n\t\t\tremove: function ( key ) {\n\n\t\t\t\tdelete objects[ key ];\n\n\t\t\t},\n\n\t\t\tremoveAll: function () {\n\n\t\t\t\tobjects = {};\n\n\t\t\t}\n\n\t\t};\n\n\t}\n\n\t\u002F*********************************\u002F\n\t\u002F********** EXTENSIONS ***********\u002F\n\t\u002F*********************************\u002F\n\n\tvar EXTENSIONS = {\n\t\tKHR_BINARY_GLTF: 'KHR_binary_glTF',\n\t\tKHR_DRACO_MESH_COMPRESSION: 'KHR_draco_mesh_compression',\n\t\tKHR_LIGHTS_PUNCTUAL: 'KHR_lights_punctual',\n\t\tKHR_MATERIALS_PBR_SPECULAR_GLOSSINESS: 'KHR_materials_pbrSpecularGlossiness',\n\t\tKHR_MATERIALS_UNLIT: 'KHR_materials_unlit',\n\t\tKHR_TEXTURE_TRANSFORM: 'KHR_texture_transform',\n\t\tMSFT_TEXTURE_DDS: 'MSFT_texture_dds'\n\t};\n\n\t\u002F**\n\t * DDS Texture Extension\n\t *\n\t * Specification:\n\t * https:\u002F\u002Fgithub.com\u002FKhronosGroup\u002FglTF\u002Ftree\u002Fmaster\u002Fextensions\u002F2.0\u002FVendor\u002FMSFT_texture_dds\n\t *\n\t *\u002F\n\tfunction GLTFTextureDDSExtension() {\n\n\t\tif ( ! THREE.DDSLoader ) {\n\n\t\t\tthrow new Error( 'THREE.GLTFLoader: Attempting to load .dds texture without importing THREE.DDSLoader' );\n\n\t\t}\n\n\t\tthis.name = EXTENSIONS.MSFT_TEXTURE_DDS;\n\t\tthis.ddsLoader = new THREE.DDSLoader();\n\n\t}\n\n\t\u002F**\n\t * Lights Extension\n\t *\n\t * Specification: PENDING\n\t *\u002F\n\tfunction GLTFLightsExtension( json ) {\n\n\t\tthis.name = EXTENSIONS.KHR_LIGHTS_PUNCTUAL;\n\n\t\tvar extension = ( json.extensions && json.extensions[ EXTENSIONS.KHR_LIGHTS_PUNCTUAL ] ) || {};\n\t\tthis.lightDefs = extension.lights || [];\n\n\t}\n\n\tGLTFLightsExtension.prototype.loadLight = function ( lightIndex ) {\n\n\t\tvar lightDef = this.lightDefs[ lightIndex ];\n\t\tvar lightNode;\n\n\t\tvar color = new THREE.Color( 0xffffff );\n\t\tif ( lightDef.color !== undefined ) color.fromArray( lightDef.color );\n\n\t\tvar range = lightDef.range !== undefined ? lightDef.range : 0;\n\n\t\tswitch ( lightDef.type ) {\n\n\t\t\tcase 'directional':\n\t\t\t\tlightNode = new THREE.DirectionalLight( color );\n\t\t\t\tlightNode.target.position.set( 0, 0, - 1 );\n\t\t\t\tlightNode.add( lightNode.target );\n\t\t\t\tbreak;\n\n\t\t\tcase 'point':\n\t\t\t\tlightNode = new THREE.PointLight( color );\n\t\t\t\tlightNode.distance = range;\n\t\t\t\tbreak;\n\n\t\t\tcase 'spot':\n\t\t\t\tlightNode = new THREE.SpotLight( color );\n\t\t\t\tlightNode.distance = range;\n\t\t\t\t\u002F\u002F Handle spotlight properties.\n\t\t\t\tlightDef.spot = lightDef.spot || {};\n\t\t\t\tlightDef.spot.innerConeAngle = lightDef.spot.innerConeAngle !== undefined ? lightDef.spot.innerConeAngle : 0;\n\t\t\t\tlightDef.spot.outerConeAngle = lightDef.spot.outerConeAngle !== undefined ? lightDef.spot.outerConeAngle : Math.PI \u002F 4.0;\n\t\t\t\tlightNode.angle = lightDef.spot.outerConeAngle;\n\t\t\t\tlightNode.penumbra = 1.0 - lightDef.spot.innerConeAngle \u002F lightDef.spot.outerConeAngle;\n\t\t\t\tlightNode.target.position.set( 0, 0, - 1 );\n\t\t\t\tlightNode.add( lightNode.target );\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tthrow new Error( 'THREE.GLTFLoader: Unexpected light type, \"' + lightDef.type + '\".' );\n\n\t\t}\n\n\t\t\u002F\u002F Some lights (e.g. spot) default to a position other than the origin. Reset the position\n\t\t\u002F\u002F here, because node-level parsing will only override position if explicitly specified.\n\t\tlightNode.position.set( 0, 0, 0 );\n\n\t\tlightNode.decay = 2;\n\n\t\tif ( lightDef.intensity !== undefined ) lightNode.intensity = lightDef.intensity;\n\n\t\tlightNode.name = lightDef.name || ( 'light_' + lightIndex );\n\n\t\treturn Promise.resolve( lightNode );\n\n\t};\n\n\t\u002F**\n\t * Unlit Materials Extension (pending)\n\t *\n\t * PR: https:\u002F\u002Fgithub.com\u002FKhronosGroup\u002FglTF\u002Fpull\u002F1163\n\t *\u002F\n\tfunction GLTFMaterialsUnlitExtension( json ) {\n\n\t\tthis.name = EXTENSIONS.KHR_MATERIALS_UNLIT;\n\n\t}\n\n\tGLTFMaterialsUnlitExtension.prototype.getMaterialType = function ( material ) {\n\n\t\treturn THREE.MeshBasicMaterial;\n\n\t};\n\n\tGLTFMaterialsUnlitExtension.prototype.extendParams = function ( materialParams, material, parser ) {\n\n\t\tvar pending = [];\n\n\t\tmaterialParams.color = new THREE.Color( 1.0, 1.0, 1.0 );\n\t\tmaterialParams.opacity = 1.0;\n\n\t\tvar metallicRoughness = material.pbrMetallicRoughness;\n\n\t\tif ( metallicRoughness ) {\n\n\t\t\tif ( Array.isArray( metallicRoughness.baseColorFactor ) ) {\n\n\t\t\t\tvar array = metallicRoughness.baseColorFactor;\n\n\t\t\t\tmaterialParams.color.fromArray( array );\n\t\t\t\tmaterialParams.opacity = array[ 3 ];\n\n\t\t\t}\n\n\t\t\tif ( metallicRoughness.baseColorTexture !== undefined ) {\n\n\t\t\t\tpending.push( parser.assignTexture( materialParams, 'map', metallicRoughness.baseColorTexture ) );\n\n\t\t\t}\n\n\t\t}\n\n\t\treturn Promise.all( pending );\n\n\t};\n\n\t\u002F* BINARY EXTENSION *\u002F\n\n\tvar BINARY_EXTENSION_BUFFER_NAME = 'binary_glTF';\n\tvar BINARY_EXTENSION_HEADER_MAGIC = 'glTF';\n\tvar BINARY_EXTENSION_HEADER_LENGTH = 12;\n\tvar BINARY_EXTENSION_CHUNK_TYPES = { JSON: 0x4E4F534A, BIN: 0x004E4942 };\n\n\tfunction GLTFBinaryExtension( data ) {\n\n\t\tthis.name = EXTENSIONS.KHR_BINARY_GLTF;\n\t\tthis.content = null;\n\t\tthis.body = null;\n\n\t\tvar headerView = new DataView( data, 0, BINARY_EXTENSION_HEADER_LENGTH );\n\n\t\tthis.header = {\n\t\t\tmagic: THREE.LoaderUtils.decodeText( new Uint8Array( data.slice( 0, 4 ) ) ),\n\t\t\tversion: headerView.getUint32( 4, true ),\n\t\t\tlength: headerView.getUint32( 8, true )\n\t\t};\n\n\t\tif ( this.header.magic !== BINARY_EXTENSION_HEADER_MAGIC ) {\n\n\t\t\tthrow new Error( 'THREE.GLTFLoader: Unsupported glTF-Binary header.' );\n\n\t\t} else if ( this.header.version \u003C 2.0 ) {\n\n\t\t\tthrow new Error( 'THREE.GLTFLoader: Legacy binary file detected. Use LegacyGLTFLoader instead.' );\n\n\t\t}\n\n\t\tvar chunkView = new DataView( data, BINARY_EXTENSION_HEADER_LENGTH );\n\t\tvar chunkIndex = 0;\n\n\t\twhile ( chunkIndex \u003C chunkView.byteLength ) {\n\n\t\t\tvar chunkLength = chunkView.getUint32( chunkIndex, true );\n\t\t\tchunkIndex += 4;\n\n\t\t\tvar chunkType = chunkView.getUint32( chunkIndex, true );\n\t\t\tchunkIndex += 4;\n\n\t\t\tif ( chunkType === BINARY_EXTENSION_CHUNK_TYPES.JSON ) {\n\n\t\t\t\tvar contentArray = new Uint8Array( data, BINARY_EXTENSION_HEADER_LENGTH + chunkIndex, chunkLength );\n\t\t\t\tthis.content = THREE.LoaderUtils.decodeText( contentArray );\n\n\t\t\t} else if ( chunkType === BINARY_EXTENSION_CHUNK_TYPES.BIN ) {\n\n\t\t\t\tvar byteOffset = BINARY_EXTENSION_HEADER_LENGTH + chunkIndex;\n\t\t\t\tthis.body = data.slice( byteOffset, byteOffset + chunkLength );\n\n\t\t\t}\n\n\t\t\t\u002F\u002F Clients must ignore chunks with unknown types.\n\n\t\t\tchunkIndex += chunkLength;\n\n\t\t}\n\n\t\tif ( this.content === null ) {\n\n\t\t\tthrow new Error( 'THREE.GLTFLoader: JSON content not found.' );\n\n\t\t}\n\n\t}\n\n\t\u002F**\n\t * DRACO Mesh Compression Extension\n\t *\n\t * Specification: https:\u002F\u002Fgithub.com\u002FKhronosGroup\u002FglTF\u002Fpull\u002F874\n\t *\u002F\n\tfunction GLTFDracoMeshCompressionExtension( json, dracoLoader ) {\n\n\t\tif ( ! dracoLoader ) {\n\n\t\t\tthrow new Error( 'THREE.GLTFLoader: No DRACOLoader instance provided.' );\n\n\t\t}\n\n\t\tthis.name = EXTENSIONS.KHR_DRACO_MESH_COMPRESSION;\n\t\tthis.json = json;\n\t\tthis.dracoLoader = dracoLoader;\n\t\tTHREE.DRACOLoader.getDecoderModule();\n\n\t}\n\n\tGLTFDracoMeshCompressionExtension.prototype.decodePrimitive = function ( primitive, parser ) {\n\n\t\tvar json = this.json;\n\t\tvar dracoLoader = this.dracoLoader;\n\t\tvar bufferViewIndex = primitive.extensions[ this.name ].bufferView;\n\t\tvar gltfAttributeMap = primitive.extensions[ this.name ].attributes;\n\t\tvar threeAttributeMap = {};\n\t\tvar attributeNormalizedMap = {};\n\t\tvar attributeTypeMap = {};\n\n\t\tfor ( var attributeName in gltfAttributeMap ) {\n\n\t\t\tif ( ! ( attributeName in ATTRIBUTES ) ) continue;\n\n\t\t\tthreeAttributeMap[ ATTRIBUTES[ attributeName ] ] = gltfAttributeMap[ attributeName ];\n\n\t\t}\n\n\t\tfor ( attributeName in primitive.attributes ) {\n\n\t\t\tif ( ATTRIBUTES[ attributeName ] !== undefined && gltfAttributeMap[ attributeName ] !== undefined ) {\n\n\t\t\t\tvar accessorDef = json.accessors[ primitive.attributes[ attributeName ] ];\n\t\t\t\tvar componentType = WEBGL_COMPONENT_TYPES[ accessorDef.componentType ];\n\n\t\t\t\tattributeTypeMap[ ATTRIBUTES[ attributeName ] ] = componentType;\n\t\t\t\tattributeNormalizedMap[ ATTRIBUTES[ attributeName ] ] = accessorDef.normalized === true;\n\n\t\t\t}\n\n\t\t}\n\n\t\treturn parser.getDependency( 'bufferView', bufferViewIndex ).then( function ( bufferView ) {\n\n\t\t\treturn new Promise( function ( resolve ) {\n\n\t\t\t\tdracoLoader.decodeDracoFile( bufferView, function ( geometry ) {\n\n\t\t\t\t\tfor ( var attributeName in geometry.attributes ) {\n\n\t\t\t\t\t\tvar attribute = geometry.attributes[ attributeName ];\n\t\t\t\t\t\tvar normalized = attributeNormalizedMap[ attributeName ];\n\n\t\t\t\t\t\tif ( normalized !== undefined ) attribute.normalized = normalized;\n\n\t\t\t\t\t}\n\n\t\t\t\t\tresolve( geometry );\n\n\t\t\t\t}, threeAttributeMap, attributeTypeMap );\n\n\t\t\t} );\n\n\t\t} );\n\n\t};\n\n\t\u002F**\n\t * Texture Transform Extension\n\t *\n\t * Specification:\n\t *\u002F\n\tfunction GLTFTextureTransformExtension( json ) {\n\n\t\tthis.name = EXTENSIONS.KHR_TEXTURE_TRANSFORM;\n\n\t}\n\n\tGLTFTextureTransformExtension.prototype.extendTexture = function ( texture, transform ) {\n\n\t\ttexture = texture.clone();\n\n\t\tif ( transform.offset !== undefined ) {\n\n\t\t\ttexture.offset.fromArray( transform.offset );\n\n\t\t}\n\n\t\tif ( transform.rotation !== undefined ) {\n\n\t\t\ttexture.rotation = transform.rotation;\n\n\t\t}\n\n\t\tif ( transform.scale !== undefined ) {\n\n\t\t\ttexture.repeat.fromArray( transform.scale );\n\n\t\t}\n\n\t\tif ( transform.texCoord !== undefined ) {\n\n\t\t\tconsole.warn( 'THREE.GLTFLoader: Custom UV sets in \"' + this.name + '\" extension not yet supported.' );\n\n\t\t}\n\n\t\ttexture.needsUpdate = true;\n\n\t\treturn texture;\n\n\t};\n\n\t\u002F**\n\t * Specular-Glossiness Extension\n\t *\n\t * Specification: https:\u002F\u002Fgithub.com\u002FKhronosGroup\u002FglTF\u002Ftree\u002Fmaster\u002Fextensions\u002F2.0\u002FKhronos\u002FKHR_materials_pbrSpecularGlossiness\n\t *\u002F\n\tfunction GLTFMaterialsPbrSpecularGlossinessExtension() {\n\n\t\treturn {\n\n\t\t\tname: EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS,\n\n\t\t\tspecularGlossinessParams: [\n\t\t\t\t'color',\n\t\t\t\t'map',\n\t\t\t\t'lightMap',\n\t\t\t\t'lightMapIntensity',\n\t\t\t\t'aoMap',\n\t\t\t\t'aoMapIntensity',\n\t\t\t\t'emissive',\n\t\t\t\t'emissiveIntensity',\n\t\t\t\t'emissiveMap',\n\t\t\t\t'bumpMap',\n\t\t\t\t'bumpScale',\n\t\t\t\t'normalMap',\n\t\t\t\t'displacementMap',\n\t\t\t\t'displacementScale',\n\t\t\t\t'displacementBias',\n\t\t\t\t'specularMap',\n\t\t\t\t'specular',\n\t\t\t\t'glossinessMap',\n\t\t\t\t'glossiness',\n\t\t\t\t'alphaMap',\n\t\t\t\t'envMap',\n\t\t\t\t'envMapIntensity',\n\t\t\t\t'refractionRatio',\n\t\t\t],\n\n\t\t\tgetMaterialType: function () {\n\n\t\t\t\treturn THREE.ShaderMaterial;\n\n\t\t\t},\n\n\t\t\textendParams: function ( params, material, parser ) {\n\n\t\t\t\tvar pbrSpecularGlossiness = material.extensions[ this.name ];\n\n\t\t\t\tvar shader = THREE.ShaderLib[ 'standard' ];\n\n\t\t\t\tvar uniforms = THREE.UniformsUtils.clone( shader.uniforms );\n\n\t\t\t\tvar specularMapParsFragmentChunk = [\n\t\t\t\t\t'#ifdef USE_SPECULARMAP',\n\t\t\t\t\t'\tuniform sampler2D specularMap;',\n\t\t\t\t\t'#endif'\n\t\t\t\t].join( '\\n' );\n\n\t\t\t\tvar glossinessMapParsFragmentChunk = [\n\t\t\t\t\t'#ifdef USE_GLOSSINESSMAP',\n\t\t\t\t\t'\tuniform sampler2D glossinessMap;',\n\t\t\t\t\t'#endif'\n\t\t\t\t].join( '\\n' );\n\n\t\t\t\tvar specularMapFragmentChunk = [\n\t\t\t\t\t'vec3 specularFactor = specular;',\n\t\t\t\t\t'#ifdef USE_SPECULARMAP',\n\t\t\t\t\t'\tvec4 texelSpecular = texture2D( specularMap, vUv );',\n\t\t\t\t\t'\ttexelSpecular = sRGBToLinear( texelSpecular );',\n\t\t\t\t\t'\t\u002F\u002F reads channel RGB, compatible with a glTF Specular-Glossiness (RGBA) texture',\n\t\t\t\t\t'\tspecularFactor *= texelSpecular.rgb;',\n\t\t\t\t\t'#endif'\n\t\t\t\t].join( '\\n' );\n\n\t\t\t\tvar glossinessMapFragmentChunk = [\n\t\t\t\t\t'float glossinessFactor = glossiness;',\n\t\t\t\t\t'#ifdef USE_GLOSSINESSMAP',\n\t\t\t\t\t'\tvec4 texelGlossiness = texture2D( glossinessMap, vUv );',\n\t\t\t\t\t'\t\u002F\u002F reads channel A, compatible with a glTF Specular-Glossiness (RGBA) texture',\n\t\t\t\t\t'\tglossinessFactor *= texelGlossiness.a;',\n\t\t\t\t\t'#endif'\n\t\t\t\t].join( '\\n' );\n\n\t\t\t\tvar lightPhysicalFragmentChunk = [\n\t\t\t\t\t'PhysicalMaterial material;',\n\t\t\t\t\t'material.diffuseColor = diffuseColor.rgb;',\n\t\t\t\t\t'material.specularRoughness = clamp( 1.0 - glossinessFactor, 0.04, 1.0 );',\n\t\t\t\t\t'material.specularColor = specularFactor.rgb;',\n\t\t\t\t].join( '\\n' );\n\n\t\t\t\tvar fragmentShader = shader.fragmentShader\n\t\t\t\t\t.replace( 'uniform float roughness;', 'uniform vec3 specular;' )\n\t\t\t\t\t.replace( 'uniform float metalness;', 'uniform float glossiness;' )\n\t\t\t\t\t.replace( '#include \u003Croughnessmap_pars_fragment\u003E', specularMapParsFragmentChunk )\n\t\t\t\t\t.replace( '#include \u003Cmetalnessmap_pars_fragment\u003E', glossinessMapParsFragmentChunk )\n\t\t\t\t\t.replace( '#include \u003Croughnessmap_fragment\u003E', specularMapFragmentChunk )\n\t\t\t\t\t.replace( '#include \u003Cmetalnessmap_fragment\u003E', glossinessMapFragmentChunk )\n\t\t\t\t\t.replace( '#include \u003Clights_physical_fragment\u003E', lightPhysicalFragmentChunk );\n\n\t\t\t\tdelete uniforms.roughness;\n\t\t\t\tdelete uniforms.metalness;\n\t\t\t\tdelete uniforms.roughnessMap;\n\t\t\t\tdelete uniforms.metalnessMap;\n\n\t\t\t\tuniforms.specular = { value: new THREE.Color().setHex( 0x111111 ) };\n\t\t\t\tuniforms.glossiness = { value: 0.5 };\n\t\t\t\tuniforms.specularMap = { value: null };\n\t\t\t\tuniforms.glossinessMap = { value: null };\n\n\t\t\t\tparams.vertexShader = shader.vertexShader;\n\t\t\t\tparams.fragmentShader = fragmentShader;\n\t\t\t\tparams.uniforms = uniforms;\n\t\t\t\tparams.defines = { 'STANDARD': '' };\n\n\t\t\t\tparams.color = new THREE.Color( 1.0, 1.0, 1.0 );\n\t\t\t\tparams.opacity = 1.0;\n\n\t\t\t\tvar pending = [];\n\n\t\t\t\tif ( Array.isArray( pbrSpecularGlossiness.diffuseFactor ) ) {\n\n\t\t\t\t\tvar array = pbrSpecularGlossiness.diffuseFactor;\n\n\t\t\t\t\tparams.color.fromArray( array );\n\t\t\t\t\tparams.opacity = array[ 3 ];\n\n\t\t\t\t}\n\n\t\t\t\tif ( pbrSpecularGlossiness.diffuseTexture !== undefined ) {\n\n\t\t\t\t\tpending.push( parser.assignTexture( params, 'map', pbrSpecularGlossiness.diffuseTexture ) );\n\n\t\t\t\t}\n\n\t\t\t\tparams.emissive = new THREE.Color( 0.0, 0.0, 0.0 );\n\t\t\t\tparams.glossiness = pbrSpecularGlossiness.glossinessFactor !== undefined ? pbrSpecularGlossiness.glossinessFactor : 1.0;\n\t\t\t\tparams.specular = new THREE.Color( 1.0, 1.0, 1.0 );\n\n\t\t\t\tif ( Array.isArray( pbrSpecularGlossiness.specularFactor ) ) {\n\n\t\t\t\t\tparams.specular.fromArray( pbrSpecularGlossiness.specularFactor );\n\n\t\t\t\t}\n\n\t\t\t\tif ( pbrSpecularGlossiness.specularGlossinessTexture !== undefined ) {\n\n\t\t\t\t\tvar specGlossMapDef = pbrSpecularGlossiness.specularGlossinessTexture;\n\t\t\t\t\tpending.push( parser.assignTexture( params, 'glossinessMap', specGlossMapDef ) );\n\t\t\t\t\tpending.push( parser.assignTexture( params, 'specularMap', specGlossMapDef ) );\n\n\t\t\t\t}\n\n\t\t\t\treturn Promise.all( pending );\n\n\t\t\t},\n\n\t\t\tcreateMaterial: function ( params ) {\n\n\t\t\t\t\u002F\u002F setup material properties based on MeshStandardMaterial for Specular-Glossiness\n\n\t\t\t\tvar material = new THREE.ShaderMaterial( {\n\t\t\t\t\tdefines: params.defines,\n\t\t\t\t\tvertexShader: params.vertexShader,\n\t\t\t\t\tfragmentShader: params.fragmentShader,\n\t\t\t\t\tuniforms: params.uniforms,\n\t\t\t\t\tfog: true,\n\t\t\t\t\tlights: true,\n\t\t\t\t\topacity: params.opacity,\n\t\t\t\t\ttransparent: params.transparent\n\t\t\t\t} );\n\n\t\t\t\tmaterial.isGLTFSpecularGlossinessMaterial = true;\n\n\t\t\t\tmaterial.color = params.color;\n\n\t\t\t\tmaterial.map = params.map === undefined ? null : params.map;\n\n\t\t\t\tmaterial.lightMap = null;\n\t\t\t\tmaterial.lightMapIntensity = 1.0;\n\n\t\t\t\tmaterial.aoMap = params.aoMap === undefined ? null : params.aoMap;\n\t\t\t\tmaterial.aoMapIntensity = 1.0;\n\n\t\t\t\tmaterial.emissive = params.emissive;\n\t\t\t\tmaterial.emissiveIntensity = 1.0;\n\t\t\t\tmaterial.emissiveMap = params.emissiveMap === undefined ? null : params.emissiveMap;\n\n\t\t\t\tmaterial.bumpMap = params.bumpMap === undefined ? null : params.bumpMap;\n\t\t\t\tmaterial.bumpScale = 1;\n\n\t\t\t\tmaterial.normalMap = params.normalMap === undefined ? null : params.normalMap;\n\t\t\t\tif ( params.normalScale ) material.normalScale = params.normalScale;\n\n\t\t\t\tmaterial.displacementMap = null;\n\t\t\t\tmaterial.displacementScale = 1;\n\t\t\t\tmaterial.displacementBias = 0;\n\n\t\t\t\tmaterial.specularMap = params.specularMap === undefined ? null : params.specularMap;\n\t\t\t\tmaterial.specular = params.specular;\n\n\t\t\t\tmaterial.glossinessMap = params.glossinessMap === undefined ? null : params.glossinessMap;\n\t\t\t\tmaterial.glossiness = params.glossiness;\n\n\t\t\t\tmaterial.alphaMap = null;\n\n\t\t\t\tmaterial.envMap = params.envMap === undefined ? null : params.envMap;\n\t\t\t\tmaterial.envMapIntensity = 1.0;\n\n\t\t\t\tmaterial.refractionRatio = 0.98;\n\n\t\t\t\tmaterial.extensions.derivatives = true;\n\n\t\t\t\treturn material;\n\n\t\t\t},\n\n\t\t\t\u002F**\n\t\t\t * Clones a GLTFSpecularGlossinessMaterial instance. The ShaderMaterial.copy() method can\n\t\t\t * copy only properties it knows about or inherits, and misses many properties that would\n\t\t\t * normally be defined by MeshStandardMaterial.\n\t\t\t *\n\t\t\t * This method allows GLTFSpecularGlossinessMaterials to be cloned in the process of\n\t\t\t * loading a glTF model, but cloning later (e.g. by the user) would require these changes\n\t\t\t * AND also updating `.onBeforeRender` on the parent mesh.\n\t\t\t *\n\t\t\t * @param {THREE.ShaderMaterial} source\n\t\t\t * @return {THREE.ShaderMaterial}\n\t\t\t *\u002F\n\t\t\tcloneMaterial: function ( source ) {\n\n\t\t\t\tvar target = source.clone();\n\n\t\t\t\ttarget.isGLTFSpecularGlossinessMaterial = true;\n\n\t\t\t\tvar params = this.specularGlossinessParams;\n\n\t\t\t\tfor ( var i = 0, il = params.length; i \u003C il; i ++ ) {\n\n\t\t\t\t\ttarget[ params[ i ] ] = source[ params[ i ] ];\n\n\t\t\t\t}\n\n\t\t\t\treturn target;\n\n\t\t\t},\n\n\t\t\t\u002F\u002F Here's based on refreshUniformsCommon() and refreshUniformsStandard() in WebGLRenderer.\n\t\t\trefreshUniforms: function ( renderer, scene, camera, geometry, material, group ) {\n\n\t\t\t\tif ( material.isGLTFSpecularGlossinessMaterial !== true ) {\n\n\t\t\t\t\treturn;\n\n\t\t\t\t}\n\n\t\t\t\tvar uniforms = material.uniforms;\n\t\t\t\tvar defines = material.defines;\n\n\t\t\t\tuniforms.opacity.value = material.opacity;\n\n\t\t\t\tuniforms.diffuse.value.copy( material.color );\n\t\t\t\tuniforms.emissive.value.copy( material.emissive ).multiplyScalar( material.emissiveIntensity );\n\n\t\t\t\tuniforms.map.value = material.map;\n\t\t\t\tuniforms.specularMap.value = material.specularMap;\n\t\t\t\tuniforms.alphaMap.value = material.alphaMap;\n\n\t\t\t\tuniforms.lightMap.value = material.lightMap;\n\t\t\t\tuniforms.lightMapIntensity.value = material.lightMapIntensity;\n\n\t\t\t\tuniforms.aoMap.value = material.aoMap;\n\t\t\t\tuniforms.aoMapIntensity.value = material.aoMapIntensity;\n\n\t\t\t\t\u002F\u002F uv repeat and offset setting priorities\n\t\t\t\t\u002F\u002F 1. color map\n\t\t\t\t\u002F\u002F 2. specular map\n\t\t\t\t\u002F\u002F 3. normal map\n\t\t\t\t\u002F\u002F 4. bump map\n\t\t\t\t\u002F\u002F 5. alpha map\n\t\t\t\t\u002F\u002F 6. emissive map\n\n\t\t\t\tvar uvScaleMap;\n\n\t\t\t\tif ( material.map ) {\n\n\t\t\t\t\tuvScaleMap = material.map;\n\n\t\t\t\t} else if ( material.specularMap ) {\n\n\t\t\t\t\tuvScaleMap = material.specularMap;\n\n\t\t\t\t} else if ( material.displacementMap ) {\n\n\t\t\t\t\tuvScaleMap = material.displacementMap;\n\n\t\t\t\t} else if ( material.normalMap ) {\n\n\t\t\t\t\tuvScaleMap = material.normalMap;\n\n\t\t\t\t} else if ( material.bumpMap ) {\n\n\t\t\t\t\tuvScaleMap = material.bumpMap;\n\n\t\t\t\t} else if ( material.glossinessMap ) {\n\n\t\t\t\t\tuvScaleMap = material.glossinessMap;\n\n\t\t\t\t} else if ( material.alphaMap ) {\n\n\t\t\t\t\tuvScaleMap = material.alphaMap;\n\n\t\t\t\t} else if ( material.emissiveMap ) {\n\n\t\t\t\t\tuvScaleMap = material.emissiveMap;\n\n\t\t\t\t}\n\n\t\t\t\tif ( uvScaleMap !== undefined ) {\n\n\t\t\t\t\t\u002F\u002F backwards compatibility\n\t\t\t\t\tif ( uvScaleMap.isWebGLRenderTarget ) {\n\n\t\t\t\t\t\tuvScaleMap = uvScaleMap.texture;\n\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( uvScaleMap.matrixAutoUpdate === true ) {\n\n\t\t\t\t\t\tuvScaleMap.updateMatrix();\n\n\t\t\t\t\t}\n\n\t\t\t\t\tuniforms.uvTransform.value.copy( uvScaleMap.matrix );\n\n\t\t\t\t}\n\n\t\t\t\tif ( material.envMap ) {\n\n\t\t\t\t\tuniforms.envMap.value = material.envMap;\n\t\t\t\t\tuniforms.envMapIntensity.value = material.envMapIntensity;\n\n\t\t\t\t\t\u002F\u002F don't flip CubeTexture envMaps, flip everything else:\n\t\t\t\t\t\u002F\u002F WebGLRenderTargetCube will be flipped for backwards compatibility\n\t\t\t\t\t\u002F\u002F WebGLRenderTargetCube.texture will be flipped because it's a Texture and NOT a CubeTexture\n\t\t\t\t\t\u002F\u002F this check must be handled differently, or removed entirely, if WebGLRenderTargetCube uses a CubeTexture in the future\n\t\t\t\t\tuniforms.flipEnvMap.value = material.envMap.isCubeTexture ? - 1 : 1;\n\n\t\t\t\t\tuniforms.reflectivity.value = material.reflectivity;\n\t\t\t\t\tuniforms.refractionRatio.value = material.refractionRatio;\n\n\t\t\t\t\tuniforms.maxMipLevel.value = renderer.properties.get( material.envMap ).__maxMipLevel;\n\n\t\t\t\t}\n\n\t\t\t\tuniforms.specular.value.copy( material.specular );\n\t\t\t\tuniforms.glossiness.value = material.glossiness;\n\n\t\t\t\tuniforms.glossinessMap.value = material.glossinessMap;\n\n\t\t\t\tuniforms.emissiveMap.value = material.emissiveMap;\n\t\t\t\tuniforms.bumpMap.value = material.bumpMap;\n\t\t\t\tuniforms.normalMap.value = material.normalMap;\n\n\t\t\t\tuniforms.displacementMap.value = material.displacementMap;\n\t\t\t\tuniforms.displacementScale.value = material.displacementScale;\n\t\t\t\tuniforms.displacementBias.value = material.displacementBias;\n\n\t\t\t\tif ( uniforms.glossinessMap.value !== null && defines.USE_GLOSSINESSMAP === undefined ) {\n\n\t\t\t\t\tdefines.USE_GLOSSINESSMAP = '';\n\t\t\t\t\t\u002F\u002F set USE_ROUGHNESSMAP to enable vUv\n\t\t\t\t\tdefines.USE_ROUGHNESSMAP = '';\n\n\t\t\t\t}\n\n\t\t\t\tif ( uniforms.glossinessMap.value === null && defines.USE_GLOSSINESSMAP !== undefined ) {\n\n\t\t\t\t\tdelete defines.USE_GLOSSINESSMAP;\n\t\t\t\t\tdelete defines.USE_ROUGHNESSMAP;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t};\n\n\t}\n\n\t\u002F*********************************\u002F\n\t\u002F********** INTERPOLATION ********\u002F\n\t\u002F*********************************\u002F\n\n\t\u002F\u002F Spline Interpolation\n\t\u002F\u002F Specification: https:\u002F\u002Fgithub.com\u002FKhronosGroup\u002FglTF\u002Fblob\u002Fmaster\u002Fspecification\u002F2.0\u002FREADME.md#appendix-c-spline-interpolation\n\tfunction GLTFCubicSplineInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {\n\n\t\tTHREE.Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer );\n\n\t}\n\n\tGLTFCubicSplineInterpolant.prototype = Object.create( THREE.Interpolant.prototype );\n\tGLTFCubicSplineInterpolant.prototype.constructor = GLTFCubicSplineInterpolant;\n\n\tGLTFCubicSplineInterpolant.prototype.copySampleValue_ = function ( index ) {\n\n\t\t\u002F\u002F Copies a sample value to the result buffer. See description of glTF\n\t\t\u002F\u002F CUBICSPLINE values layout in interpolate_() function below.\n\n\t\tvar result = this.resultBuffer,\n\t\t\tvalues = this.sampleValues,\n\t\t\tvalueSize = this.valueSize,\n\t\t\toffset = index * valueSize * 3 + valueSize;\n\n\t\tfor ( var i = 0; i !== valueSize; i ++ ) {\n\n\t\t\tresult[ i ] = values[ offset + i ];\n\n\t\t}\n\n\t\treturn result;\n\n\t};\n\n\tGLTFCubicSplineInterpolant.prototype.beforeStart_ = GLTFCubicSplineInterpolant.prototype.copySampleValue_;\n\n\tGLTFCubicSplineInterpolant.prototype.afterEnd_ = GLTFCubicSplineInterpolant.prototype.copySampleValue_;\n\n\tGLTFCubicSplineInterpolant.prototype.interpolate_ = function ( i1, t0, t, t1 ) {\n\n\t\tvar result = this.resultBuffer;\n\t\tvar values = this.sampleValues;\n\t\tvar stride = this.valueSize;\n\n\t\tvar stride2 = stride * 2;\n\t\tvar stride3 = stride * 3;\n\n\t\tvar td = t1 - t0;\n\n\t\tvar p = ( t - t0 ) \u002F td;\n\t\tvar pp = p * p;\n\t\tvar ppp = pp * p;\n\n\t\tvar offset1 = i1 * stride3;\n\t\tvar offset0 = offset1 - stride3;\n\n\t\tvar s2 = - 2 * ppp + 3 * pp;\n\t\tvar s3 = ppp - pp;\n\t\tvar s0 = 1 - s2;\n\t\tvar s1 = s3 - pp + p;\n\n\t\t\u002F\u002F Layout of keyframe output values for CUBICSPLINE animations:\n\t\t\u002F\u002F [ inTangent_1, splineVertex_1, outTangent_1, inTangent_2, splineVertex_2, ... ]\n\t\tfor ( var i = 0; i !== stride; i ++ ) {\n\n\t\t\tvar p0 = values[ offset0 + i + stride ]; \u002F\u002F splineVertex_k\n\t\t\tvar m0 = values[ offset0 + i + stride2 ] * td; \u002F\u002F outTangent_k * (t_k+1 - t_k)\n\t\t\tvar p1 = values[ offset1 + i + stride ]; \u002F\u002F splineVertex_k+1\n\t\t\tvar m1 = values[ offset1 + i ] * td; \u002F\u002F inTangent_k+1 * (t_k+1 - t_k)\n\n\t\t\tresult[ i ] = s0 * p0 + s1 * m0 + s2 * p1 + s3 * m1;\n\n\t\t}\n\n\t\treturn result;\n\n\t};\n\n\t\u002F*********************************\u002F\n\t\u002F********** INTERNALS ************\u002F\n\t\u002F*********************************\u002F\n\n\t\u002F* CONSTANTS *\u002F\n\n\tvar WEBGL_CONSTANTS = {\n\t\tFLOAT: 5126,\n\t\t\u002F\u002FFLOAT_MAT2: 35674,\n\t\tFLOAT_MAT3: 35675,\n\t\tFLOAT_MAT4: 35676,\n\t\tFLOAT_VEC2: 35664,\n\t\tFLOAT_VEC3: 35665,\n\t\tFLOAT_VEC4: 35666,\n\t\tLINEAR: 9729,\n\t\tREPEAT: 10497,\n\t\tSAMPLER_2D: 35678,\n\t\tPOINTS: 0,\n\t\tLINES: 1,\n\t\tLINE_LOOP: 2,\n\t\tLINE_STRIP: 3,\n\t\tTRIANGLES: 4,\n\t\tTRIANGLE_STRIP: 5,\n\t\tTRIANGLE_FAN: 6,\n\t\tUNSIGNED_BYTE: 5121,\n\t\tUNSIGNED_SHORT: 5123\n\t};\n\n\tvar WEBGL_TYPE = {\n\t\t5126: Number,\n\t\t\u002F\u002F35674: THREE.Matrix2,\n\t\t35675: THREE.Matrix3,\n\t\t35676: THREE.Matrix4,\n\t\t35664: THREE.Vector2,\n\t\t35665: THREE.Vector3,\n\t\t35666: THREE.Vector4,\n\t\t35678: THREE.Texture\n\t};\n\n\tvar WEBGL_COMPONENT_TYPES = {\n\t\t5120: Int8Array,\n\t\t5121: Uint8Array,\n\t\t5122: Int16Array,\n\t\t5123: Uint16Array,\n\t\t5125: Uint32Array,\n\t\t5126: Float32Array\n\t};\n\n\tvar WEBGL_FILTERS = {\n\t\t9728: THREE.NearestFilter,\n\t\t9729: THREE.LinearFilter,\n\t\t9984: THREE.NearestMipMapNearestFilter,\n\t\t9985: THREE.LinearMipMapNearestFilter,\n\t\t9986: THREE.NearestMipMapLinearFilter,\n\t\t9987: THREE.LinearMipMapLinearFilter\n\t};\n\n\tvar WEBGL_WRAPPINGS = {\n\t\t33071: THREE.ClampToEdgeWrapping,\n\t\t33648: THREE.MirroredRepeatWrapping,\n\t\t10497: THREE.RepeatWrapping\n\t};\n\n\tvar WEBGL_SIDES = {\n\t\t1028: THREE.BackSide, \u002F\u002F Culling front\n\t\t1029: THREE.FrontSide \u002F\u002F Culling back\n\t\t\u002F\u002F1032: THREE.NoSide \u002F\u002F Culling front and back, what to do?\n\t};\n\n\tvar WEBGL_DEPTH_FUNCS = {\n\t\t512: THREE.NeverDepth,\n\t\t513: THREE.LessDepth,\n\t\t514: THREE.EqualDepth,\n\t\t515: THREE.LessEqualDepth,\n\t\t516: THREE.GreaterEqualDepth,\n\t\t517: THREE.NotEqualDepth,\n\t\t518: THREE.GreaterEqualDepth,\n\t\t519: THREE.AlwaysDepth\n\t};\n\n\tvar WEBGL_BLEND_EQUATIONS = {\n\t\t32774: THREE.AddEquation,\n\t\t32778: THREE.SubtractEquation,\n\t\t32779: THREE.ReverseSubtractEquation\n\t};\n\n\tvar WEBGL_BLEND_FUNCS = {\n\t\t0: THREE.ZeroFactor,\n\t\t1: THREE.OneFactor,\n\t\t768: THREE.SrcColorFactor,\n\t\t769: THREE.OneMinusSrcColorFactor,\n\t\t770: THREE.SrcAlphaFactor,\n\t\t771: THREE.OneMinusSrcAlphaFactor,\n\t\t772: THREE.DstAlphaFactor,\n\t\t773: THREE.OneMinusDstAlphaFactor,\n\t\t774: THREE.DstColorFactor,\n\t\t775: THREE.OneMinusDstColorFactor,\n\t\t776: THREE.SrcAlphaSaturateFactor\n\t\t\u002F\u002F The followings are not supported by Three.js yet\n\t\t\u002F\u002F32769: CONSTANT_COLOR,\n\t\t\u002F\u002F32770: ONE_MINUS_CONSTANT_COLOR,\n\t\t\u002F\u002F32771: CONSTANT_ALPHA,\n\t\t\u002F\u002F32772: ONE_MINUS_CONSTANT_COLOR\n\t};\n\n\tvar WEBGL_TYPE_SIZES = {\n\t\t'SCALAR': 1,\n\t\t'VEC2': 2,\n\t\t'VEC3': 3,\n\t\t'VEC4': 4,\n\t\t'MAT2': 4,\n\t\t'MAT3': 9,\n\t\t'MAT4': 16\n\t};\n\n\tvar ATTRIBUTES = {\n\t\tPOSITION: 'position',\n\t\tNORMAL: 'normal',\n\t\tTANGENT: 'tangent',\n\t\tTEXCOORD_0: 'uv',\n\t\tTEXCOORD_1: 'uv2',\n\t\tCOLOR_0: 'color',\n\t\tWEIGHTS_0: 'skinWeight',\n\t\tJOINTS_0: 'skinIndex',\n\t};\n\n\tvar PATH_PROPERTIES = {\n\t\tscale: 'scale',\n\t\ttranslation: 'position',\n\t\trotation: 'quaternion',\n\t\tweights: 'morphTargetInfluences'\n\t};\n\n\tvar INTERPOLATION = {\n\t\tCUBICSPLINE: THREE.InterpolateSmooth, \u002F\u002F We use custom interpolation GLTFCubicSplineInterpolation for CUBICSPLINE.\n\t\t \u002F\u002F KeyframeTrack.optimize() can't handle glTF Cubic Spline output values layout,\n\t\t \u002F\u002F using THREE.InterpolateSmooth for KeyframeTrack instantiation to prevent optimization.\n\t\t \u002F\u002F See KeyframeTrack.optimize() for the detail.\n\t\tLINEAR: THREE.InterpolateLinear,\n\t\tSTEP: THREE.InterpolateDiscrete\n\t};\n\n\tvar STATES_ENABLES = {\n\t\t2884: 'CULL_FACE',\n\t\t2929: 'DEPTH_TEST',\n\t\t3042: 'BLEND',\n\t\t3089: 'SCISSOR_TEST',\n\t\t32823: 'POLYGON_OFFSET_FILL',\n\t\t32926: 'SAMPLE_ALPHA_TO_COVERAGE'\n\t};\n\n\tvar ALPHA_MODES = {\n\t\tOPAQUE: 'OPAQUE',\n\t\tMASK: 'MASK',\n\t\tBLEND: 'BLEND'\n\t};\n\n\tvar MIME_TYPE_FORMATS = {\n\t\t'image\u002Fpng': THREE.RGBAFormat,\n\t\t'image\u002Fjpeg': THREE.RGBFormat\n\t};\n\n\t\u002F* UTILITY FUNCTIONS *\u002F\n\n\tfunction resolveURL( url, path ) {\n\n\t\t\u002F\u002F Invalid URL\n\t\tif ( typeof url !== 'string' || url === '' ) return '';\n\n\t\t\u002F\u002F Absolute URL http:\u002F\u002F,https:\u002F\u002F,\u002F\u002F\n\t\tif ( \u002F^(https?:)?\\\u002F\\\u002F\u002Fi.test( url ) ) return url;\n\n\t\t\u002F\u002F Data URI\n\t\tif ( \u002F^data:.*,.*$\u002Fi.test( url ) ) return url;\n\n\t\t\u002F\u002F Blob URL\n\t\tif ( \u002F^blob:.*$\u002Fi.test( url ) ) return url;\n\n\t\t\u002F\u002F Relative URL\n\t\treturn path + url;\n\n\t}\n\n\t\u002F**\n\t * Specification: https:\u002F\u002Fgithub.com\u002FKhronosGroup\u002FglTF\u002Fblob\u002Fmaster\u002Fspecification\u002F2.0\u002FREADME.md#default-material\n\t *\u002F\n\tfunction createDefaultMaterial() {\n\n\t\treturn new THREE.MeshStandardMaterial( {\n\t\t\tcolor: 0xFFFFFF,\n\t\t\temissive: 0x000000,\n\t\t\tmetalness: 1,\n\t\t\troughness: 1,\n\t\t\ttransparent: false,\n\t\t\tdepthTest: true,\n\t\t\tside: THREE.FrontSide\n\t\t} );\n\n\t}\n\n\tfunction addUnknownExtensionsToUserData( knownExtensions, object, objectDef ) {\n\n\t\t\u002F\u002F Add unknown glTF extensions to an object's userData.\n\n\t\tfor ( var name in objectDef.extensions ) {\n\n\t\t\tif ( knownExtensions[ name ] === undefined ) {\n\n\t\t\t\tobject.userData.gltfExtensions = object.userData.gltfExtensions || {};\n\t\t\t\tobject.userData.gltfExtensions[ name ] = objectDef.extensions[ name ];\n\n\t\t\t}\n\n\t\t}\n\n\t}\n\n\t\u002F**\n\t * @param {THREE.Object3D|THREE.Material|THREE.BufferGeometry} object\n\t * @param {GLTF.definition} gltfDef\n\t *\u002F\n\tfunction assignExtrasToUserData( object, gltfDef ) {\n\n\t\tif ( gltfDef.extras !== undefined ) {\n\n\t\t\tif ( typeof gltfDef.extras === 'object' ) {\n\n\t\t\t\tobject.userData = gltfDef.extras;\n\n\t\t\t} else {\n\n\t\t\t\tconsole.warn( 'THREE.GLTFLoader: Ignoring primitive type .extras, ' + gltfDef.extras );\n\n\t\t\t}\n\n\t\t}\n\n\t}\n\n\t\u002F**\n\t * Specification: https:\u002F\u002Fgithub.com\u002FKhronosGroup\u002FglTF\u002Fblob\u002Fmaster\u002Fspecification\u002F2.0\u002FREADME.md#morph-targets\n\t *\n\t * @param {THREE.BufferGeometry} geometry\n\t * @param {Array\u003CGLTF.Target\u003E} targets\n\t * @param {GLTFParser} parser\n\t * @return {Promise\u003CTHREE.BufferGeometry\u003E}\n\t *\u002F\n\tfunction addMorphTargets( geometry, targets, parser ) {\n\n\t\tvar hasMorphPosition = false;\n\t\tvar hasMorphNormal = false;\n\n\t\tfor ( var i = 0, il = targets.length; i \u003C il; i ++ ) {\n\n\t\t\tvar target = targets[ i ];\n\n\t\t\tif ( target.POSITION !== undefined ) hasMorphPosition = true;\n\t\t\tif ( target.NORMAL !== undefined ) hasMorphNormal = true;\n\n\t\t\tif ( hasMorphPosition && hasMorphNormal ) break;\n\n\t\t}\n\n\t\tif ( ! hasMorphPosition && ! hasMorphNormal ) return Promise.resolve( geometry );\n\n\t\tvar pendingPositionAccessors = [];\n\t\tvar pendingNormalAccessors = [];\n\n\t\tfor ( var i = 0, il = targets.length; i \u003C il; i ++ ) {\n\n\t\t\tvar target = targets[ i ];\n\n\t\t\tif ( hasMorphPosition ) {\n\n\t\t\t\t\u002F\u002F TODO: Error-prone use of a callback inside a loop.\n\t\t\t\tvar accessor = target.POSITION !== undefined\n\t\t\t\t\t? parser.getDependency( 'accessor', target.POSITION )\n\t\t\t\t\t\t.then( function ( accessor ) {\n\n\t\t\t\t\t\t\t\u002F\u002F Cloning not to pollute original accessor below\n\t\t\t\t\t\t\treturn cloneBufferAttribute( accessor );\n\n\t\t\t\t\t\t} )\n\t\t\t\t\t: geometry.attributes.position;\n\n\t\t\t\tpendingPositionAccessors.push( accessor );\n\n\t\t\t}\n\n\t\t\tif ( hasMorphNormal ) {\n\n\t\t\t\t\u002F\u002F TODO: Error-prone use of a callback inside a loop.\n\t\t\t\tvar accessor = target.NORMAL !== undefined\n\t\t\t\t\t? parser.getDependency( 'accessor', target.NORMAL )\n\t\t\t\t\t\t.then( function ( accessor ) {\n\n\t\t\t\t\t\t\treturn cloneBufferAttribute( accessor );\n\n\t\t\t\t\t\t} )\n\t\t\t\t\t: geometry.attributes.normal;\n\n\t\t\t\tpendingNormalAccessors.push( accessor );\n\n\t\t\t}\n\n\t\t}\n\n\t\treturn Promise.all( [\n\t\t\tPromise.all( pendingPositionAccessors ),\n\t\t\tPromise.all( pendingNormalAccessors )\n\t\t] ).then( function ( accessors ) {\n\n\t\t\tvar morphPositions = accessors[ 0 ];\n\t\t\tvar morphNormals = accessors[ 1 ];\n\n\t\t\tfor ( var i = 0, il = targets.length; i \u003C il; i ++ ) {\n\n\t\t\t\tvar target = targets[ i ];\n\t\t\t\tvar attributeName = 'morphTarget' + i;\n\n\t\t\t\tif ( hasMorphPosition ) {\n\n\t\t\t\t\t\u002F\u002F Three.js morph position is absolute value. The formula is\n\t\t\t\t\t\u002F\u002F basePosition\n\t\t\t\t\t\u002F\u002F + weight0 * ( morphPosition0 - basePosition )\n\t\t\t\t\t\u002F\u002F + weight1 * ( morphPosition1 - basePosition )\n\t\t\t\t\t\u002F\u002F ...\n\t\t\t\t\t\u002F\u002F while the glTF one is relative\n\t\t\t\t\t\u002F\u002F basePosition\n\t\t\t\t\t\u002F\u002F + weight0 * glTFmorphPosition0\n\t\t\t\t\t\u002F\u002F + weight1 * glTFmorphPosition1\n\t\t\t\t\t\u002F\u002F ...\n\t\t\t\t\t\u002F\u002F then we need to convert from relative to absolute here.\n\n\t\t\t\t\tif ( target.POSITION !== undefined ) {\n\n\t\t\t\t\t\tvar positionAttribute = morphPositions[ i ];\n\t\t\t\t\t\tpositionAttribute.name = attributeName;\n\n\t\t\t\t\t\tvar position = geometry.attributes.position;\n\n\t\t\t\t\t\tfor ( var j = 0, jl = positionAttribute.count; j \u003C jl; j ++ ) {\n\n\t\t\t\t\t\t\tpositionAttribute.setXYZ(\n\t\t\t\t\t\t\t\tj,\n\t\t\t\t\t\t\t\tpositionAttribute.getX( j ) + position.getX( j ),\n\t\t\t\t\t\t\t\tpositionAttribute.getY( j ) + position.getY( j ),\n\t\t\t\t\t\t\t\tpositionAttribute.getZ( j ) + position.getZ( j )\n\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\tif ( hasMorphNormal ) {\n\n\t\t\t\t\t\u002F\u002F see target.POSITION's comment\n\n\t\t\t\t\tif ( target.NORMAL !== undefined ) {\n\n\t\t\t\t\t\tvar normalAttribute = morphNormals[ i ];\n\t\t\t\t\t\tnormalAttribute.name = attributeName;\n\n\t\t\t\t\t\tvar normal = geometry.attributes.normal;\n\n\t\t\t\t\t\tfor ( var j = 0, jl = normalAttribute.count; j \u003C jl; j ++ ) {\n\n\t\t\t\t\t\t\tnormalAttribute.setXYZ(\n\t\t\t\t\t\t\t\tj,\n\t\t\t\t\t\t\t\tnormalAttribute.getX( j ) + normal.getX( j ),\n\t\t\t\t\t\t\t\tnormalAttribute.getY( j ) + normal.getY( j ),\n\t\t\t\t\t\t\t\tnormalAttribute.getZ( j ) + normal.getZ( j )\n\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tif ( hasMorphPosition ) geometry.morphAttributes.position = morphPositions;\n\t\t\tif ( hasMorphNormal ) geometry.morphAttributes.normal = morphNormals;\n\n\t\t\treturn geometry;\n\n\t\t} );\n\n\t}\n\n\t\u002F**\n\t * @param {THREE.Mesh} mesh\n\t * @param {GLTF.Mesh} meshDef\n\t *\u002F\n\tfunction updateMorphTargets( mesh, meshDef ) {\n\n\t\tmesh.updateMorphTargets();\n\n\t\tif ( meshDef.weights !== undefined ) {\n\n\t\t\tfor ( var i = 0, il = meshDef.weights.length; i \u003C il; i ++ ) {\n\n\t\t\t\tmesh.morphTargetInfluences[ i ] = meshDef.weights[ i ];\n\n\t\t\t}\n\n\t\t}\n\n\t\t\u002F\u002F .extras has user-defined data, so check that .extras.targetNames is an array.\n\t\tif ( meshDef.extras && Array.isArray( meshDef.extras.targetNames ) ) {\n\n\t\t\tvar targetNames = meshDef.extras.targetNames;\n\n\t\t\tif ( mesh.morphTargetInfluences.length === targetNames.length ) {\n\n\t\t\t\tmesh.morphTargetDictionary = {};\n\n\t\t\t\tfor ( var i = 0, il = targetNames.length; i \u003C il; i ++ ) {\n\n\t\t\t\t\tmesh.morphTargetDictionary[ targetNames[ i ] ] = i;\n\n\t\t\t\t}\n\n\t\t\t} else {\n\n\t\t\t\tconsole.warn( 'THREE.GLTFLoader: Invalid extras.targetNames length. Ignoring names.' );\n\n\t\t\t}\n\n\t\t}\n\n\t}\n\tfunction isObjectEqual( a, b ) {\n\n\t\tif ( Object.keys( a ).length !== Object.keys( b ).length ) return false;\n\n\t\tfor ( var key in a ) {\n\n\t\t\tif ( a[ key ] !== b[ key ] ) return false;\n\n\t\t}\n\n\t\treturn true;\n\n\t}\n\n\tfunction createPrimitiveKey( primitiveDef ) {\n\n\t\tvar dracoExtension = primitiveDef.extensions && primitiveDef.extensions[ EXTENSIONS.KHR_DRACO_MESH_COMPRESSION ];\n\t\tvar geometryKey;\n\n\t\tif ( dracoExtension ) {\n\n\t\t\tgeometryKey = 'draco:' + dracoExtension.bufferView\n\t\t\t\t+ ':' + dracoExtension.indices\n\t\t\t\t+ ':' + createAttributesKey( dracoExtension.attributes );\n\n\t\t} else {\n\n\t\t\tgeometryKey = primitiveDef.indices + ':' + createAttributesKey( primitiveDef.attributes ) + ':' + primitiveDef.mode;\n\n\t\t}\n\n\t\treturn geometryKey;\n\n\t}\n\n\tfunction createAttributesKey( attributes ) {\n\n\t\tvar attributesKey = '';\n\n\t\tvar keys = Object.keys( attributes ).sort();\n\n\t\tfor ( var i = 0, il = keys.length; i \u003C il; i ++ ) {\n\n\t\t\tattributesKey += keys[ i ] + ':' + attributes[ keys[ i ] ] + ';';\n\n\t\t}\n\n\t\treturn attributesKey;\n\n\t}\n\n\tfunction createArrayKeyBufferGeometry( a ) {\n\n\t\tvar arrayKey = '';\n\n\t\tfor ( var i = 0, il = a.length; i \u003C il; i ++ ) {\n\n\t\t\tarrayKey += ':' + a[ i ].uuid;\n\n\t\t}\n\n\t\treturn arrayKey;\n\n\t}\n\n\tfunction createMultiPassGeometryKey( geometry, primitives ) {\n\n\t\tvar key = geometry.uuid;\n\n\t\tfor ( var i = 0, il = primitives.length; i \u003C il; i ++ ) {\n\n\t\t\tkey += i + createPrimitiveKey( primitives[ i ] );\n\n\t\t}\n\n\t\treturn key;\n\n\t}\n\n\tfunction cloneBufferAttribute( attribute ) {\n\n\t\tif ( attribute.isInterleavedBufferAttribute ) {\n\n\t\t\tvar count = attribute.count;\n\t\t\tvar itemSize = attribute.itemSize;\n\t\t\tvar array = attribute.array.slice( 0, count * itemSize );\n\n\t\t\tfor ( var i = 0, j = 0; i \u003C count; ++ i ) {\n\n\t\t\t\tarray[ j ++ ] = attribute.getX( i );\n\t\t\t\tif ( itemSize \u003E= 2 ) array[ j ++ ] = attribute.getY( i );\n\t\t\t\tif ( itemSize \u003E= 3 ) array[ j ++ ] = attribute.getZ( i );\n\t\t\t\tif ( itemSize \u003E= 4 ) array[ j ++ ] = attribute.getW( i );\n\n\t\t\t}\n\n\t\t\treturn new THREE.BufferAttribute( array, itemSize, attribute.normalized );\n\n\t\t}\n\n\t\treturn attribute.clone();\n\n\t}\n\n\t\u002F**\n\t * Checks if we can build a single Mesh with MultiMaterial from multiple primitives.\n\t * Returns true if all primitives use the same attributes\u002FmorphAttributes\u002Fmode\n\t * and also have index. Otherwise returns false.\n\t *\n\t * @param {Array\u003CGLTF.Primitive\u003E} primitives\n\t * @return {Boolean}\n\t *\u002F\n\tfunction isMultiPassGeometry( primitives ) {\n\n\t\tif ( primitives.length \u003C 2 ) return false;\n\n\t\tvar primitive0 = primitives[ 0 ];\n\t\tvar targets0 = primitive0.targets || [];\n\n\t\tif ( primitive0.indices === undefined ) return false;\n\n\t\tfor ( var i = 1, il = primitives.length; i \u003C il; i ++ ) {\n\n\t\t\tvar primitive = primitives[ i ];\n\n\t\t\tif ( primitive0.mode !== primitive.mode ) return false;\n\t\t\tif ( primitive.indices === undefined ) return false;\n\t\t\tif ( primitive.extensions && primitive.extensions[ EXTENSIONS.KHR_DRACO_MESH_COMPRESSION ] ) return false;\n\t\t\tif ( ! isObjectEqual( primitive0.attributes, primitive.attributes ) ) return false;\n\n\t\t\tvar targets = primitive.targets || [];\n\n\t\t\tif ( targets0.length !== targets.length ) return false;\n\n\t\t\tfor ( var j = 0, jl = targets0.length; j \u003C jl; j ++ ) {\n\n\t\t\t\tif ( ! isObjectEqual( targets0[ j ], targets[ j ] ) ) return false;\n\n\t\t\t}\n\n\t\t}\n\n\t\treturn true;\n\n\t}\n\n\t\u002F* GLTF PARSER *\u002F\n\n\tfunction GLTFParser( json, extensions, options ) {\n\n\t\tthis.json = json || {};\n\t\tthis.extensions = extensions || {};\n\t\tthis.options = options || {};\n\n\t\t\u002F\u002F loader object cache\n\t\tthis.cache = new GLTFRegistry();\n\n\t\t\u002F\u002F BufferGeometry caching\n\t\tthis.primitiveCache = {};\n\t\tthis.multiplePrimitivesCache = {};\n\t\tthis.multiPassGeometryCache = {};\n\n\t\tthis.textureLoader = new THREE.TextureLoader( this.options.manager );\n\t\tthis.textureLoader.setCrossOrigin( this.options.crossOrigin );\n\n\t\tthis.fileLoader = new THREE.FileLoader( this.options.manager );\n\t\tthis.fileLoader.setResponseType( 'arraybuffer' );\n\n\t}\n\n\tGLTFParser.prototype.parse = function ( onLoad, onError ) {\n\n\t\tvar json = this.json;\n\n\t\t\u002F\u002F Clear the loader cache\n\t\tthis.cache.removeAll();\n\n\t\t\u002F\u002F Mark the special nodes\u002Fmeshes in json for efficient parse\n\t\tthis.markDefs();\n\n\t\t\u002F\u002F Fire the callback on complete\n\t\tthis.getMultiDependencies( [\n\n\t\t\t'scene',\n\t\t\t'animation',\n\t\t\t'camera'\n\n\t\t] ).then( function ( dependencies ) {\n\n\t\t\tvar scenes = dependencies.scenes || [];\n\t\t\tvar scene = scenes[ json.scene || 0 ];\n\t\t\tvar animations = dependencies.animations || [];\n\t\t\tvar cameras = dependencies.cameras || [];\n\n\t\t\tonLoad( scene, scenes, cameras, animations, json );\n\n\t\t} ).catch( onError );\n\n\t};\n\n\t\u002F**\n\t * Marks the special nodes\u002Fmeshes in json for efficient parse.\n\t *\u002F\n\tGLTFParser.prototype.markDefs = function () {\n\n\t\tvar nodeDefs = this.json.nodes || [];\n\t\tvar skinDefs = this.json.skins || [];\n\t\tvar meshDefs = this.json.meshes || [];\n\n\t\tvar meshReferences = {};\n\t\tvar meshUses = {};\n\n\t\t\u002F\u002F Nothing in the node definition indicates whether it is a Bone or an\n\t\t\u002F\u002F Object3D. Use the skins' joint references to mark bones.\n\t\tfor ( var skinIndex = 0, skinLength = skinDefs.length; skinIndex \u003C skinLength; skinIndex ++ ) {\n\n\t\t\tvar joints = skinDefs[ skinIndex ].joints;\n\n\t\t\tfor ( var i = 0, il = joints.length; i \u003C il; i ++ ) {\n\n\t\t\t\tnodeDefs[ joints[ i ] ].isBone = true;\n\n\t\t\t}\n\n\t\t}\n\n\t\t\u002F\u002F Meshes can (and should) be reused by multiple nodes in a glTF asset. To\n\t\t\u002F\u002F avoid having more than one THREE.Mesh with the same name, count\n\t\t\u002F\u002F references and rename instances below.\n\t\t\u002F\u002F\n\t\t\u002F\u002F Example: CesiumMilkTruck sample model reuses \"Wheel\" meshes.\n\t\tfor ( var nodeIndex = 0, nodeLength = nodeDefs.length; nodeIndex \u003C nodeLength; nodeIndex ++ ) {\n\n\t\t\tvar nodeDef = nodeDefs[ nodeIndex ];\n\n\t\t\tif ( nodeDef.mesh !== undefined ) {\n\n\t\t\t\tif ( meshReferences[ nodeDef.mesh ] === undefined ) {\n\n\t\t\t\t\tmeshReferences[ nodeDef.mesh ] = meshUses[ nodeDef.mesh ] = 0;\n\n\t\t\t\t}\n\n\t\t\t\tmeshReferences[ nodeDef.mesh ] ++;\n\n\t\t\t\t\u002F\u002F Nothing in the mesh definition indicates whether it is\n\t\t\t\t\u002F\u002F a SkinnedMesh or Mesh. Use the node's mesh reference\n\t\t\t\t\u002F\u002F to mark SkinnedMesh if node has skin.\n\t\t\t\tif ( nodeDef.skin !== undefined ) {\n\n\t\t\t\t\tmeshDefs[ nodeDef.mesh ].isSkinnedMesh = true;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\tthis.json.meshReferences = meshReferences;\n\t\tthis.json.meshUses = meshUses;\n\n\t};\n\n\t\u002F**\n\t * Requests the specified dependency asynchronously, with caching.\n\t * @param {string} type\n\t * @param {number} index\n\t * @return {Promise\u003CTHREE.Object3D|THREE.Material|THREE.Texture|THREE.AnimationClip|ArrayBuffer|Object\u003E}\n\t *\u002F\n\tGLTFParser.prototype.getDependency = function ( type, index ) {\n\n\t\tvar cacheKey = type + ':' + index;\n\t\tvar dependency = this.cache.get( cacheKey );\n\n\t\tif ( ! dependency ) {\n\n\t\t\tswitch ( type ) {\n\n\t\t\t\tcase 'scene':\n\t\t\t\t\tdependency = this.loadScene( index );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'node':\n\t\t\t\t\tdependency = this.loadNode( index );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'mesh':\n\t\t\t\t\tdependency = this.loadMesh( index );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'accessor':\n\t\t\t\t\tdependency = this.loadAccessor( index );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'bufferView':\n\t\t\t\t\tdependency = this.loadBufferView( index );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'buffer':\n\t\t\t\t\tdependency = this.loadBuffer( index );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'material':\n\t\t\t\t\tdependency = this.loadMaterial( index );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'texture':\n\t\t\t\t\tdependency = this.loadTexture( index );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'skin':\n\t\t\t\t\tdependency = this.loadSkin( index );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'animation':\n\t\t\t\t\tdependency = this.loadAnimation( index );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'camera':\n\t\t\t\t\tdependency = this.loadCamera( index );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'light':\n\t\t\t\t\tdependency = this.extensions[ EXTENSIONS.KHR_LIGHTS_PUNCTUAL ].loadLight( index );\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tthrow new Error( 'Unknown type: ' + type );\n\n\t\t\t}\n\n\t\t\tthis.cache.add( cacheKey, dependency );\n\n\t\t}\n\n\t\treturn dependency;\n\n\t};\n\n\t\u002F**\n\t * Requests all dependencies of the specified type asynchronously, with caching.\n\t * @param {string} type\n\t * @return {Promise\u003CArray\u003CObject\u003E\u003E}\n\t *\u002F\n\tGLTFParser.prototype.getDependencies = function ( type ) {\n\n\t\tvar dependencies = this.cache.get( type );\n\n\t\tif ( ! dependencies ) {\n\n\t\t\tvar parser = this;\n\t\t\tvar defs = this.json[ type + ( type === 'mesh' ? 'es' : 's' ) ] || [];\n\n\t\t\tdependencies = Promise.all( defs.map( function ( def, index ) {\n\n\t\t\t\treturn parser.getDependency( type, index );\n\n\t\t\t} ) );\n\n\t\t\tthis.cache.add( type, dependencies );\n\n\t\t}\n\n\t\treturn dependencies;\n\n\t};\n\n\t\u002F**\n\t * Requests all multiple dependencies of the specified types asynchronously, with caching.\n\t * @param {Array\u003Cstring\u003E} types\n\t * @return {Promise\u003CObject\u003CArray\u003CObject\u003E\u003E\u003E}\n\t *\u002F\n\tGLTFParser.prototype.getMultiDependencies = function ( types ) {\n\n\t\tvar results = {};\n\t\tvar pending = [];\n\n\t\tfor ( var i = 0, il = types.length; i \u003C il; i ++ ) {\n\n\t\t\tvar type = types[ i ];\n\t\t\tvar value = this.getDependencies( type );\n\n\t\t\t\u002F\u002F TODO: Error-prone use of a callback inside a loop.\n\t\t\tvalue = value.then( function ( key, value ) {\n\n\t\t\t\tresults[ key ] = value;\n\n\t\t\t}.bind( this, type + ( type === 'mesh' ? 'es' : 's' ) ) );\n\n\t\t\tpending.push( value );\n\n\t\t}\n\n\t\treturn Promise.all( pending ).then( function () {\n\n\t\t\treturn results;\n\n\t\t} );\n\n\t};\n\n\t\u002F**\n\t * Specification: https:\u002F\u002Fgithub.com\u002FKhronosGroup\u002FglTF\u002Fblob\u002Fmaster\u002Fspecification\u002F2.0\u002FREADME.md#buffers-and-buffer-views\n\t * @param {number} bufferIndex\n\t * @return {Promise\u003CArrayBuffer\u003E}\n\t *\u002F\n\tGLTFParser.prototype.loadBuffer = function ( bufferIndex ) {\n\n\t\tvar bufferDef = this.json.buffers[ bufferIndex ];\n\t\tvar loader = this.fileLoader;\n\n\t\tif ( bufferDef.type && bufferDef.type !== 'arraybuffer' ) {\n\n\t\t\tthrow new Error( 'THREE.GLTFLoader: ' + bufferDef.type + ' buffer type is not supported.' );\n\n\t\t}\n\n\t\t\u002F\u002F If present, GLB container is required to be the first buffer.\n\t\tif ( bufferDef.uri === undefined && bufferIndex === 0 ) {\n\n\t\t\treturn Promise.resolve( this.extensions[ EXTENSIONS.KHR_BINARY_GLTF ].body );\n\n\t\t}\n\n\t\tvar options = this.options;\n\n\t\treturn new Promise( function ( resolve, reject ) {\n\n\t\t\tloader.load( resolveURL( bufferDef.uri, options.path ), resolve, undefined, function () {\n\n\t\t\t\treject( new Error( 'THREE.GLTFLoader: Failed to load buffer \"' + bufferDef.uri + '\".' ) );\n\n\t\t\t} );\n\n\t\t} );\n\n\t};\n\n\t\u002F**\n\t * Specification: https:\u002F\u002Fgithub.com\u002FKhronosGroup\u002FglTF\u002Fblob\u002Fmaster\u002Fspecification\u002F2.0\u002FREADME.md#buffers-and-buffer-views\n\t * @param {number} bufferViewIndex\n\t * @return {Promise\u003CArrayBuffer\u003E}\n\t *\u002F\n\tGLTFParser.prototype.loadBufferView = function ( bufferViewIndex ) {\n\n\t\tvar bufferViewDef = this.json.bufferViews[ bufferViewIndex ];\n\n\t\treturn this.getDependency( 'buffer', bufferViewDef.buffer ).then( function ( buffer ) {\n\n\t\t\tvar byteLength = bufferViewDef.byteLength || 0;\n\t\t\tvar byteOffset = bufferViewDef.byteOffset || 0;\n\t\t\treturn buffer.slice( byteOffset, byteOffset + byteLength );\n\n\t\t} );\n\n\t};\n\n\t\u002F**\n\t * Specification: https:\u002F\u002Fgithub.com\u002FKhronosGroup\u002FglTF\u002Fblob\u002Fmaster\u002Fspecification\u002F2.0\u002FREADME.md#accessors\n\t * @param {number} accessorIndex\n\t * @return {Promise\u003CTHREE.BufferAttribute|THREE.InterleavedBufferAttribute\u003E}\n\t *\u002F\n\tGLTFParser.prototype.loadAccessor = function ( accessorIndex ) {\n\n\t\tvar parser = this;\n\t\tvar json = this.json;\n\n\t\tvar accessorDef = this.json.accessors[ accessorIndex ];\n\n\t\tif ( accessorDef.bufferView === undefined && accessorDef.sparse === undefined ) {\n\n\t\t\t\u002F\u002F Ignore empty accessors, which may be used to declare runtime\n\t\t\t\u002F\u002F information about attributes coming from another source (e.g. Draco\n\t\t\t\u002F\u002F compression extension).\n\t\t\treturn Promise.resolve( null );\n\n\t\t}\n\n\t\tvar pendingBufferViews = [];\n\n\t\tif ( accessorDef.bufferView !== undefined ) {\n\n\t\t\tpendingBufferViews.push( this.getDependency( 'bufferView', accessorDef.bufferView ) );\n\n\t\t} else {\n\n\t\t\tpendingBufferViews.push( null );\n\n\t\t}\n\n\t\tif ( accessorDef.sparse !== undefined ) {\n\n\t\t\tpendingBufferViews.push( this.getDependency( 'bufferView', accessorDef.sparse.indices.bufferView ) );\n\t\t\tpendingBufferViews.push( this.getDependency( 'bufferView', accessorDef.sparse.values.bufferView ) );\n\n\t\t}\n\n\t\treturn Promise.all( pendingBufferViews ).then( function ( bufferViews ) {\n\n\t\t\tvar bufferView = bufferViews[ 0 ];\n\n\t\t\tvar itemSize = WEBGL_TYPE_SIZES[ accessorDef.type ];\n\t\t\tvar TypedArray = WEBGL_COMPONENT_TYPES[ accessorDef.componentType ];\n\n\t\t\t\u002F\u002F For VEC3: itemSize is 3, elementBytes is 4, itemBytes is 12.\n\t\t\tvar elementBytes = TypedArray.BYTES_PER_ELEMENT;\n\t\t\tvar itemBytes = elementBytes * itemSize;\n\t\t\tvar byteOffset = accessorDef.byteOffset || 0;\n\t\t\tvar byteStride = accessorDef.bufferView !== undefined ? json.bufferViews[ accessorDef.bufferView ].byteStride : undefined;\n\t\t\tvar normalized = accessorDef.normalized === true;\n\t\t\tvar array, bufferAttribute;\n\n\t\t\t\u002F\u002F The buffer is not interleaved if the stride is the item size in bytes.\n\t\t\tif ( byteStride && byteStride !== itemBytes ) {\n\n\t\t\t\tvar ibCacheKey = 'InterleavedBuffer:' + accessorDef.bufferView + ':' + accessorDef.componentType;\n\t\t\t\tvar ib = parser.cache.get( ibCacheKey );\n\n\t\t\t\tif ( ! ib ) {\n\n\t\t\t\t\t\u002F\u002F Use the full buffer if it's interleaved.\n\t\t\t\t\tarray = new TypedArray( bufferView );\n\n\t\t\t\t\t\u002F\u002F Integer parameters to IB\u002FIBA are in array elements, not bytes.\n\t\t\t\t\tib = new THREE.InterleavedBuffer( array, byteStride \u002F elementBytes );\n\n\t\t\t\t\tparser.cache.add( ibCacheKey, ib );\n\n\t\t\t\t}\n\n\t\t\t\tbufferAttribute = new THREE.InterleavedBufferAttribute( ib, itemSize, byteOffset \u002F elementBytes, normalized );\n\n\t\t\t} else {\n\n\t\t\t\tif ( bufferView === null ) {\n\n\t\t\t\t\tarray = new TypedArray( accessorDef.count * itemSize );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tarray = new TypedArray( bufferView, byteOffset, accessorDef.count * itemSize );\n\n\t\t\t\t}\n\n\t\t\t\tbufferAttribute = new THREE.BufferAttribute( array, itemSize, normalized );\n\n\t\t\t}\n\n\t\t\t\u002F\u002F https:\u002F\u002Fgithub.com\u002FKhronosGroup\u002FglTF\u002Fblob\u002Fmaster\u002Fspecification\u002F2.0\u002FREADME.md#sparse-accessors\n\t\t\tif ( accessorDef.sparse !== undefined ) {\n\n\t\t\t\tvar itemSizeIndices = WEBGL_TYPE_SIZES.SCALAR;\n\t\t\t\tvar TypedArrayIndices = WEBGL_COMPONENT_TYPES[ accessorDef.sparse.indices.componentType ];\n\n\t\t\t\tvar byteOffsetIndices = accessorDef.sparse.indices.byteOffset || 0;\n\t\t\t\tvar byteOffsetValues = accessorDef.sparse.values.byteOffset || 0;\n\n\t\t\t\tvar sparseIndices = new TypedArrayIndices( bufferViews[ 1 ], byteOffsetIndices, accessorDef.sparse.count * itemSizeIndices );\n\t\t\t\tvar sparseValues = new TypedArray( bufferViews[ 2 ], byteOffsetValues, accessorDef.sparse.count * itemSize );\n\n\t\t\t\tif ( bufferView !== null ) {\n\n\t\t\t\t\t\u002F\u002F Avoid modifying the original ArrayBuffer, if the bufferView wasn't initialized with zeroes.\n\t\t\t\t\tbufferAttribute.setArray( bufferAttribute.array.slice() );\n\n\t\t\t\t}\n\n\t\t\t\tfor ( var i = 0, il = sparseIndices.length; i \u003C il; i ++ ) {\n\n\t\t\t\t\tvar index = sparseIndices[ i ];\n\n\t\t\t\t\tbufferAttribute.setX( index, sparseValues[ i * itemSize ] );\n\t\t\t\t\tif ( itemSize \u003E= 2 ) bufferAttribute.setY( index, sparseValues[ i * itemSize + 1 ] );\n\t\t\t\t\tif ( itemSize \u003E= 3 ) bufferAttribute.setZ( index, sparseValues[ i * itemSize + 2 ] );\n\t\t\t\t\tif ( itemSize \u003E= 4 ) bufferAttribute.setW( index, sparseValues[ i * itemSize + 3 ] );\n\t\t\t\t\tif ( itemSize \u003E= 5 ) throw new Error( 'THREE.GLTFLoader: Unsupported itemSize in sparse BufferAttribute.' );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn bufferAttribute;\n\n\t\t} );\n\n\t};\n\n\t\u002F**\n\t * Specification: https:\u002F\u002Fgithub.com\u002FKhronosGroup\u002FglTF\u002Ftree\u002Fmaster\u002Fspecification\u002F2.0#textures\n\t * @param {number} textureIndex\n\t * @return {Promise\u003CTHREE.Texture\u003E}\n\t *\u002F\n\tGLTFParser.prototype.loadTexture = function ( textureIndex ) {\n\n\t\tvar parser = this;\n\t\tvar json = this.json;\n\t\tvar options = this.options;\n\t\tvar textureLoader = this.textureLoader;\n\n\t\tvar URL = window.URL || window.webkitURL;\n\n\t\tvar textureDef = json.textures[ textureIndex ];\n\n\t\tvar textureExtensions = textureDef.extensions || {};\n\n\t\tvar source;\n\n\t\tif ( textureExtensions[ EXTENSIONS.MSFT_TEXTURE_DDS ] ) {\n\n\t\t\tsource = json.images[ textureExtensions[ EXTENSIONS.MSFT_TEXTURE_DDS ].source ];\n\n\t\t} else {\n\n\t\t\tsource = json.images[ textureDef.source ];\n\n\t\t}\n\n\t\tvar sourceURI = source.uri;\n\t\tvar isObjectURL = false;\n\n\t\tif ( source.bufferView !== undefined ) {\n\n\t\t\t\u002F\u002F Load binary image data from bufferView, if provided.\n\n\t\t\tsourceURI = parser.getDependency( 'bufferView', source.bufferView ).then( function ( bufferView ) {\n\n\t\t\t\tisObjectURL = true;\n\t\t\t\tvar blob = new Blob( [ bufferView ], { type: source.mimeType } );\n\t\t\t\tsourceURI = URL.createObjectURL( blob );\n\t\t\t\treturn sourceURI;\n\n\t\t\t} );\n\n\t\t}\n\n\t\treturn Promise.resolve( sourceURI ).then( function ( sourceURI ) {\n\n\t\t\t\u002F\u002F Load Texture resource.\n\n\t\t\tvar loader = THREE.Loader.Handlers.get( sourceURI );\n\n\t\t\tif ( ! loader ) {\n\n\t\t\t\tloader = textureExtensions[ EXTENSIONS.MSFT_TEXTURE_DDS ]\n\t\t\t\t\t? parser.extensions[ EXTENSIONS.MSFT_TEXTURE_DDS ].ddsLoader\n\t\t\t\t\t: textureLoader;\n\n\t\t\t}\n\n\t\t\treturn new Promise( function ( resolve, reject ) {\n\n\t\t\t\tloader.load( resolveURL( sourceURI, options.path ), resolve, undefined, reject );\n\n\t\t\t} );\n\n\t\t} ).then( function ( texture ) {\n\n\t\t\t\u002F\u002F Clean up resources and configure Texture.\n\n\t\t\tif ( isObjectURL === true ) {\n\n\t\t\t\tURL.revokeObjectURL( sourceURI );\n\n\t\t\t}\n\n\t\t\ttexture.flipY = false;\n\n\t\t\tif ( textureDef.name !== undefined ) texture.name = textureDef.name;\n\n\t\t\t\u002F\u002F Ignore unknown mime types, like DDS files.\n\t\t\tif ( source.mimeType in MIME_TYPE_FORMATS ) {\n\n\t\t\t\ttexture.format = MIME_TYPE_FORMATS[ source.mimeType ];\n\n\t\t\t}\n\n\t\t\tvar samplers = json.samplers || {};\n\t\t\tvar sampler = samplers[ textureDef.sampler ] || {};\n\n\t\t\ttexture.magFilter = WEBGL_FILTERS[ sampler.magFilter ] || THREE.LinearFilter;\n\t\t\ttexture.minFilter = WEBGL_FILTERS[ sampler.minFilter ] || THREE.LinearMipMapLinearFilter;\n\t\t\ttexture.wrapS = WEBGL_WRAPPINGS[ sampler.wrapS ] || THREE.RepeatWrapping;\n\t\t\ttexture.wrapT = WEBGL_WRAPPINGS[ sampler.wrapT ] || THREE.RepeatWrapping;\n\n\t\t\treturn texture;\n\n\t\t} );\n\n\t};\n\n\t\u002F**\n\t * Asynchronously assigns a texture to the given material parameters.\n\t * @param {Object} materialParams\n\t * @param {string} mapName\n\t * @param {Object} mapDef\n\t * @return {Promise}\n\t *\u002F\n\tGLTFParser.prototype.assignTexture = function ( materialParams, mapName, mapDef ) {\n\n\t\tvar parser = this;\n\n\t\treturn this.getDependency( 'texture', mapDef.index ).then( function ( texture ) {\n\n\t\t\tswitch ( mapName ) {\n\n\t\t\t\tcase 'aoMap':\n\t\t\t\tcase 'emissiveMap':\n\t\t\t\tcase 'metalnessMap':\n\t\t\t\tcase 'normalMap':\n\t\t\t\tcase 'roughnessMap':\n\t\t\t\t\ttexture.format = THREE.RGBFormat;\n\t\t\t\t\tbreak;\n\n\t\t\t}\n\n\t\t\tif ( parser.extensions[ EXTENSIONS.KHR_TEXTURE_TRANSFORM ] ) {\n\n\t\t\t\tvar transform = mapDef.extensions !== undefined ? mapDef.extensions[ EXTENSIONS.KHR_TEXTURE_TRANSFORM ] : undefined;\n\n\t\t\t\tif ( transform ) {\n\n\t\t\t\t\ttexture = parser.extensions[ EXTENSIONS.KHR_TEXTURE_TRANSFORM ].extendTexture( texture, transform );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tmaterialParams[ mapName ] = texture;\n\n\t\t} );\n\n\t};\n\n\t\u002F**\n\t * Specification: https:\u002F\u002Fgithub.com\u002FKhronosGroup\u002FglTF\u002Fblob\u002Fmaster\u002Fspecification\u002F2.0\u002FREADME.md#materials\n\t * @param {number} materialIndex\n\t * @return {Promise\u003CTHREE.Material\u003E}\n\t *\u002F\n\tGLTFParser.prototype.loadMaterial = function ( materialIndex ) {\n\n\t\tvar parser = this;\n\t\tvar json = this.json;\n\t\tvar extensions = this.extensions;\n\t\tvar materialDef = json.materials[ materialIndex ];\n\n\t\tvar materialType;\n\t\tvar materialParams = {};\n\t\tvar materialExtensions = materialDef.extensions || {};\n\n\t\tvar pending = [];\n\n\t\tif ( materialExtensions[ EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS ] ) {\n\n\t\t\tvar sgExtension = extensions[ EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS ];\n\t\t\tmaterialType = sgExtension.getMaterialType( materialDef );\n\t\t\tpending.push( sgExtension.extendParams( materialParams, materialDef, parser ) );\n\n\t\t} else if ( materialExtensions[ EXTENSIONS.KHR_MATERIALS_UNLIT ] ) {\n\n\t\t\tvar kmuExtension = extensions[ EXTENSIONS.KHR_MATERIALS_UNLIT ];\n\t\t\tmaterialType = kmuExtension.getMaterialType( materialDef );\n\t\t\tpending.push( kmuExtension.extendParams( materialParams, materialDef, parser ) );\n\n\t\t} else {\n\n\t\t\t\u002F\u002F Specification:\n\t\t\t\u002F\u002F https:\u002F\u002Fgithub.com\u002FKhronosGroup\u002FglTF\u002Ftree\u002Fmaster\u002Fspecification\u002F2.0#metallic-roughness-material\n\n\t\t\tmaterialType = THREE.MeshStandardMaterial;\n\n\t\t\tvar metallicRoughness = materialDef.pbrMetallicRoughness || {};\n\n\t\t\tmaterialParams.color = new THREE.Color( 1.0, 1.0, 1.0 );\n\t\t\tmaterialParams.opacity = 1.0;\n\n\t\t\tif ( Array.isArray( metallicRoughness.baseColorFactor ) ) {\n\n\t\t\t\tvar array = metallicRoughness.baseColorFactor;\n\n\t\t\t\tmaterialParams.color.fromArray( array );\n\t\t\t\tmaterialParams.opacity = array[ 3 ];\n\n\t\t\t}\n\n\t\t\tif ( metallicRoughness.baseColorTexture !== undefined ) {\n\n\t\t\t\tpending.push( parser.assignTexture( materialParams, 'map', metallicRoughness.baseColorTexture ) );\n\n\t\t\t}\n\n\t\t\tmaterialParams.metalness = metallicRoughness.metallicFactor !== undefined ? metallicRoughness.metallicFactor : 1.0;\n\t\t\tmaterialParams.roughness = metallicRoughness.roughnessFactor !== undefined ? metallicRoughness.roughnessFactor : 1.0;\n\n\t\t\tif ( metallicRoughness.metallicRoughnessTexture !== undefined ) {\n\n\t\t\t\tpending.push( parser.assignTexture( materialParams, 'metalnessMap', metallicRoughness.metallicRoughnessTexture ) );\n\t\t\t\tpending.push( parser.assignTexture( materialParams, 'roughnessMap', metallicRoughness.metallicRoughnessTexture ) );\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( materialDef.doubleSided === true ) {\n\n\t\t\tmaterialParams.side = THREE.DoubleSide;\n\n\t\t}\n\n\t\tvar alphaMode = materialDef.alphaMode || ALPHA_MODES.OPAQUE;\n\n\t\tif ( alphaMode === ALPHA_MODES.BLEND ) {\n\n\t\t\tmaterialParams.transparent = true;\n\n\t\t} else {\n\n\t\t\tmaterialParams.transparent = false;\n\n\t\t\tif ( alphaMode === ALPHA_MODES.MASK ) {\n\n\t\t\t\tmaterialParams.alphaTest = materialDef.alphaCutoff !== undefined ? materialDef.alphaCutoff : 0.5;\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( materialDef.normalTexture !== undefined && materialType !== THREE.MeshBasicMaterial ) {\n\n\t\t\tpending.push( parser.assignTexture( materialParams, 'normalMap', materialDef.normalTexture ) );\n\n\t\t\tmaterialParams.normalScale = new THREE.Vector2( 1, 1 );\n\n\t\t\tif ( materialDef.normalTexture.scale !== undefined ) {\n\n\t\t\t\tmaterialParams.normalScale.set( materialDef.normalTexture.scale, materialDef.normalTexture.scale );\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( materialDef.occlusionTexture !== undefined && materialType !== THREE.MeshBasicMaterial ) {\n\n\t\t\tpending.push( parser.assignTexture( materialParams, 'aoMap', materialDef.occlusionTexture ) );\n\n\t\t\tif ( materialDef.occlusionTexture.strength !== undefined ) {\n\n\t\t\t\tmaterialParams.aoMapIntensity = materialDef.occlusionTexture.strength;\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( materialDef.emissiveFactor !== undefined && materialType !== THREE.MeshBasicMaterial ) {\n\n\t\t\tmaterialParams.emissive = new THREE.Color().fromArray( materialDef.emissiveFactor );\n\n\t\t}\n\n\t\tif ( materialDef.emissiveTexture !== undefined && materialType !== THREE.MeshBasicMaterial ) {\n\n\t\t\tpending.push( parser.assignTexture( materialParams, 'emissiveMap', materialDef.emissiveTexture ) );\n\n\t\t}\n\n\t\treturn Promise.all( pending ).then( function () {\n\n\t\t\tvar material;\n\n\t\t\tif ( materialType === THREE.ShaderMaterial ) {\n\n\t\t\t\tmaterial = extensions[ EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS ].createMaterial( materialParams );\n\n\t\t\t} else {\n\n\t\t\t\tmaterial = new materialType( materialParams );\n\n\t\t\t}\n\n\t\t\tif ( materialDef.name !== undefined ) material.name = materialDef.name;\n\n\t\t\t\u002F\u002F baseColorTexture, emissiveTexture, and specularGlossinessTexture use sRGB encoding.\n\t\t\tif ( material.map ) material.map.encoding = THREE.sRGBEncoding;\n\t\t\tif ( material.emissiveMap ) material.emissiveMap.encoding = THREE.sRGBEncoding;\n\t\t\tif ( material.specularMap ) material.specularMap.encoding = THREE.sRGBEncoding;\n\n\t\t\tassignExtrasToUserData( material, materialDef );\n\n\t\t\tif ( materialDef.extensions ) addUnknownExtensionsToUserData( extensions, material, materialDef );\n\n\t\t\treturn material;\n\n\t\t} );\n\n\t};\n\n\t\u002F**\n\t * @param {THREE.BufferGeometry} geometry\n\t * @param {GLTF.Primitive} primitiveDef\n\t * @param {GLTFParser} parser\n\t * @return {Promise\u003CTHREE.BufferGeometry\u003E}\n\t *\u002F\n\tfunction addPrimitiveAttributes( geometry, primitiveDef, parser ) {\n\n\t\tvar attributes = primitiveDef.attributes;\n\n\t\tvar pending = [];\n\n\t\tfunction assignAttributeAccessor( accessorIndex, attributeName ) {\n\n\t\t\treturn parser.getDependency( 'accessor', accessorIndex )\n\t\t\t\t.then( function ( accessor ) {\n\n\t\t\t\t\tgeometry.addAttribute( attributeName, accessor );\n\n\t\t\t\t} );\n\n\t\t}\n\n\t\tfor ( var gltfAttributeName in attributes ) {\n\n\t\t\tvar threeAttributeName = ATTRIBUTES[ gltfAttributeName ];\n\n\t\t\tif ( ! threeAttributeName ) continue;\n\n\t\t\t\u002F\u002F Skip attributes already provided by e.g. Draco extension.\n\t\t\tif ( threeAttributeName in geometry.attributes ) continue;\n\n\t\t\tpending.push( assignAttributeAccessor( attributes[ gltfAttributeName ], threeAttributeName ) );\n\n\t\t}\n\n\t\tif ( primitiveDef.indices !== undefined && ! geometry.index ) {\n\n\t\t\tvar accessor = parser.getDependency( 'accessor', primitiveDef.indices ).then( function ( accessor ) {\n\n\t\t\t\tgeometry.setIndex( accessor );\n\n\t\t\t} );\n\n\t\t\tpending.push( accessor );\n\n\t\t}\n\n\t\tassignExtrasToUserData( geometry, primitiveDef );\n\n\t\treturn Promise.all( pending ).then( function () {\n\n\t\t\treturn primitiveDef.targets !== undefined\n\t\t\t\t? addMorphTargets( geometry, primitiveDef.targets, parser )\n\t\t\t\t: geometry;\n\n\t\t} );\n\n\t}\n\n\t\u002F**\n\t * Specification: https:\u002F\u002Fgithub.com\u002FKhronosGroup\u002FglTF\u002Fblob\u002Fmaster\u002Fspecification\u002F2.0\u002FREADME.md#geometry\n\t *\n\t * Creates BufferGeometries from primitives.\n\t * If we can build a single BufferGeometry with .groups from multiple primitives, returns one BufferGeometry.\n\t * Otherwise, returns BufferGeometries without .groups as many as primitives.\n\t *\n\t * @param {Array\u003CGLTF.Primitive\u003E} primitives\n\t * @return {Promise\u003CArray\u003CTHREE.BufferGeometry\u003E\u003E}\n\t *\u002F\n\tGLTFParser.prototype.loadGeometries = function ( primitives ) {\n\n\t\tvar parser = this;\n\t\tvar extensions = this.extensions;\n\t\tvar cache = this.primitiveCache;\n\n\t\tvar isMultiPass = isMultiPassGeometry( primitives );\n\t\tvar originalPrimitives;\n\n\t\tif ( isMultiPass ) {\n\n\t\t\toriginalPrimitives = primitives; \u002F\u002F save original primitives and use later\n\n\t\t\t\u002F\u002F We build a single BufferGeometry with .groups from multiple primitives\n\t\t\t\u002F\u002F because all primitives share the same attributes\u002Fmorph\u002Fmode and have indices.\n\n\t\t\tprimitives = [ primitives[ 0 ] ];\n\n\t\t\t\u002F\u002F Sets .groups and combined indices to a geometry later in this method.\n\n\t\t}\n\n\t\tfunction createDracoPrimitive( primitive ) {\n\n\t\t\treturn extensions[ EXTENSIONS.KHR_DRACO_MESH_COMPRESSION ]\n\t\t\t\t.decodePrimitive( primitive, parser )\n\t\t\t\t.then( function ( geometry ) {\n\n\t\t\t\t\treturn addPrimitiveAttributes( geometry, primitive, parser );\n\n\t\t\t\t} );\n\n\t\t}\n\n\t\tvar pending = [];\n\n\t\tfor ( var i = 0, il = primitives.length; i \u003C il; i ++ ) {\n\n\t\t\tvar primitive = primitives[ i ];\n\t\t\tvar cacheKey = createPrimitiveKey( primitive );\n\n\t\t\t\u002F\u002F See if we've already created this geometry\n\t\t\tvar cached = cache[ cacheKey ];\n\n\t\t\tif ( cached ) {\n\n\t\t\t\t\u002F\u002F Use the cached geometry if it exists\n\t\t\t\tpending.push( cached.promise );\n\n\t\t\t} else {\n\n\t\t\t\tvar geometryPromise;\n\n\t\t\t\tif ( primitive.extensions && primitive.extensions[ EXTENSIONS.KHR_DRACO_MESH_COMPRESSION ] ) {\n\n\t\t\t\t\t\u002F\u002F Use DRACO geometry if available\n\t\t\t\t\tgeometryPromise = createDracoPrimitive( primitive );\n\n\t\t\t\t} else {\n\n\t\t\t\t\t\u002F\u002F Otherwise create a new geometry\n\t\t\t\t\tgeometryPromise = addPrimitiveAttributes( new THREE.BufferGeometry(), primitive, parser );\n\n\t\t\t\t}\n\n\t\t\t\t\u002F\u002F Cache this geometry\n\t\t\t\tcache[ cacheKey ] = { primitive: primitive, promise: geometryPromise };\n\n\t\t\t\tpending.push( geometryPromise );\n\n\t\t\t}\n\n\t\t}\n\n\t\treturn Promise.all( pending ).then( function ( geometries ) {\n\n\t\t\tif ( isMultiPass ) {\n\n\t\t\t\tvar baseGeometry = geometries[ 0 ];\n\n\t\t\t\t\u002F\u002F See if we've already created this combined geometry\n\t\t\t\tvar cache = parser.multiPassGeometryCache;\n\t\t\t\tvar cacheKey = createMultiPassGeometryKey( baseGeometry, originalPrimitives );\n\t\t\t\tvar cached = cache[ cacheKey ];\n\n\t\t\t\tif ( cached !== null ) return [ cached.geometry ];\n\n\t\t\t\t\u002F\u002F Cloning geometry because of index override.\n\t\t\t\t\u002F\u002F Attributes can be reused so cloning by myself here.\n\t\t\t\tvar geometry = new THREE.BufferGeometry();\n\n\t\t\t\tgeometry.name = baseGeometry.name;\n\t\t\t\tgeometry.userData = baseGeometry.userData;\n\n\t\t\t\tfor ( var key in baseGeometry.attributes ) geometry.addAttribute( key, baseGeometry.attributes[ key ] );\n\t\t\t\tfor ( var key in baseGeometry.morphAttributes ) geometry.morphAttributes[ key ] = baseGeometry.morphAttributes[ key ];\n\n\t\t\t\tvar pendingIndices = [];\n\n\t\t\t\tfor ( var i = 0, il = originalPrimitives.length; i \u003C il; i ++ ) {\n\n\t\t\t\t\tpendingIndices.push( parser.getDependency( 'accessor', originalPrimitives[ i ].indices ) );\n\n\t\t\t\t}\n\n\t\t\t\treturn Promise.all( pendingIndices ).then( function ( accessors ) {\n\n\t\t\t\t\tvar indices = [];\n\t\t\t\t\tvar offset = 0;\n\n\t\t\t\t\tfor ( var i = 0, il = originalPrimitives.length; i \u003C il; i ++ ) {\n\n\t\t\t\t\t\tvar accessor = accessors[ i ];\n\n\t\t\t\t\t\tfor ( var j = 0, jl = accessor.count; j \u003C jl; j ++ ) indices.push( accessor.array[ j ] );\n\n\t\t\t\t\t\tgeometry.addGroup( offset, accessor.count, i );\n\n\t\t\t\t\t\toffset += accessor.count;\n\n\t\t\t\t\t}\n\n\t\t\t\t\tgeometry.setIndex( indices );\n\n\t\t\t\t\tcache[ cacheKey ] = { geometry: geometry, baseGeometry: baseGeometry, primitives: originalPrimitives };\n\n\t\t\t\t\treturn [ geometry ];\n\n\t\t\t\t} );\n\n\t\t\t} else if ( geometries.length \u003E 1 && THREE.BufferGeometryUtils !== undefined ) {\n\n\t\t\t\t\u002F\u002F Tries to merge geometries with BufferGeometryUtils if possible\n\n\t\t\t\tfor ( var i = 1, il = primitives.length; i \u003C il; i ++ ) {\n\n\t\t\t\t\t\u002F\u002F can't merge if draw mode is different\n\t\t\t\t\tif ( primitives[ 0 ].mode !== primitives[ i ].mode ) return geometries;\n\n\t\t\t\t}\n\n\t\t\t\t\u002F\u002F See if we've already created this combined geometry\n\t\t\t\tvar cache = parser.multiplePrimitivesCache;\n\t\t\t\tvar cacheKey = createArrayKeyBufferGeometry( geometries );\n\t\t\t\tvar cached = cache[ cacheKey ];\n\n\t\t\t\tif ( cached ) {\n\n\t\t\t\t\tif ( cached.geometry !== null ) return [ cached.geometry ];\n\n\t\t\t\t} else {\n\n\t\t\t\t\tvar geometry = THREE.BufferGeometryUtils.mergeBufferGeometries( geometries, true );\n\n\t\t\t\t\tcache[ cacheKey ] = { geometry: geometry, baseGeometries: geometries };\n\n\t\t\t\t\tif ( geometry !== null ) return [ geometry ];\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn geometries;\n\n\t\t} );\n\n\t};\n\n\t\u002F**\n\t * Specification: https:\u002F\u002Fgithub.com\u002FKhronosGroup\u002FglTF\u002Fblob\u002Fmaster\u002Fspecification\u002F2.0\u002FREADME.md#meshes\n\t * @param {number} meshIndex\n\t * @return {Promise\u003CTHREE.Group|THREE.Mesh|THREE.SkinnedMesh\u003E}\n\t *\u002F\n\tGLTFParser.prototype.loadMesh = function ( meshIndex ) {\n\n\t\tvar parser = this;\n\t\tvar json = this.json;\n\t\tvar extensions = this.extensions;\n\n\t\tvar meshDef = json.meshes[ meshIndex ];\n\t\tvar primitives = meshDef.primitives;\n\n\t\tvar pending = [];\n\n\t\tfor ( var i = 0, il = primitives.length; i \u003C il; i ++ ) {\n\n\t\t\tvar material = primitives[ i ].material === undefined\n\t\t\t\t? createDefaultMaterial()\n\t\t\t\t: this.getDependency( 'material', primitives[ i ].material );\n\n\t\t\tpending.push( material );\n\n\t\t}\n\n\t\treturn Promise.all( pending ).then( function ( originalMaterials ) {\n\n\t\t\treturn parser.loadGeometries( primitives ).then( function ( geometries ) {\n\n\t\t\t\tvar isMultiMaterial = geometries.length === 1 && geometries[ 0 ].groups.length \u003E 0;\n\n\t\t\t\tvar meshes = [];\n\n\t\t\t\tfor ( var i = 0, il = geometries.length; i \u003C il; i ++ ) {\n\n\t\t\t\t\tvar geometry = geometries[ i ];\n\t\t\t\t\tvar primitive = primitives[ i ];\n\n\t\t\t\t\t\u002F\u002F 1. create Mesh\n\n\t\t\t\t\tvar mesh;\n\n\t\t\t\t\tvar material = isMultiMaterial ? originalMaterials : originalMaterials[ i ];\n\n\t\t\t\t\tif ( primitive.mode === WEBGL_CONSTANTS.TRIANGLES ||\n\t\t\t\t\t\tprimitive.mode === WEBGL_CONSTANTS.TRIANGLE_STRIP ||\n\t\t\t\t\t\tprimitive.mode === WEBGL_CONSTANTS.TRIANGLE_FAN ||\n\t\t\t\t\t\tprimitive.mode === undefined ) {\n\n\t\t\t\t\t\t\u002F\u002F .isSkinnedMesh isn't in glTF spec. See .markDefs()\n\t\t\t\t\t\tmesh = meshDef.isSkinnedMesh === true\n\t\t\t\t\t\t\t? new THREE.SkinnedMesh( geometry, material )\n\t\t\t\t\t\t\t: new THREE.Mesh( geometry, material );\n\n\t\t\t\t\t\tif ( mesh.isSkinnedMesh === true ) mesh.normalizeSkinWeights(); \u002F\u002F #15319\n\n\t\t\t\t\t\tif ( primitive.mode === WEBGL_CONSTANTS.TRIANGLE_STRIP ) {\n\n\t\t\t\t\t\t\tmesh.drawMode = THREE.TriangleStripDrawMode;\n\n\t\t\t\t\t\t} else if ( primitive.mode === WEBGL_CONSTANTS.TRIANGLE_FAN ) {\n\n\t\t\t\t\t\t\tmesh.drawMode = THREE.TriangleFanDrawMode;\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else if ( primitive.mode === WEBGL_CONSTANTS.LINES ) {\n\n\t\t\t\t\t\tmesh = new THREE.LineSegments( geometry, material );\n\n\t\t\t\t\t} else if ( primitive.mode === WEBGL_CONSTANTS.LINE_STRIP ) {\n\n\t\t\t\t\t\tmesh = new THREE.Line( geometry, material );\n\n\t\t\t\t\t} else if ( primitive.mode === WEBGL_CONSTANTS.LINE_LOOP ) {\n\n\t\t\t\t\t\tmesh = new THREE.LineLoop( geometry, material );\n\n\t\t\t\t\t} else if ( primitive.mode === WEBGL_CONSTANTS.POINTS ) {\n\n\t\t\t\t\t\tmesh = new THREE.Points( geometry, material );\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\tthrow new Error( 'THREE.GLTFLoader: Primitive mode unsupported: ' + primitive.mode );\n\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( Object.keys( mesh.geometry.morphAttributes ).length \u003E 0 ) {\n\n\t\t\t\t\t\tupdateMorphTargets( mesh, meshDef );\n\n\t\t\t\t\t}\n\n\t\t\t\t\tmesh.name = meshDef.name || ( 'mesh_' + meshIndex );\n\n\t\t\t\t\tif ( geometries.length \u003E 1 ) mesh.name += '_' + i;\n\n\t\t\t\t\tassignExtrasToUserData( mesh, meshDef );\n\n\t\t\t\t\tmeshes.push( mesh );\n\n\t\t\t\t\t\u002F\u002F 2. update Material depending on Mesh and BufferGeometry\n\n\t\t\t\t\tvar materials = isMultiMaterial ? mesh.material : [ mesh.material ];\n\n\t\t\t\t\tvar useVertexTangents = geometry.attributes.tangent !== undefined;\n\t\t\t\t\tvar useVertexColors = geometry.attributes.color !== undefined;\n\t\t\t\t\tvar useFlatShading = geometry.attributes.normal === undefined;\n\t\t\t\t\tvar useSkinning = mesh.isSkinnedMesh === true;\n\t\t\t\t\tvar useMorphTargets = Object.keys( geometry.morphAttributes ).length \u003E 0;\n\t\t\t\t\tvar useMorphNormals = useMorphTargets && geometry.morphAttributes.normal !== undefined;\n\n\t\t\t\t\tfor ( var j = 0, jl = materials.length; j \u003C jl; j ++ ) {\n\n\t\t\t\t\t\tvar material = materials[ j ];\n\n\t\t\t\t\t\tif ( mesh.isPoints ) {\n\n\t\t\t\t\t\t\tvar cacheKey = 'PointsMaterial:' + material.uuid;\n\n\t\t\t\t\t\t\tvar pointsMaterial = parser.cache.get( cacheKey );\n\n\t\t\t\t\t\t\tif ( ! pointsMaterial ) {\n\n\t\t\t\t\t\t\t\tpointsMaterial = new THREE.PointsMaterial();\n\t\t\t\t\t\t\t\tTHREE.Material.prototype.copy.call( pointsMaterial, material );\n\t\t\t\t\t\t\t\tpointsMaterial.color.copy( material.color );\n\t\t\t\t\t\t\t\tpointsMaterial.map = material.map;\n\t\t\t\t\t\t\t\tpointsMaterial.lights = false; \u002F\u002F PointsMaterial doesn't support lights yet\n\n\t\t\t\t\t\t\t\tparser.cache.add( cacheKey, pointsMaterial );\n\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tmaterial = pointsMaterial;\n\n\t\t\t\t\t\t} else if ( mesh.isLine ) {\n\n\t\t\t\t\t\t\tvar cacheKey = 'LineBasicMaterial:' + material.uuid;\n\n\t\t\t\t\t\t\tvar lineMaterial = parser.cache.get( cacheKey );\n\n\t\t\t\t\t\t\tif ( ! lineMaterial ) {\n\n\t\t\t\t\t\t\t\tlineMaterial = new THREE.LineBasicMaterial();\n\t\t\t\t\t\t\t\tTHREE.Material.prototype.copy.call( lineMaterial, material );\n\t\t\t\t\t\t\t\tlineMaterial.color.copy( material.color );\n\t\t\t\t\t\t\t\tlineMaterial.lights = false; \u002F\u002F LineBasicMaterial doesn't support lights yet\n\n\t\t\t\t\t\t\t\tparser.cache.add( cacheKey, lineMaterial );\n\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tmaterial = lineMaterial;\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\u002F\u002F Clone the material if it will be modified\n\t\t\t\t\t\tif ( useVertexTangents || useVertexColors || useFlatShading || useSkinning || useMorphTargets ) {\n\n\t\t\t\t\t\t\tvar cacheKey = 'ClonedMaterial:' + material.uuid + ':';\n\n\t\t\t\t\t\t\tif ( material.isGLTFSpecularGlossinessMaterial ) cacheKey += 'specular-glossiness:';\n\t\t\t\t\t\t\tif ( useSkinning ) cacheKey += 'skinning:';\n\t\t\t\t\t\t\tif ( useVertexTangents ) cacheKey += 'vertex-tangents:';\n\t\t\t\t\t\t\tif ( useVertexColors ) cacheKey += 'vertex-colors:';\n\t\t\t\t\t\t\tif ( useFlatShading ) cacheKey += 'flat-shading:';\n\t\t\t\t\t\t\tif ( useMorphTargets ) cacheKey += 'morph-targets:';\n\t\t\t\t\t\t\tif ( useMorphNormals ) cacheKey += 'morph-normals:';\n\n\t\t\t\t\t\t\tvar cachedMaterial = parser.cache.get( cacheKey );\n\n\t\t\t\t\t\t\tif ( ! cachedMaterial ) {\n\n\t\t\t\t\t\t\t\tcachedMaterial = material.isGLTFSpecularGlossinessMaterial\n\t\t\t\t\t\t\t\t\t? extensions[ EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS ].cloneMaterial( material )\n\t\t\t\t\t\t\t\t\t: material.clone();\n\n\t\t\t\t\t\t\t\tif ( useSkinning ) cachedMaterial.skinning = true;\n\t\t\t\t\t\t\t\tif ( useVertexTangents ) cachedMaterial.vertexTangents = true;\n\t\t\t\t\t\t\t\tif ( useVertexColors ) cachedMaterial.vertexColors = THREE.VertexColors;\n\t\t\t\t\t\t\t\tif ( useFlatShading ) cachedMaterial.flatShading = true;\n\t\t\t\t\t\t\t\tif ( useMorphTargets ) cachedMaterial.morphTargets = true;\n\t\t\t\t\t\t\t\tif ( useMorphNormals ) cachedMaterial.morphNormals = true;\n\n\t\t\t\t\t\t\t\tparser.cache.add( cacheKey, cachedMaterial );\n\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tmaterial = cachedMaterial;\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tmaterials[ j ] = material;\n\n\t\t\t\t\t\t\u002F\u002F workarounds for mesh and geometry\n\n\t\t\t\t\t\tif ( material.aoMap && geometry.attributes.uv2 === undefined && geometry.attributes.uv !== undefined ) {\n\n\t\t\t\t\t\t\tconsole.log( 'THREE.GLTFLoader: Duplicating UVs to support aoMap.' );\n\t\t\t\t\t\t\tgeometry.addAttribute( 'uv2', new THREE.BufferAttribute( geometry.attributes.uv.array, 2 ) );\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif ( material.isGLTFSpecularGlossinessMaterial ) {\n\n\t\t\t\t\t\t\t\u002F\u002F for GLTFSpecularGlossinessMaterial(ShaderMaterial) uniforms runtime update\n\t\t\t\t\t\t\tmesh.onBeforeRender = extensions[ EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS ].refreshUniforms;\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t\tmesh.material = isMultiMaterial ? materials : materials[ 0 ];\n\n\t\t\t\t}\n\n\t\t\t\tif ( meshes.length === 1 ) {\n\n\t\t\t\t\treturn meshes[ 0 ];\n\n\t\t\t\t}\n\n\t\t\t\tvar group = new THREE.Group();\n\n\t\t\t\tfor ( var i = 0, il = meshes.length; i \u003C il; i ++ ) {\n\n\t\t\t\t\tgroup.add( meshes[ i ] );\n\n\t\t\t\t}\n\n\t\t\t\treturn group;\n\n\t\t\t} );\n\n\t\t} );\n\n\t};\n\n\t\u002F**\n\t * Specification: https:\u002F\u002Fgithub.com\u002FKhronosGroup\u002FglTF\u002Ftree\u002Fmaster\u002Fspecification\u002F2.0#cameras\n\t * @param {number} cameraIndex\n\t * @return {Promise\u003CTHREE.Camera\u003E}\n\t *\u002F\n\tGLTFParser.prototype.loadCamera = function ( cameraIndex ) {\n\n\t\tvar camera;\n\t\tvar cameraDef = this.json.cameras[ cameraIndex ];\n\t\tvar params = cameraDef[ cameraDef.type ];\n\n\t\tif ( ! params ) {\n\n\t\t\tconsole.warn( 'THREE.GLTFLoader: Missing camera parameters.' );\n\t\t\treturn;\n\n\t\t}\n\n\t\tif ( cameraDef.type === 'perspective' ) {\n\n\t\t\tcamera = new THREE.PerspectiveCamera( THREE.Math.radToDeg( params.yfov ), params.aspectRatio || 1, params.znear || 1, params.zfar || 2e6 );\n\n\t\t} else if ( cameraDef.type === 'orthographic' ) {\n\n\t\t\tcamera = new THREE.OrthographicCamera( params.xmag \u002F - 2, params.xmag \u002F 2, params.ymag \u002F 2, params.ymag \u002F - 2, params.znear, params.zfar );\n\n\t\t}\n\n\t\tif ( cameraDef.name !== undefined ) camera.name = cameraDef.name;\n\n\t\tassignExtrasToUserData( camera, cameraDef );\n\n\t\treturn Promise.resolve( camera );\n\n\t};\n\n\t\u002F**\n\t * Specification: https:\u002F\u002Fgithub.com\u002FKhronosGroup\u002FglTF\u002Ftree\u002Fmaster\u002Fspecification\u002F2.0#skins\n\t * @param {number} skinIndex\n\t * @return {Promise\u003CObject\u003E}\n\t *\u002F\n\tGLTFParser.prototype.loadSkin = function ( skinIndex ) {\n\n\t\tvar skinDef = this.json.skins[ skinIndex ];\n\n\t\tvar skinEntry = { joints: skinDef.joints };\n\n\t\tif ( skinDef.inverseBindMatrices === undefined ) {\n\n\t\t\treturn Promise.resolve( skinEntry );\n\n\t\t}\n\n\t\treturn this.getDependency( 'accessor', skinDef.inverseBindMatrices ).then( function ( accessor ) {\n\n\t\t\tskinEntry.inverseBindMatrices = accessor;\n\n\t\t\treturn skinEntry;\n\n\t\t} );\n\n\t};\n\n\t\u002F**\n\t * Specification: https:\u002F\u002Fgithub.com\u002FKhronosGroup\u002FglTF\u002Ftree\u002Fmaster\u002Fspecification\u002F2.0#animations\n\t * @param {number} animationIndex\n\t * @return {Promise\u003CTHREE.AnimationClip\u003E}\n\t *\u002F\n\tGLTFParser.prototype.loadAnimation = function ( animationIndex ) {\n\n\t\tvar json = this.json;\n\n\t\tvar animationDef = json.animations[ animationIndex ];\n\n\t\tvar pendingNodes = [];\n\t\tvar pendingInputAccessors = [];\n\t\tvar pendingOutputAccessors = [];\n\t\tvar pendingSamplers = [];\n\t\tvar pendingTargets = [];\n\n\t\tfor ( var i = 0, il = animationDef.channels.length; i \u003C il; i ++ ) {\n\n\t\t\tvar channel = animationDef.channels[ i ];\n\t\t\tvar sampler = animationDef.samplers[ channel.sampler ];\n\t\t\tvar target = channel.target;\n\t\t\tvar name = target.node !== undefined ? target.node : target.id; \u002F\u002F NOTE: target.id is deprecated.\n\t\t\tvar input = animationDef.parameters !== undefined ? animationDef.parameters[ sampler.input ] : sampler.input;\n\t\t\tvar output = animationDef.parameters !== undefined ? animationDef.parameters[ sampler.output ] : sampler.output;\n\n\t\t\tpendingNodes.push( this.getDependency( 'node', name ) );\n\t\t\tpendingInputAccessors.push( this.getDependency( 'accessor', input ) );\n\t\t\tpendingOutputAccessors.push( this.getDependency( 'accessor', output ) );\n\t\t\tpendingSamplers.push( sampler );\n\t\t\tpendingTargets.push( target );\n\n\t\t}\n\n\t\treturn Promise.all( [\n\n\t\t\tPromise.all( pendingNodes ),\n\t\t\tPromise.all( pendingInputAccessors ),\n\t\t\tPromise.all( pendingOutputAccessors ),\n\t\t\tPromise.all( pendingSamplers ),\n\t\t\tPromise.all( pendingTargets )\n\n\t\t] ).then( function ( dependencies ) {\n\n\t\t\tvar nodes = dependencies[ 0 ];\n\t\t\tvar inputAccessors = dependencies[ 1 ];\n\t\t\tvar outputAccessors = dependencies[ 2 ];\n\t\t\tvar samplers = dependencies[ 3 ];\n\t\t\tvar targets = dependencies[ 4 ];\n\n\t\t\tvar tracks = [];\n\n\t\t\tfor ( var i = 0, il = nodes.length; i \u003C il; i ++ ) {\n\n\t\t\t\tvar node = nodes[ i ];\n\t\t\t\tvar inputAccessor = inputAccessors[ i ];\n\t\t\t\tvar outputAccessor = outputAccessors[ i ];\n\t\t\t\tvar sampler = samplers[ i ];\n\t\t\t\tvar target = targets[ i ];\n\n\t\t\t\tif ( node === undefined ) continue;\n\n\t\t\t\tnode.updateMatrix();\n\t\t\t\tnode.matrixAutoUpdate = true;\n\n\t\t\t\tvar TypedKeyframeTrack;\n\n\t\t\t\tswitch ( PATH_PROPERTIES[ target.path ] ) {\n\n\t\t\t\t\tcase PATH_PROPERTIES.weights:\n\n\t\t\t\t\t\tTypedKeyframeTrack = THREE.NumberKeyframeTrack;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase PATH_PROPERTIES.rotation:\n\n\t\t\t\t\t\tTypedKeyframeTrack = THREE.QuaternionKeyframeTrack;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase PATH_PROPERTIES.position:\n\t\t\t\t\tcase PATH_PROPERTIES.scale:\n\t\t\t\t\tdefault:\n\n\t\t\t\t\t\tTypedKeyframeTrack = THREE.VectorKeyframeTrack;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t\tvar targetName = node.name ? node.name : node.uuid;\n\n\t\t\t\tvar interpolation = sampler.interpolation !== undefined ? INTERPOLATION[ sampler.interpolation ] : THREE.InterpolateLinear;\n\n\t\t\t\tvar targetNames = [];\n\n\t\t\t\tif ( PATH_PROPERTIES[ target.path ] === PATH_PROPERTIES.weights ) {\n\n\t\t\t\t\t\u002F\u002F node can be THREE.Group here but\n\t\t\t\t\t\u002F\u002F PATH_PROPERTIES.weights(morphTargetInfluences) should be\n\t\t\t\t\t\u002F\u002F the property of a mesh object under group.\n\n\t\t\t\t\tnode.traverse( function ( object ) {\n\n\t\t\t\t\t\tif ( object.isMesh === true && object.morphTargetInfluences ) {\n\n\t\t\t\t\t\t\ttargetNames.push( object.name ? object.name : object.uuid );\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} );\n\n\t\t\t\t} else {\n\n\t\t\t\t\ttargetNames.push( targetName );\n\n\t\t\t\t}\n\n\t\t\t\t\u002F\u002F KeyframeTrack.optimize() will modify given 'times' and 'values'\n\t\t\t\t\u002F\u002F buffers before creating a truncated copy to keep. Because buffers may\n\t\t\t\t\u002F\u002F be reused by other tracks, make copies here.\n\t\t\t\tfor ( var j = 0, jl = targetNames.length; j \u003C jl; j ++ ) {\n\n\t\t\t\t\tvar track = new TypedKeyframeTrack(\n\t\t\t\t\t\ttargetNames[ j ] + '.' + PATH_PROPERTIES[ target.path ],\n\t\t\t\t\t\tTHREE.AnimationUtils.arraySlice( inputAccessor.array, 0 ),\n\t\t\t\t\t\tTHREE.AnimationUtils.arraySlice( outputAccessor.array, 0 ),\n\t\t\t\t\t\tinterpolation\n\t\t\t\t\t);\n\n\t\t\t\t\t\u002F\u002F Here is the trick to enable custom interpolation.\n\t\t\t\t\t\u002F\u002F Overrides .createInterpolant in a factory method which creates custom interpolation.\n\t\t\t\t\tif ( sampler.interpolation === 'CUBICSPLINE' ) {\n\n\t\t\t\t\t\ttrack.createInterpolant = function InterpolantFactoryMethodGLTFCubicSpline( result ) {\n\n\t\t\t\t\t\t\t\u002F\u002F A CUBICSPLINE keyframe in glTF has three output values for each input value,\n\t\t\t\t\t\t\t\u002F\u002F representing inTangent, splineVertex, and outTangent. As a result, track.getValueSize()\n\t\t\t\t\t\t\t\u002F\u002F must be divided by three to get the interpolant's sampleSize argument.\n\n\t\t\t\t\t\t\treturn new GLTFCubicSplineInterpolant( this.times, this.values, this.getValueSize() \u002F 3, result );\n\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\u002F\u002F Workaround, provide an alternate way to know if the interpolant type is cubis spline to track.\n\t\t\t\t\t\t\u002F\u002F track.getInterpolation() doesn't return valid value for custom interpolant.\n\t\t\t\t\t\ttrack.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline = true;\n\n\t\t\t\t\t}\n\n\t\t\t\t\ttracks.push( track );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tvar name = animationDef.name !== undefined ? animationDef.name : 'animation_' + animationIndex;\n\n\t\t\treturn new THREE.AnimationClip( name, undefined, tracks );\n\n\t\t} );\n\n\t};\n\n\t\u002F**\n\t * Specification: https:\u002F\u002Fgithub.com\u002FKhronosGroup\u002FglTF\u002Ftree\u002Fmaster\u002Fspecification\u002F2.0#nodes-and-hierarchy\n\t * @param {number} nodeIndex\n\t * @return {Promise\u003CTHREE.Object3D\u003E}\n\t *\u002F\n\tGLTFParser.prototype.loadNode = function ( nodeIndex ) {\n\n\t\tvar json = this.json;\n\t\tvar extensions = this.extensions;\n\t\tvar parser = this;\n\n\t\tvar meshReferences = json.meshReferences;\n\t\tvar meshUses = json.meshUses;\n\n\t\tvar nodeDef = json.nodes[ nodeIndex ];\n\n\t\treturn ( function () {\n\n\t\t\t\u002F\u002F .isBone isn't in glTF spec. See .markDefs\n\t\t\tif ( nodeDef.isBone === true ) {\n\n\t\t\t\treturn Promise.resolve( new THREE.Bone() );\n\n\t\t\t} else if ( nodeDef.mesh !== undefined ) {\n\n\t\t\t\treturn parser.getDependency( 'mesh', nodeDef.mesh ).then( function ( mesh ) {\n\n\t\t\t\t\tvar node;\n\n\t\t\t\t\tif ( meshReferences[ nodeDef.mesh ] \u003E 1 ) {\n\n\t\t\t\t\t\tvar instanceNum = meshUses[ nodeDef.mesh ] ++;\n\n\t\t\t\t\t\tnode = mesh.clone();\n\t\t\t\t\t\tnode.name += '_instance_' + instanceNum;\n\n\t\t\t\t\t\t\u002F\u002F onBeforeRender copy for Specular-Glossiness\n\t\t\t\t\t\tnode.onBeforeRender = mesh.onBeforeRender;\n\n\t\t\t\t\t\tfor ( var i = 0, il = node.children.length; i \u003C il; i ++ ) {\n\n\t\t\t\t\t\t\tnode.children[ i ].name += '_instance_' + instanceNum;\n\t\t\t\t\t\t\tnode.children[ i ].onBeforeRender = mesh.children[ i ].onBeforeRender;\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\tnode = mesh;\n\n\t\t\t\t\t}\n\n\t\t\t\t\t\u002F\u002F if weights are provided on the node, override weights on the mesh.\n\t\t\t\t\tif ( nodeDef.weights !== undefined ) {\n\n\t\t\t\t\t\tnode.traverse( function ( o ) {\n\n\t\t\t\t\t\t\tif ( ! o.isMesh ) return;\n\n\t\t\t\t\t\t\tfor ( var i = 0, il = nodeDef.weights.length; i \u003C il; i ++ ) {\n\n\t\t\t\t\t\t\t\to.morphTargetInfluences[ i ] = nodeDef.weights[ i ];\n\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t} );\n\n\t\t\t\t\t}\n\n\t\t\t\t\treturn node;\n\n\t\t\t\t} );\n\n\t\t\t} else if ( nodeDef.camera !== undefined ) {\n\n\t\t\t\treturn parser.getDependency( 'camera', nodeDef.camera );\n\n\t\t\t} else if ( nodeDef.extensions\n\t\t\t\t&& nodeDef.extensions[ EXTENSIONS.KHR_LIGHTS_PUNCTUAL ]\n\t\t\t\t&& nodeDef.extensions[ EXTENSIONS.KHR_LIGHTS_PUNCTUAL ].light !== undefined ) {\n\n\t\t\t\treturn parser.getDependency( 'light', nodeDef.extensions[ EXTENSIONS.KHR_LIGHTS_PUNCTUAL ].light );\n\n\t\t\t} else {\n\n\t\t\t\treturn Promise.resolve( new THREE.Object3D() );\n\n\t\t\t}\n\n\t\t}() ).then( function ( node ) {\n\n\t\t\tif ( nodeDef.name !== undefined ) {\n\n\t\t\t\tnode.name = THREE.PropertyBinding.sanitizeNodeName( nodeDef.name );\n\n\t\t\t}\n\n\t\t\tassignExtrasToUserData( node, nodeDef );\n\n\t\t\tif ( nodeDef.extensions ) addUnknownExtensionsToUserData( extensions, node, nodeDef );\n\n\t\t\tif ( nodeDef.matrix !== undefined ) {\n\n\t\t\t\tvar matrix = new THREE.Matrix4();\n\t\t\t\tmatrix.fromArray( nodeDef.matrix );\n\t\t\t\tnode.applyMatrix( matrix );\n\n\t\t\t} else {\n\n\t\t\t\tif ( nodeDef.translation !== undefined ) {\n\n\t\t\t\t\tnode.position.fromArray( nodeDef.translation );\n\n\t\t\t\t}\n\n\t\t\t\tif ( nodeDef.rotation !== undefined ) {\n\n\t\t\t\t\tnode.quaternion.fromArray( nodeDef.rotation );\n\n\t\t\t\t}\n\n\t\t\t\tif ( nodeDef.scale !== undefined ) {\n\n\t\t\t\t\tnode.scale.fromArray( nodeDef.scale );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn node;\n\n\t\t} );\n\n\t};\n\n\t\u002F**\n\t * Specification: https:\u002F\u002Fgithub.com\u002FKhronosGroup\u002FglTF\u002Ftree\u002Fmaster\u002Fspecification\u002F2.0#scenes\n\t * @param {number} sceneIndex\n\t * @return {Promise\u003CTHREE.Scene\u003E}\n\t *\u002F\n\tGLTFParser.prototype.loadScene = function () {\n\n\t\t\u002F\u002F scene node hierachy builder\n\n\t\tfunction buildNodeHierachy( nodeId, parentObject, json, parser ) {\n\n\t\t\tvar nodeDef = json.nodes[ nodeId ];\n\n\t\t\treturn parser.getDependency( 'node', nodeId ).then( function ( node ) {\n\n\t\t\t\tif ( nodeDef.skin === undefined ) return node;\n\n\t\t\t\t\u002F\u002F build skeleton here as well\n\n\t\t\t\tvar skinEntry;\n\n\t\t\t\treturn parser.getDependency( 'skin', nodeDef.skin ).then( function ( skin ) {\n\n\t\t\t\t\tskinEntry = skin;\n\n\t\t\t\t\tvar pendingJoints = [];\n\n\t\t\t\t\tfor ( var i = 0, il = skinEntry.joints.length; i \u003C il; i ++ ) {\n\n\t\t\t\t\t\tpendingJoints.push( parser.getDependency( 'node', skinEntry.joints[ i ] ) );\n\n\t\t\t\t\t}\n\n\t\t\t\t\treturn Promise.all( pendingJoints );\n\n\t\t\t\t} ).then( function ( jointNodes ) {\n\n\t\t\t\t\tvar meshes = node.isGroup === true ? node.children : [ node ];\n\n\t\t\t\t\tfor ( var i = 0, il = meshes.length; i \u003C il; i ++ ) {\n\n\t\t\t\t\t\tvar mesh = meshes[ i ];\n\n\t\t\t\t\t\tvar bones = [];\n\t\t\t\t\t\tvar boneInverses = [];\n\n\t\t\t\t\t\tfor ( var j = 0, jl = jointNodes.length; j \u003C jl; j ++ ) {\n\n\t\t\t\t\t\t\tvar jointNode = jointNodes[ j ];\n\n\t\t\t\t\t\t\tif ( jointNode ) {\n\n\t\t\t\t\t\t\t\tbones.push( jointNode );\n\n\t\t\t\t\t\t\t\tvar mat = new THREE.Matrix4();\n\n\t\t\t\t\t\t\t\tif ( skinEntry.inverseBindMatrices !== undefined ) {\n\n\t\t\t\t\t\t\t\t\tmat.fromArray( skinEntry.inverseBindMatrices.array, j * 16 );\n\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tboneInverses.push( mat );\n\n\t\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t\tconsole.warn( 'THREE.GLTFLoader: Joint \"%s\" could not be found.', skinEntry.joints[ j ] );\n\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tmesh.bind( new THREE.Skeleton( bones, boneInverses ), mesh.matrixWorld );\n\n\t\t\t\t\t}\n\n\t\t\t\t\treturn node;\n\n\t\t\t\t} );\n\n\t\t\t} ).then( function ( node ) {\n\n\t\t\t\t\u002F\u002F build node hierachy\n\n\t\t\t\tparentObject.add( node );\n\n\t\t\t\tvar pending = [];\n\n\t\t\t\tif ( nodeDef.children ) {\n\n\t\t\t\t\tvar children = nodeDef.children;\n\n\t\t\t\t\tfor ( var i = 0, il = children.length; i \u003C il; i ++ ) {\n\n\t\t\t\t\t\tvar child = children[ i ];\n\t\t\t\t\t\tpending.push( buildNodeHierachy( child, node, json, parser ) );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\treturn Promise.all( pending );\n\n\t\t\t} );\n\n\t\t}\n\n\t\treturn function loadScene( sceneIndex ) {\n\n\t\t\tvar json = this.json;\n\t\t\tvar extensions = this.extensions;\n\t\t\tvar sceneDef = this.json.scenes[ sceneIndex ];\n\t\t\tvar parser = this;\n\n\t\t\tvar scene = new THREE.Scene();\n\t\t\tif ( sceneDef.name !== undefined ) scene.name = sceneDef.name;\n\n\t\t\tassignExtrasToUserData( scene, sceneDef );\n\n\t\t\tif ( sceneDef.extensions ) addUnknownExtensionsToUserData( extensions, scene, sceneDef );\n\n\t\t\tvar nodeIds = sceneDef.nodes || [];\n\n\t\t\tvar pending = [];\n\n\t\t\tfor ( var i = 0, il = nodeIds.length; i \u003C il; i ++ ) {\n\n\t\t\t\tpending.push( buildNodeHierachy( nodeIds[ i ], scene, json, parser ) );\n\n\t\t\t}\n\n\t\t\treturn Promise.all( pending ).then( function () {\n\n\t\t\t\treturn scene;\n\n\t\t\t} );\n\n\t\t};\n\n\t}();\n\n\treturn GLTFLoader;\n\n} )();\n","directory_shortid":"BJzTbcoD-P","id":"6cce52f7-4457-4ea8-b2e0-63f12692d9e7","inserted_at":"2020-08-05T03:39:49","is_binary":false,"shortid":"BJ6Tb9ovWw","source_id":"3985691b-c62a-4f15-b163-88a57fd46675","title":"GLTFLoader.js","updated_at":"2020-08-05T03:39:49","upload_id":null},{"code":"body {\n margin: 0px;\n overflow: hidden;\n color: white;\n text-align: center;\n}\n\nh1 {\n position: absolute;\n width: 100%;\n z-index: 1;\n font-size: 1.5rem;\n}\n\na {\n color: white;\n}\na:hover{\n color: purple;\n}\n\n#scene-container {\n position: absolute;\n width: 100%;\n height: 100%;\n}","directory_shortid":"H17ab9iPbw","id":"161d26c9-b5ca-4770-92f4-2ff94fed4e27","inserted_at":"2020-08-05T03:39:49","is_binary":false,"shortid":"SyhpZciwWP","source_id":"3985691b-c62a-4f15-b163-88a57fd46675","title":"main.css","updated_at":"2020-08-05T03:39:49","upload_id":null},{"code":"{\n \"template\": \"static\",\n \"infiniteLoopProtection\": false\n}","directory_shortid":null,"id":"0d752036-c3fb-4e33-82c9-fff512965817","inserted_at":"2020-08-05T03:39:49","is_binary":false,"shortid":"rysabcoDZw","source_id":"3985691b-c62a-4f15-b163-88a57fd46675","title":"sandbox.config.json","updated_at":"2020-08-05T03:39:49","upload_id":null},{"code":"{\n \"name\": \"discoverthreejs-com-ch-1-7-load-models\",\n \"version\": \"1.1.0\",\n \"description\": \"Final code from Ch 1.7 of Discover three.js\",\n \"main\": \"index.html\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https:\u002F\u002Fgithub.com\u002Flooeee\u002Fdiscoverthree.com-examples.git\"\n },\n \"keywords\": [\n \"three.js\",\n \"web\",\n \"animation\",\n \"javascript\",\n \"examples\",\n \"tutorials\",\n \"blog\",\n \"book\"\n ],\n \"author\": \"Lewy Blue\",\n \"license\": \"MIT\",\n \"bugs\": {\n \"url\": \"https:\u002F\u002Fgithub.com\u002Flooeee\u002Fdiscoverthree.com-examples\u002Fissues\"\n },\n \"homepage\": \"https:\u002F\u002Fdiscoverthreejs.com\",\n \"scripts\": {\n \"start\": \"parcel index.html --open\",\n \"build\": \"parcel build index.html\"\n },\n \"dependencies\": {},\n \"devDependencies\": {\n \"parcel-bundler\": \"^1.6.1\"\n }\n}\n","directory_shortid":null,"id":"1729ee92-4d57-4284-bb67-942f8307902e","inserted_at":"2020-08-05T03:39:49","is_binary":false,"shortid":"B15pZ5sPZP","source_id":"3985691b-c62a-4f15-b163-88a57fd46675","title":"package.json","updated_at":"2020-08-05T03:39:49","upload_id":null},{"code":"\u002F**\n * @author qiao \u002F https:\u002F\u002Fgithub.com\u002Fqiao\n * @author mrdoob \u002F http:\u002F\u002Fmrdoob.com\n * @author alteredq \u002F http:\u002F\u002Falteredqualia.com\u002F\n * @author WestLangley \u002F http:\u002F\u002Fgithub.com\u002FWestLangley\n * @author erich666 \u002F http:\u002F\u002Ferichaines.com\n *\u002F\n\n\u002F\u002F This set of controls performs orbiting, dollying (zooming), and panning.\n\u002F\u002F Unlike TrackballControls, it maintains the \"up\" direction object.up (+Y by default).\n\u002F\u002F\n\u002F\u002F Orbit - left mouse \u002F touch: one-finger move\n\u002F\u002F Zoom - middle mouse, or mousewheel \u002F touch: two-finger spread or squish\n\u002F\u002F Pan - right mouse, or left mouse + ctrl\u002Fmeta\u002FshiftKey, or arrow keys \u002F touch: two-finger move\n\nTHREE.OrbitControls = function ( object, domElement ) {\n\n\tthis.object = object;\n\n\tthis.domElement = ( domElement !== undefined ) ? domElement : document;\n\n\t\u002F\u002F Set to false to disable this control\n\tthis.enabled = true;\n\n\t\u002F\u002F \"target\" sets the location of focus, where the object orbits around\n\tthis.target = new THREE.Vector3();\n\n\t\u002F\u002F How far you can dolly in and out ( PerspectiveCamera only )\n\tthis.minDistance = 0;\n\tthis.maxDistance = Infinity;\n\n\t\u002F\u002F How far you can zoom in and out ( OrthographicCamera only )\n\tthis.minZoom = 0;\n\tthis.maxZoom = Infinity;\n\n\t\u002F\u002F How far you can orbit vertically, upper and lower limits.\n\t\u002F\u002F Range is 0 to Math.PI radians.\n\tthis.minPolarAngle = 0; \u002F\u002F radians\n\tthis.maxPolarAngle = Math.PI; \u002F\u002F radians\n\n\t\u002F\u002F How far you can orbit horizontally, upper and lower limits.\n\t\u002F\u002F If set, must be a sub-interval of the interval [ - Math.PI, Math.PI ].\n\tthis.minAzimuthAngle = - Infinity; \u002F\u002F radians\n\tthis.maxAzimuthAngle = Infinity; \u002F\u002F radians\n\n\t\u002F\u002F Set to true to enable damping (inertia)\n\t\u002F\u002F If damping is enabled, you must call controls.update() in your animation loop\n\tthis.enableDamping = false;\n\tthis.dampingFactor = 0.25;\n\n\t\u002F\u002F This option actually enables dollying in and out; left as \"zoom\" for backwards compatibility.\n\t\u002F\u002F Set to false to disable zooming\n\tthis.enableZoom = true;\n\tthis.zoomSpeed = 1.0;\n\n\t\u002F\u002F Set to false to disable rotating\n\tthis.enableRotate = true;\n\tthis.rotateSpeed = 1.0;\n\n\t\u002F\u002F Set to false to disable panning\n\tthis.enablePan = true;\n\tthis.panSpeed = 1.0;\n\tthis.screenSpacePanning = false; \u002F\u002F if true, pan in screen-space\n\tthis.keyPanSpeed = 7.0;\t\u002F\u002F pixels moved per arrow key push\n\n\t\u002F\u002F Set to true to automatically rotate around the target\n\t\u002F\u002F If auto-rotate is enabled, you must call controls.update() in your animation loop\n\tthis.autoRotate = false;\n\tthis.autoRotateSpeed = 2.0; \u002F\u002F 30 seconds per round when fps is 60\n\n\t\u002F\u002F Set to false to disable use of the keys\n\tthis.enableKeys = true;\n\n\t\u002F\u002F The four arrow keys\n\tthis.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40 };\n\n\t\u002F\u002F Mouse buttons\n\tthis.mouseButtons = { LEFT: THREE.MOUSE.LEFT, MIDDLE: THREE.MOUSE.MIDDLE, RIGHT: THREE.MOUSE.RIGHT };\n\n\t\u002F\u002F for reset\n\tthis.target0 = this.target.clone();\n\tthis.position0 = this.object.position.clone();\n\tthis.zoom0 = this.object.zoom;\n\n\t\u002F\u002F\n\t\u002F\u002F public methods\n\t\u002F\u002F\n\n\tthis.getPolarAngle = function () {\n\n\t\treturn spherical.phi;\n\n\t};\n\n\tthis.getAzimuthalAngle = function () {\n\n\t\treturn spherical.theta;\n\n\t};\n\n\tthis.saveState = function () {\n\n\t\tscope.target0.copy( scope.target );\n\t\tscope.position0.copy( scope.object.position );\n\t\tscope.zoom0 = scope.object.zoom;\n\n\t};\n\n\tthis.reset = function () {\n\n\t\tscope.target.copy( scope.target0 );\n\t\tscope.object.position.copy( scope.position0 );\n\t\tscope.object.zoom = scope.zoom0;\n\n\t\tscope.object.updateProjectionMatrix();\n\t\tscope.dispatchEvent( changeEvent );\n\n\t\tscope.update();\n\n\t\tstate = STATE.NONE;\n\n\t};\n\n\t\u002F\u002F this method is exposed, but perhaps it would be better if we can make it private...\n\tthis.update = function () {\n\n\t\tvar offset = new THREE.Vector3();\n\n\t\t\u002F\u002F so camera.up is the orbit axis\n\t\tvar quat = new THREE.Quaternion().setFromUnitVectors( object.up, new THREE.Vector3( 0, 1, 0 ) );\n\t\tvar quatInverse = quat.clone().inverse();\n\n\t\tvar lastPosition = new THREE.Vector3();\n\t\tvar lastQuaternion = new THREE.Quaternion();\n\n\t\treturn function update() {\n\n\t\t\tvar position = scope.object.position;\n\n\t\t\toffset.copy( position ).sub( scope.target );\n\n\t\t\t\u002F\u002F rotate offset to \"y-axis-is-up\" space\n\t\t\toffset.applyQuaternion( quat );\n\n\t\t\t\u002F\u002F angle from z-axis around y-axis\n\t\t\tspherical.setFromVector3( offset );\n\n\t\t\tif ( scope.autoRotate && state === STATE.NONE ) {\n\n\t\t\t\trotateLeft( getAutoRotationAngle() );\n\n\t\t\t}\n\n\t\t\tspherical.theta += sphericalDelta.theta;\n\t\t\tspherical.phi += sphericalDelta.phi;\n\n\t\t\t\u002F\u002F restrict theta to be between desired limits\n\t\t\tspherical.theta = Math.max( scope.minAzimuthAngle, Math.min( scope.maxAzimuthAngle, spherical.theta ) );\n\n\t\t\t\u002F\u002F restrict phi to be between desired limits\n\t\t\tspherical.phi = Math.max( scope.minPolarAngle, Math.min( scope.maxPolarAngle, spherical.phi ) );\n\n\t\t\tspherical.makeSafe();\n\n\n\t\t\tspherical.radius *= scale;\n\n\t\t\t\u002F\u002F restrict radius to be between desired limits\n\t\t\tspherical.radius = Math.max( scope.minDistance, Math.min( scope.maxDistance, spherical.radius ) );\n\n\t\t\t\u002F\u002F move target to panned location\n\t\t\tscope.target.add( panOffset );\n\n\t\t\toffset.setFromSpherical( spherical );\n\n\t\t\t\u002F\u002F rotate offset back to \"camera-up-vector-is-up\" space\n\t\t\toffset.applyQuaternion( quatInverse );\n\n\t\t\tposition.copy( scope.target ).add( offset );\n\n\t\t\tscope.object.lookAt( scope.target );\n\n\t\t\tif ( scope.enableDamping === true ) {\n\n\t\t\t\tsphericalDelta.theta *= ( 1 - scope.dampingFactor );\n\t\t\t\tsphericalDelta.phi *= ( 1 - scope.dampingFactor );\n\n\t\t\t\tpanOffset.multiplyScalar( 1 - scope.dampingFactor );\n\n\t\t\t} else {\n\n\t\t\t\tsphericalDelta.set( 0, 0, 0 );\n\n\t\t\t\tpanOffset.set( 0, 0, 0 );\n\n\t\t\t}\n\n\t\t\tscale = 1;\n\n\t\t\t\u002F\u002F update condition is:\n\t\t\t\u002F\u002F min(camera displacement, camera rotation in radians)^2 \u003E EPS\n\t\t\t\u002F\u002F using small-angle approximation cos(x\u002F2) = 1 - x^2 \u002F 8\n\n\t\t\tif ( zoomChanged ||\n\t\t\t\tlastPosition.distanceToSquared( scope.object.position ) \u003E EPS ||\n\t\t\t\t8 * ( 1 - lastQuaternion.dot( scope.object.quaternion ) ) \u003E EPS ) {\n\n\t\t\t\tscope.dispatchEvent( changeEvent );\n\n\t\t\t\tlastPosition.copy( scope.object.position );\n\t\t\t\tlastQuaternion.copy( scope.object.quaternion );\n\t\t\t\tzoomChanged = false;\n\n\t\t\t\treturn true;\n\n\t\t\t}\n\n\t\t\treturn false;\n\n\t\t};\n\n\t}();\n\n\tthis.dispose = function () {\n\n\t\tscope.domElement.removeEventListener( 'contextmenu', onContextMenu, false );\n\t\tscope.domElement.removeEventListener( 'mousedown', onMouseDown, false );\n\t\tscope.domElement.removeEventListener( 'wheel', onMouseWheel, false );\n\n\t\tscope.domElement.removeEventListener( 'touchstart', onTouchStart, false );\n\t\tscope.domElement.removeEventListener( 'touchend', onTouchEnd, false );\n\t\tscope.domElement.removeEventListener( 'touchmove', onTouchMove, false );\n\n\t\tdocument.removeEventListener( 'mousemove', onMouseMove, false );\n\t\tdocument.removeEventListener( 'mouseup', onMouseUp, false );\n\n\t\twindow.removeEventListener( 'keydown', onKeyDown, false );\n\n\t\t\u002F\u002Fscope.dispatchEvent( { type: 'dispose' } ); \u002F\u002F should this be added here?\n\n\t};\n\n\t\u002F\u002F\n\t\u002F\u002F internals\n\t\u002F\u002F\n\n\tvar scope = this;\n\n\tvar changeEvent = { type: 'change' };\n\tvar startEvent = { type: 'start' };\n\tvar endEvent = { type: 'end' };\n\n\tvar STATE = { NONE: - 1, ROTATE: 0, DOLLY: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_DOLLY_PAN: 4 };\n\n\tvar state = STATE.NONE;\n\n\tvar EPS = 0.000001;\n\n\t\u002F\u002F current position in spherical coordinates\n\tvar spherical = new THREE.Spherical();\n\tvar sphericalDelta = new THREE.Spherical();\n\n\tvar scale = 1;\n\tvar panOffset = new THREE.Vector3();\n\tvar zoomChanged = false;\n\n\tvar rotateStart = new THREE.Vector2();\n\tvar rotateEnd = new THREE.Vector2();\n\tvar rotateDelta = new THREE.Vector2();\n\n\tvar panStart = new THREE.Vector2();\n\tvar panEnd = new THREE.Vector2();\n\tvar panDelta = new THREE.Vector2();\n\n\tvar dollyStart = new THREE.Vector2();\n\tvar dollyEnd = new THREE.Vector2();\n\tvar dollyDelta = new THREE.Vector2();\n\n\tfunction getAutoRotationAngle() {\n\n\t\treturn 2 * Math.PI \u002F 60 \u002F 60 * scope.autoRotateSpeed;\n\n\t}\n\n\tfunction getZoomScale() {\n\n\t\treturn Math.pow( 0.95, scope.zoomSpeed );\n\n\t}\n\n\tfunction rotateLeft( angle ) {\n\n\t\tsphericalDelta.theta -= angle;\n\n\t}\n\n\tfunction rotateUp( angle ) {\n\n\t\tsphericalDelta.phi -= angle;\n\n\t}\n\n\tvar panLeft = function () {\n\n\t\tvar v = new THREE.Vector3();\n\n\t\treturn function panLeft( distance, objectMatrix ) {\n\n\t\t\tv.setFromMatrixColumn( objectMatrix, 0 ); \u002F\u002F get X column of objectMatrix\n\t\t\tv.multiplyScalar( - distance );\n\n\t\t\tpanOffset.add( v );\n\n\t\t};\n\n\t}();\n\n\tvar panUp = function () {\n\n\t\tvar v = new THREE.Vector3();\n\n\t\treturn function panUp( distance, objectMatrix ) {\n\n\t\t\tif ( scope.screenSpacePanning === true ) {\n\n\t\t\t\tv.setFromMatrixColumn( objectMatrix, 1 );\n\n\t\t\t} else {\n\n\t\t\t\tv.setFromMatrixColumn( objectMatrix, 0 );\n\t\t\t\tv.crossVectors( scope.object.up, v );\n\n\t\t\t}\n\n\t\t\tv.multiplyScalar( distance );\n\n\t\t\tpanOffset.add( v );\n\n\t\t};\n\n\t}();\n\n\t\u002F\u002F deltaX and deltaY are in pixels; right and down are positive\n\tvar pan = function () {\n\n\t\tvar offset = new THREE.Vector3();\n\n\t\treturn function pan( deltaX, deltaY ) {\n\n\t\t\tvar element = scope.domElement === document ? scope.domElement.body : scope.domElement;\n\n\t\t\tif ( scope.object.isPerspectiveCamera ) {\n\n\t\t\t\t\u002F\u002F perspective\n\t\t\t\tvar position = scope.object.position;\n\t\t\t\toffset.copy( position ).sub( scope.target );\n\t\t\t\tvar targetDistance = offset.length();\n\n\t\t\t\t\u002F\u002F half of the fov is center to top of screen\n\t\t\t\ttargetDistance *= Math.tan( ( scope.object.fov \u002F 2 ) * Math.PI \u002F 180.0 );\n\n\t\t\t\t\u002F\u002F we use only clientHeight here so aspect ratio does not distort speed\n\t\t\t\tpanLeft( 2 * deltaX * targetDistance \u002F element.clientHeight, scope.object.matrix );\n\t\t\t\tpanUp( 2 * deltaY * targetDistance \u002F element.clientHeight, scope.object.matrix );\n\n\t\t\t} else if ( scope.object.isOrthographicCamera ) {\n\n\t\t\t\t\u002F\u002F orthographic\n\t\t\t\tpanLeft( deltaX * ( scope.object.right - scope.object.left ) \u002F scope.object.zoom \u002F element.clientWidth, scope.object.matrix );\n\t\t\t\tpanUp( deltaY * ( scope.object.top - scope.object.bottom ) \u002F scope.object.zoom \u002F element.clientHeight, scope.object.matrix );\n\n\t\t\t} else {\n\n\t\t\t\t\u002F\u002F camera neither orthographic nor perspective\n\t\t\t\tconsole.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.' );\n\t\t\t\tscope.enablePan = false;\n\n\t\t\t}\n\n\t\t};\n\n\t}();\n\n\tfunction dollyIn( dollyScale ) {\n\n\t\tif ( scope.object.isPerspectiveCamera ) {\n\n\t\t\tscale \u002F= dollyScale;\n\n\t\t} else if ( scope.object.isOrthographicCamera ) {\n\n\t\t\tscope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom * dollyScale ) );\n\t\t\tscope.object.updateProjectionMatrix();\n\t\t\tzoomChanged = true;\n\n\t\t} else {\n\n\t\t\tconsole.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly\u002Fzoom disabled.' );\n\t\t\tscope.enableZoom = false;\n\n\t\t}\n\n\t}\n\n\tfunction dollyOut( dollyScale ) {\n\n\t\tif ( scope.object.isPerspectiveCamera ) {\n\n\t\t\tscale *= dollyScale;\n\n\t\t} else if ( scope.object.isOrthographicCamera ) {\n\n\t\t\tscope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom \u002F dollyScale ) );\n\t\t\tscope.object.updateProjectionMatrix();\n\t\t\tzoomChanged = true;\n\n\t\t} else {\n\n\t\t\tconsole.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly\u002Fzoom disabled.' );\n\t\t\tscope.enableZoom = false;\n\n\t\t}\n\n\t}\n\n\t\u002F\u002F\n\t\u002F\u002F event callbacks - update the object state\n\t\u002F\u002F\n\n\tfunction handleMouseDownRotate( event ) {\n\n\t\t\u002F\u002Fconsole.log( 'handleMouseDownRotate' );\n\n\t\trotateStart.set( event.clientX, event.clientY );\n\n\t}\n\n\tfunction handleMouseDownDolly( event ) {\n\n\t\t\u002F\u002Fconsole.log( 'handleMouseDownDolly' );\n\n\t\tdollyStart.set( event.clientX, event.clientY );\n\n\t}\n\n\tfunction handleMouseDownPan( event ) {\n\n\t\t\u002F\u002Fconsole.log( 'handleMouseDownPan' );\n\n\t\tpanStart.set( event.clientX, event.clientY );\n\n\t}\n\n\tfunction handleMouseMoveRotate( event ) {\n\n\t\t\u002F\u002Fconsole.log( 'handleMouseMoveRotate' );\n\n\t\trotateEnd.set( event.clientX, event.clientY );\n\n\t\trotateDelta.subVectors( rotateEnd, rotateStart ).multiplyScalar( scope.rotateSpeed );\n\n\t\tvar element = scope.domElement === document ? scope.domElement.body : scope.domElement;\n\n\t\trotateLeft( 2 * Math.PI * rotateDelta.x \u002F element.clientHeight ); \u002F\u002F yes, height\n\n\t\trotateUp( 2 * Math.PI * rotateDelta.y \u002F element.clientHeight );\n\n\t\trotateStart.copy( rotateEnd );\n\n\t\tscope.update();\n\n\t}\n\n\tfunction handleMouseMoveDolly( event ) {\n\n\t\t\u002F\u002Fconsole.log( 'handleMouseMoveDolly' );\n\n\t\tdollyEnd.set( event.clientX, event.clientY );\n\n\t\tdollyDelta.subVectors( dollyEnd, dollyStart );\n\n\t\tif ( dollyDelta.y \u003E 0 ) {\n\n\t\t\tdollyIn( getZoomScale() );\n\n\t\t} else if ( dollyDelta.y \u003C 0 ) {\n\n\t\t\tdollyOut( getZoomScale() );\n\n\t\t}\n\n\t\tdollyStart.copy( dollyEnd );\n\n\t\tscope.update();\n\n\t}\n\n\tfunction handleMouseMovePan( event ) {\n\n\t\t\u002F\u002Fconsole.log( 'handleMouseMovePan' );\n\n\t\tpanEnd.set( event.clientX, event.clientY );\n\n\t\tpanDelta.subVectors( panEnd, panStart ).multiplyScalar( scope.panSpeed );\n\n\t\tpan( panDelta.x, panDelta.y );\n\n\t\tpanStart.copy( panEnd );\n\n\t\tscope.update();\n\n\t}\n\n\tfunction handleMouseUp( event ) {\n\n\t\t\u002F\u002F console.log( 'handleMouseUp' );\n\n\t}\n\n\tfunction handleMouseWheel( event ) {\n\n\t\t\u002F\u002F console.log( 'handleMouseWheel' );\n\n\t\tif ( event.deltaY \u003C 0 ) {\n\n\t\t\tdollyOut( getZoomScale() );\n\n\t\t} else if ( event.deltaY \u003E 0 ) {\n\n\t\t\tdollyIn( getZoomScale() );\n\n\t\t}\n\n\t\tscope.update();\n\n\t}\n\n\tfunction handleKeyDown( event ) {\n\n\t\t\u002F\u002F console.log( 'handleKeyDown' );\n\n\t\tvar needsUpdate = false;\n\n\t\tswitch ( event.keyCode ) {\n\n\t\t\tcase scope.keys.UP:\n\t\t\t\tpan( 0, scope.keyPanSpeed );\n\t\t\t\tneedsUpdate = true;\n\t\t\t\tbreak;\n\n\t\t\tcase scope.keys.BOTTOM:\n\t\t\t\tpan( 0, - scope.keyPanSpeed );\n\t\t\t\tneedsUpdate = true;\n\t\t\t\tbreak;\n\n\t\t\tcase scope.keys.LEFT:\n\t\t\t\tpan( scope.keyPanSpeed, 0 );\n\t\t\t\tneedsUpdate = true;\n\t\t\t\tbreak;\n\n\t\t\tcase scope.keys.RIGHT:\n\t\t\t\tpan( - scope.keyPanSpeed, 0 );\n\t\t\t\tneedsUpdate = true;\n\t\t\t\tbreak;\n\n\t\t}\n\n\t\tif ( needsUpdate ) {\n\n\t\t\t\u002F\u002F prevent the browser from scrolling on cursor keys\n\t\t\tevent.preventDefault();\n\n\t\t\tscope.update();\n\n\t\t}\n\n\n\t}\n\n\tfunction handleTouchStartRotate( event ) {\n\n\t\t\u002F\u002Fconsole.log( 'handleTouchStartRotate' );\n\n\t\trotateStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );\n\n\t}\n\n\tfunction handleTouchStartDollyPan( event ) {\n\n\t\t\u002F\u002Fconsole.log( 'handleTouchStartDollyPan' );\n\n\t\tif ( scope.enableZoom ) {\n\n\t\t\tvar dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;\n\t\t\tvar dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;\n\n\t\t\tvar distance = Math.sqrt( dx * dx + dy * dy );\n\n\t\t\tdollyStart.set( 0, distance );\n\n\t\t}\n\n\t\tif ( scope.enablePan ) {\n\n\t\t\tvar x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX );\n\t\t\tvar y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY );\n\n\t\t\tpanStart.set( x, y );\n\n\t\t}\n\n\t}\n\n\tfunction handleTouchMoveRotate( event ) {\n\n\t\t\u002F\u002Fconsole.log( 'handleTouchMoveRotate' );\n\n\t\trotateEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );\n\n\t\trotateDelta.subVectors( rotateEnd, rotateStart ).multiplyScalar( scope.rotateSpeed );\n\n\t\tvar element = scope.domElement === document ? scope.domElement.body : scope.domElement;\n\n\t\trotateLeft( 2 * Math.PI * rotateDelta.x \u002F element.clientHeight ); \u002F\u002F yes, height\n\n\t\trotateUp( 2 * Math.PI * rotateDelta.y \u002F element.clientHeight );\n\n\t\trotateStart.copy( rotateEnd );\n\n\t\tscope.update();\n\n\t}\n\n\tfunction handleTouchMoveDollyPan( event ) {\n\n\t\t\u002F\u002Fconsole.log( 'handleTouchMoveDollyPan' );\n\n\t\tif ( scope.enableZoom ) {\n\n\t\t\tvar dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;\n\t\t\tvar dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;\n\n\t\t\tvar distance = Math.sqrt( dx * dx + dy * dy );\n\n\t\t\tdollyEnd.set( 0, distance );\n\n\t\t\tdollyDelta.set( 0, Math.pow( dollyEnd.y \u002F dollyStart.y, scope.zoomSpeed ) );\n\n\t\t\tdollyIn( dollyDelta.y );\n\n\t\t\tdollyStart.copy( dollyEnd );\n\n\t\t}\n\n\t\tif ( scope.enablePan ) {\n\n\t\t\tvar x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX );\n\t\t\tvar y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY );\n\n\t\t\tpanEnd.set( x, y );\n\n\t\t\tpanDelta.subVectors( panEnd, panStart ).multiplyScalar( scope.panSpeed );\n\n\t\t\tpan( panDelta.x, panDelta.y );\n\n\t\t\tpanStart.copy( panEnd );\n\n\t\t}\n\n\t\tscope.update();\n\n\t}\n\n\tfunction handleTouchEnd( event ) {\n\n\t\t\u002F\u002Fconsole.log( 'handleTouchEnd' );\n\n\t}\n\n\t\u002F\u002F\n\t\u002F\u002F event handlers - FSM: listen for events and reset state\n\t\u002F\u002F\n\n\tfunction onMouseDown( event ) {\n\n\t\tif ( scope.enabled === false ) return;\n\n\t\t\u002F\u002F Prevent the browser from scrolling.\n\n\t\tevent.preventDefault();\n\n\t\t\u002F\u002F Manually set the focus since calling preventDefault above\n\t\t\u002F\u002F prevents the browser from setting it automatically.\n\n\t\tscope.domElement.focus ? scope.domElement.focus() : window.focus();\n\n\t\tswitch ( event.button ) {\n\n\t\t\tcase scope.mouseButtons.LEFT:\n\n\t\t\t\tif ( event.ctrlKey || event.metaKey || event.shiftKey ) {\n\n\t\t\t\t\tif ( scope.enablePan === false ) return;\n\n\t\t\t\t\thandleMouseDownPan( event );\n\n\t\t\t\t\tstate = STATE.PAN;\n\n\t\t\t\t} else {\n\n\t\t\t\t\tif ( scope.enableRotate === false ) return;\n\n\t\t\t\t\thandleMouseDownRotate( event );\n\n\t\t\t\t\tstate = STATE.ROTATE;\n\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\n\t\t\tcase scope.mouseButtons.MIDDLE:\n\n\t\t\t\tif ( scope.enableZoom === false ) return;\n\n\t\t\t\thandleMouseDownDolly( event );\n\n\t\t\t\tstate = STATE.DOLLY;\n\n\t\t\t\tbreak;\n\n\t\t\tcase scope.mouseButtons.RIGHT:\n\n\t\t\t\tif ( scope.enablePan === false ) return;\n\n\t\t\t\thandleMouseDownPan( event );\n\n\t\t\t\tstate = STATE.PAN;\n\n\t\t\t\tbreak;\n\n\t\t}\n\n\t\tif ( state !== STATE.NONE ) {\n\n\t\t\tdocument.addEventListener( 'mousemove', onMouseMove, false );\n\t\t\tdocument.addEventListener( 'mouseup', onMouseUp, false );\n\n\t\t\tscope.dispatchEvent( startEvent );\n\n\t\t}\n\n\t}\n\n\tfunction onMouseMove( event ) {\n\n\t\tif ( scope.enabled === false ) return;\n\n\t\tevent.preventDefault();\n\n\t\tswitch ( state ) {\n\n\t\t\tcase STATE.ROTATE:\n\n\t\t\t\tif ( scope.enableRotate === false ) return;\n\n\t\t\t\thandleMouseMoveRotate( event );\n\n\t\t\t\tbreak;\n\n\t\t\tcase STATE.DOLLY:\n\n\t\t\t\tif ( scope.enableZoom === false ) return;\n\n\t\t\t\thandleMouseMoveDolly( event );\n\n\t\t\t\tbreak;\n\n\t\t\tcase STATE.PAN:\n\n\t\t\t\tif ( scope.enablePan === false ) return;\n\n\t\t\t\thandleMouseMovePan( event );\n\n\t\t\t\tbreak;\n\n\t\t}\n\n\t}\n\n\tfunction onMouseUp( event ) {\n\n\t\tif ( scope.enabled === false ) return;\n\n\t\thandleMouseUp( event );\n\n\t\tdocument.removeEventListener( 'mousemove', onMouseMove, false );\n\t\tdocument.removeEventListener( 'mouseup', onMouseUp, false );\n\n\t\tscope.dispatchEvent( endEvent );\n\n\t\tstate = STATE.NONE;\n\n\t}\n\n\tfunction onMouseWheel( event ) {\n\n\t\tif ( scope.enabled === false || scope.enableZoom === false || ( state !== STATE.NONE && state !== STATE.ROTATE ) ) return;\n\n\t\tevent.preventDefault();\n\t\tevent.stopPropagation();\n\n\t\tscope.dispatchEvent( startEvent );\n\n\t\thandleMouseWheel( event );\n\n\t\tscope.dispatchEvent( endEvent );\n\n\t}\n\n\tfunction onKeyDown( event ) {\n\n\t\tif ( scope.enabled === false || scope.enableKeys === false || scope.enablePan === false ) return;\n\n\t\thandleKeyDown( event );\n\n\t}\n\n\tfunction onTouchStart( event ) {\n\n\t\tif ( scope.enabled === false ) return;\n\n\t\tevent.preventDefault();\n\n\t\tswitch ( event.touches.length ) {\n\n\t\t\tcase 1:\t\u002F\u002F one-fingered touch: rotate\n\n\t\t\t\tif ( scope.enableRotate === false ) return;\n\n\t\t\t\thandleTouchStartRotate( event );\n\n\t\t\t\tstate = STATE.TOUCH_ROTATE;\n\n\t\t\t\tbreak;\n\n\t\t\tcase 2:\t\u002F\u002F two-fingered touch: dolly-pan\n\n\t\t\t\tif ( scope.enableZoom === false && scope.enablePan === false ) return;\n\n\t\t\t\thandleTouchStartDollyPan( event );\n\n\t\t\t\tstate = STATE.TOUCH_DOLLY_PAN;\n\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\n\t\t\t\tstate = STATE.NONE;\n\n\t\t}\n\n\t\tif ( state !== STATE.NONE ) {\n\n\t\t\tscope.dispatchEvent( startEvent );\n\n\t\t}\n\n\t}\n\n\tfunction onTouchMove( event ) {\n\n\t\tif ( scope.enabled === false ) return;\n\n\t\tevent.preventDefault();\n\t\tevent.stopPropagation();\n\n\t\tswitch ( event.touches.length ) {\n\n\t\t\tcase 1: \u002F\u002F one-fingered touch: rotate\n\n\t\t\t\tif ( scope.enableRotate === false ) return;\n\t\t\t\tif ( state !== STATE.TOUCH_ROTATE ) return; \u002F\u002F is this needed?\n\n\t\t\t\thandleTouchMoveRotate( event );\n\n\t\t\t\tbreak;\n\n\t\t\tcase 2: \u002F\u002F two-fingered touch: dolly-pan\n\n\t\t\t\tif ( scope.enableZoom === false && scope.enablePan === false ) return;\n\t\t\t\tif ( state !== STATE.TOUCH_DOLLY_PAN ) return; \u002F\u002F is this needed?\n\n\t\t\t\thandleTouchMoveDollyPan( event );\n\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\n\t\t\t\tstate = STATE.NONE;\n\n\t\t}\n\n\t}\n\n\tfunction onTouchEnd( event ) {\n\n\t\tif ( scope.enabled === false ) return;\n\n\t\thandleTouchEnd( event );\n\n\t\tscope.dispatchEvent( endEvent );\n\n\t\tstate = STATE.NONE;\n\n\t}\n\n\tfunction onContextMenu( event ) {\n\n\t\tif ( scope.enabled === false ) return;\n\n\t\tevent.preventDefault();\n\n\t}\n\n\t\u002F\u002F\n\n\tscope.domElement.addEventListener( 'contextmenu', onContextMenu, false );\n\n\tscope.domElement.addEventListener( 'mousedown', onMouseDown, false );\n\tscope.domElement.addEventListener( 'wheel', onMouseWheel, false );\n\n\tscope.domElement.addEventListener( 'touchstart', onTouchStart, false );\n\tscope.domElement.addEventListener( 'touchend', onTouchEnd, false );\n\tscope.domElement.addEventListener( 'touchmove', onTouchMove, false );\n\n\twindow.addEventListener( 'keydown', onKeyDown, false );\n\n\t\u002F\u002F force an update at start\n\n\tthis.update();\n\n};\n\nTHREE.OrbitControls.prototype = Object.create( THREE.EventDispatcher.prototype );\nTHREE.OrbitControls.prototype.constructor = THREE.OrbitControls;\n\nObject.defineProperties( THREE.OrbitControls.prototype, {\n\n\tcenter: {\n\n\t\tget: function () {\n\n\t\t\tconsole.warn( 'THREE.OrbitControls: .center has been renamed to .target' );\n\t\t\treturn this.target;\n\n\t\t}\n\n\t},\n\n\t\u002F\u002F backward compatibility\n\n\tnoZoom: {\n\n\t\tget: function () {\n\n\t\t\tconsole.warn( 'THREE.OrbitControls: .noZoom has been deprecated. Use .enableZoom instead.' );\n\t\t\treturn ! this.enableZoom;\n\n\t\t},\n\n\t\tset: function ( value ) {\n\n\t\t\tconsole.warn( 'THREE.OrbitControls: .noZoom has been deprecated. Use .enableZoom instead.' );\n\t\t\tthis.enableZoom = ! value;\n\n\t\t}\n\n\t},\n\n\tnoRotate: {\n\n\t\tget: function () {\n\n\t\t\tconsole.warn( 'THREE.OrbitControls: .noRotate has been deprecated. Use .enableRotate instead.' );\n\t\t\treturn ! this.enableRotate;\n\n\t\t},\n\n\t\tset: function ( value ) {\n\n\t\t\tconsole.warn( 'THREE.OrbitControls: .noRotate has been deprecated. Use .enableRotate instead.' );\n\t\t\tthis.enableRotate = ! value;\n\n\t\t}\n\n\t},\n\n\tnoPan: {\n\n\t\tget: function () {\n\n\t\t\tconsole.warn( 'THREE.OrbitControls: .noPan has been deprecated. Use .enablePan instead.' );\n\t\t\treturn ! this.enablePan;\n\n\t\t},\n\n\t\tset: function ( value ) {\n\n\t\t\tconsole.warn( 'THREE.OrbitControls: .noPan has been deprecated. Use .enablePan instead.' );\n\t\t\tthis.enablePan = ! value;\n\n\t\t}\n\n\t},\n\n\tnoKeys: {\n\n\t\tget: function () {\n\n\t\t\tconsole.warn( 'THREE.OrbitControls: .noKeys has been deprecated. Use .enableKeys instead.' );\n\t\t\treturn ! this.enableKeys;\n\n\t\t},\n\n\t\tset: function ( value ) {\n\n\t\t\tconsole.warn( 'THREE.OrbitControls: .noKeys has been deprecated. Use .enableKeys instead.' );\n\t\t\tthis.enableKeys = ! value;\n\n\t\t}\n\n\t},\n\n\tstaticMoving: {\n\n\t\tget: function () {\n\n\t\t\tconsole.warn( 'THREE.OrbitControls: .staticMoving has been deprecated. Use .enableDamping instead.' );\n\t\t\treturn ! this.enableDamping;\n\n\t\t},\n\n\t\tset: function ( value ) {\n\n\t\t\tconsole.warn( 'THREE.OrbitControls: .staticMoving has been deprecated. Use .enableDamping instead.' );\n\t\t\tthis.enableDamping = ! value;\n\n\t\t}\n\n\t},\n\n\tdynamicDampingFactor: {\n\n\t\tget: function () {\n\n\t\t\tconsole.warn( 'THREE.OrbitControls: .dynamicDampingFactor has been renamed. Use .dampingFactor instead.' );\n\t\t\treturn this.dampingFactor;\n\n\t\t},\n\n\t\tset: function ( value ) {\n\n\t\t\tconsole.warn( 'THREE.OrbitControls: .dynamicDampingFactor has been renamed. Use .dampingFactor instead.' );\n\t\t\tthis.dampingFactor = value;\n\n\t\t}\n\n\t}\n\n} );\n","directory_shortid":"BJzTbcoD-P","id":"d3fae823-7b8a-4d17-be2f-9d5264c387cd","inserted_at":"2020-08-05T03:39:49","is_binary":false,"shortid":"SyFTW9jDWv","source_id":"3985691b-c62a-4f15-b163-88a57fd46675","title":"OrbitControls.js","updated_at":"2020-08-05T03:39:49","upload_id":null},{"code":"\u002F\u002F these need to be accessed inside more than one function so we'll declare them first\nlet container;\nlet camera;\nlet controls;\nlet renderer;\nlet scene;\n\nconst mixers = [];\nconst clock = new THREE.Clock();\n\nfunction init() {\n\n container = document.querySelector( '#scene-container' );\n\n scene = new THREE.Scene();\n scene.background = new THREE.Color( 0x8FBCD4 );\n\n createCamera();\n createControls();\n createLights();\n loadModels();\n createRenderer();\n\n renderer.setAnimationLoop( () =\u003E {\n\n update();\n render();\n\n } );\n\n}\n\nfunction createCamera() {\n\n camera = new THREE.PerspectiveCamera( 35, container.clientWidth \u002F container.clientHeight, 1, 100 );\n camera.position.set( -1.5, 1.5, 6.5 );\n\n}\n\nfunction createControls() {\n\n controls = new THREE.OrbitControls( camera, container );\n\n}\n\nfunction createLights() {\n\n const ambientLight = new THREE.HemisphereLight( 0xddeeff, 0x0f0e0d, 5 );\n\n const mainLight = new THREE.DirectionalLight( 0xffffff, 5 );\n mainLight.position.set( 10, 10, 10 );\n\n scene.add( ambientLight, mainLight );\n\n}\n\nfunction loadModels() {\n\n const loader = new THREE.GLTFLoader();\n\n \u002F\u002F A reusable function to set up the models. We're passing in a position parameter\n \u002F\u002F so that they can be individually placed around the scene\n const onLoad = ( gltf, position ) =\u003E {\n\n const model = gltf.scene.children[ 0 ];\n model.position.copy( position );\n\n const animation = gltf.animations[ 0 ];\n\n const mixer = new THREE.AnimationMixer( model );\n mixers.push( mixer );\n\n const action = mixer.clipAction( animation );\n action.play();\n\n scene.add( model );\n\n };\n\n \u002F\u002F the loader will report the loading progress to this function\n const onProgress = () =\u003E {};\n\n \u002F\u002F the loader will send any error messages to this function, and we'll log\n \u002F\u002F them to to console\n const onError = ( errorMessage ) =\u003E { console.log( errorMessage ); };\n\n \u002F\u002F load the first model. Each model is loaded asynchronously,\n \u002F\u002F so don't make any assumption about which one will finish loading first\n const parrotPosition = new THREE.Vector3( 0, 0, 2.5 );\n loader.load( 'models\u002FParrot.glb', gltf =\u003E onLoad( gltf, parrotPosition ), onProgress, onError );\n\n const flamingoPosition = new THREE.Vector3( 7.5, 0, -10 );\n loader.load( 'models\u002FFlamingo.glb', gltf =\u003E onLoad( gltf, flamingoPosition ), onProgress, onError );\n\n const storkPosition = new THREE.Vector3( 0, -2.5, -10 );\n loader.load( 'models\u002FStork.glb', gltf =\u003E onLoad( gltf, storkPosition ), onProgress, onError );\n\n}\n\nfunction createRenderer() {\n\n \u002F\u002F create a WebGLRenderer and set its width and height\n renderer = new THREE.WebGLRenderer( { antialias: true } );\n renderer.setSize( container.clientWidth, container.clientHeight );\n\n renderer.setPixelRatio( window.devicePixelRatio );\n\n renderer.gammaFactor = 2.2;\n renderer.gammaOutput = true;\n\n renderer.physicallyCorrectLights = true;\n\n container.appendChild( renderer.domElement );\n\n}\n\nfunction update() {\n\n const delta = clock.getDelta();\n\n for ( const mixer of mixers ) {\n\n mixer.update( delta );\n\n }\n\n}\n\nfunction render() {\n\n renderer.render( scene, camera );\n\n}\n\nfunction onWindowResize() {\n\n camera.aspect = container.clientWidth \u002F container.clientHeight;\n\n \u002F\u002F update the camera's frustum\n camera.updateProjectionMatrix();\n\n renderer.setSize( container.clientWidth, container.clientHeight );\n\n}\n\nwindow.addEventListener( 'resize', onWindowResize );\n\ninit();\n","directory_shortid":"BJgaWcoPbD","id":"066fc8e8-d68b-4098-855b-f908c2c1cd51","inserted_at":"2020-08-05T03:39:49","is_binary":false,"shortid":"By_aZcsPZP","source_id":"3985691b-c62a-4f15-b163-88a57fd46675","title":"app.js","updated_at":"2020-08-05T03:39:49","upload_id":null},{"code":"\u003C!DOCTYPE html\u003E\n\u003Chtml\u003E\n\n\t\u003Chead\u003E\n\n\t\t\u003Ctitle\u003EDiscoverthreejs.com - Ch 1.7: Load Models\u003C\u002Ftitle\u003E\n\n\t\t\u003Cmeta name=\"viewport\" content=\"width=device-width, initial-scale=1\"\u003E\n\t\t\u003Cmeta charset=\"UTF-8\" \u002F\u003E\n\n\t\t\u003Clink rel=\"icon\" href=\"https:\u002F\u002Fdiscoverthreejs.com\u002Ffavicon.ico\" type=\"image\u002Fx-icon\"\u003E\n\n\t\t\u003Clink href=\"styles\u002Fmain.css\" rel=\"stylesheet\" type=\"text\u002Fcss\"\u003E\n\n \u003C!--\n\n Include the main three.js script.\n\n The global variable THREE will be\n available for use in any scripts\n loaded after this one.\n\n --\u003E\n\n \u003Cscript src=\"js\u002Fvendor\u002Fthree\u002Fthree.js\"\u003E\u003C\u002Fscript\u003E\n\n \u003C!--\n\n Include the OrbitControls script.\n\n This must be included AFTER the three.js script as it\n needs to use the global THREE variable\n\n --\u003E\n\n \u003Cscript src=\"js\u002Fvendor\u002Fthree\u002FOrbitControls.js\"\u003E\u003C\u002Fscript\u003E\n\n\t\t\u003C!--\n\n\t\t\tInclude the GLTFLoader script. This also needs to be loaded after the three.js script\n\n\t\t--\u003E\n\n\t\t\u003Cscript src=\"js\u002Fvendor\u002Fthree\u002FGLTFLoader.js\"\u003E\u003C\u002Fscript\u003E\n\n\t\u003C\u002Fhead\u003E\n\n\t\u003Cbody\u003E\n\n\t\t\u003Ch1 class=\"title\"\u003E\u003Ca href=\"https:\u002F\u002Fdiscoverthreejs.com\u002F\"\u003EDiscoverthreejs.com\u003C\u002Fa\u003E - Ch 1.7 Load Models\u003C\u002Fh1\u003E\n\n\t\t\u003Cdiv id=\"scene-container\"\u003E\n\t\t\t\u003C!-- This div will hold our scene--\u003E\n\t\t\u003C\u002Fdiv\u003E\n\n\t\t\u003C!--\n\t\t\tFinally, include the script that\n\t\t\truns your three.js app.\n\t\t--\u003E\n\n\t\t\u003Cscript src=\"js\u002Fapp.js\"\u003E\u003C\u002Fscript\u003E\n\n\t\u003C\u002Fbody\u003E\n\n\u003C\u002Fhtml\u003E","directory_shortid":null,"id":"b598da02-9c09-4793-937c-a8968d21c5e1","inserted_at":"2020-08-05T03:39:49","is_binary":false,"shortid":"SkwpW9ovWP","source_id":"3985691b-c62a-4f15-b163-88a57fd46675","title":"index.html","updated_at":"2020-08-05T03:39:49","upload_id":null},{"code":"https:\u002F\u002Frawcdn.githack.com\u002Flooeee\u002Fdiscoverthree.com-examples\u002Fe5685a56de31cedc25465ace3f488946bdc26478\u002Ffirst-steps\u002F7-load-models\u002Fmodels\u002FStork.glb","directory_shortid":"HyTZ9iwZP","id":"5d2a5b08-b453-473c-b0e6-33862e44f6f5","inserted_at":"2020-08-05T03:39:49","is_binary":true,"shortid":"S1LpW5jD-v","source_id":"3985691b-c62a-4f15-b163-88a57fd46675","title":"Stork.glb","updated_at":"2020-08-05T03:39:49","upload_id":null},{"code":"https:\u002F\u002Frawcdn.githack.com\u002Flooeee\u002Fdiscoverthree.com-examples\u002Fe5685a56de31cedc25465ace3f488946bdc26478\u002Ffirst-steps\u002F7-load-models\u002Fmodels\u002FParrot.glb","directory_shortid":"HyTZ9iwZP","id":"b1114005-f961-4de9-a647-b3ac6a6cc4a8","inserted_at":"2020-08-05T03:39:49","is_binary":true,"shortid":"HkHpZqoPbv","source_id":"3985691b-c62a-4f15-b163-88a57fd46675","title":"Parrot.glb","updated_at":"2020-08-05T03:39:49","upload_id":null},{"code":"https:\u002F\u002Frawcdn.githack.com\u002Flooeee\u002Fdiscoverthree.com-examples\u002Fe5685a56de31cedc25465ace3f488946bdc26478\u002Ffirst-steps\u002F7-load-models\u002Fmodels\u002FFlamingo.glb","directory_shortid":"HyTZ9iwZP","id":"e8173bae-4ae1-43ae-821a-aeb347e50ea5","inserted_at":"2020-08-05T03:39:49","is_binary":true,"shortid":"SyNTb5oDZP","source_id":"3985691b-c62a-4f15-b163-88a57fd46675","title":"Flamingo.glb","updated_at":"2020-08-05T03:39:49","upload_id":null}],"picks":[],"is_frozen":false,"view_count":237859,"forked_template_sandbox":null,"template":"static","npm_dependencies":{},"external_resources":[],"forked_template":null,"title":"looeee\u002Fdiscoverthree.com-examples: 7-load-models","privacy":0,"description":"Final code from Ch 1.7 of Discover three.js","original_git_commit_sha":null,"preview_secret":null,"original_git":null,"room_id":null,"version":3,"screenshot_url":"https:\u002F\u002Fscreenshots.codesandbox.io\u002Fi24yn.png","tags":[]};