Browse Source

Giving a second go to WebGLRenderer2.

Mr.doob 12 years ago
parent
commit
7327917535
4 changed files with 6655 additions and 6294 deletions
  1. 6262 5901
      build/three.js
  2. 383 383
      build/three.min.js
  3. 8 2
      utils/build/includes/common.json
  4. 2 8
      utils/build/includes/common_old.json

+ 6262 - 5901
build/three.js

@@ -2676,130 +2676,6 @@ THREE.extend( THREE.Vector4.prototype, {
  * @author bhouston / http://exocortex.com
  * @author bhouston / http://exocortex.com
  */
  */
 
 
-THREE.Line3 = function ( start, end ) {
-
-	this.start = ( start !== undefined ) ? start : new THREE.Vector3();
-	this.end = ( end !== undefined ) ? end : new THREE.Vector3();
-
-};
-
-THREE.extend( THREE.Line3.prototype, {
-
-	set: function ( start, end ) {
-
-		this.start.copy( start );
-		this.end.copy( end );
-
-		return this;
-
-	},
-
-	copy: function ( line ) {
-
-		this.start.copy( line.start );
-		this.end.copy( line.end );
-
-		return this;
-
-	},
-
-	center: function ( optionalTarget ) {
-
-		var result = optionalTarget || new THREE.Vector3();
-		return result.addVectors( this.start, this.end ).multiplyScalar( 0.5 );
-
-	},
-
-	delta: function ( optionalTarget ) {
-
-		var result = optionalTarget || new THREE.Vector3();
-		return result.subVectors( this.end, this.start );
-
-	},
-
-	distanceSq: function () {
-
-		return this.start.distanceToSquared( this.end );
-
-	},
-
-	distance: function () {
-
-		return this.start.distanceTo( this.end );
-
-	},
-
-	at: function ( t, optionalTarget ) {
-
-		var result = optionalTarget || new THREE.Vector3();
-
-		return this.delta( result ).multiplyScalar( t ).add( this.start );
-
-	},
-
-	closestPointToPointParameter: function() {
-
-		var startP = new THREE.Vector3();
-		var startEnd = new THREE.Vector3();
-
-		return function ( point, clampToLine ) {
-		
-			startP.subVectors( point, this.start );
-			startEnd.subVectors( this.end, this.start );
-
-			var startEnd2 = startEnd.dot( startEnd );
-			var startEnd_startP = startEnd.dot( startP );
-
-			var t = startEnd_startP / startEnd2;
-
-			if( clampToLine ) {
-				
-	        	t = THREE.Math.clamp( t, 0, 1 );
-
-	        }
-
-	        return t;
-
-		};
-
-	}(),
-
-	closestPointToPoint: function ( point, clampToLine, optionalTarget ) {
-
-		var t = this.closestPointToPointParameter( point, clampToLine );
-
-		var result = optionalTarget || new THREE.Vector3();			
-
-        return this.delta( result ).multiplyScalar( t ).add( this.start );
-
-	},
-
-	applyMatrix4: function ( matrix ) {
-
-		this.start.applyMatrix4( matrix );
-		this.end.applyMatrix4( matrix );
-
-		return this;
-
-	},
-
-	equals: function ( line ) {
-
-		return line.start.equals( this.start ) && line.end.equals( this.end );
-
-	},
-
-	clone: function () {
-
-		return new THREE.Line3().copy( this );
-
-	}
-
-} );
-/**
- * @author bhouston / http://exocortex.com
- */
-
 THREE.Box2 = function ( min, max ) {
 THREE.Box2 = function ( min, max ) {
 
 
 	this.min = ( min !== undefined ) ? min : new THREE.Vector2( Infinity, Infinity );
 	this.min = ( min !== undefined ) ? min : new THREE.Vector2( Infinity, Infinity );
@@ -6258,8 +6134,6 @@ THREE.Object3D = function () {
 
 
 	this.frustumCulled = true;
 	this.frustumCulled = true;
 
 
-	this._vector = new THREE.Vector3();
-
 };
 };
 
 
 
 
@@ -6295,32 +6169,71 @@ THREE.Object3D.prototype = {
 
 
 	}(),
 	}(),
 
 
-	translate: function ( distance, axis ) {
+	translate: function () {
 
 
-		axis.transformDirection( this.matrix );
-		axis.multiplyScalar( distance );
+		var v1 = new THREE.Vector3();
 
 
-		this.position.add( axis );
+		return function ( distance, axis ) {
 
 
-	},
+			// axis is assumed to be normalized
 
 
-	translateX: function ( distance ) {
+			v1.copy( axis );
 
 
-		this.translate( distance, this._vector.set( 1, 0, 0 ) );
+			if ( this.useQuaternion === true ) {
 
 
-	},
+				v1.applyQuaternion( this.quaternion );
 
 
-	translateY: function ( distance ) {
+			} else {
 
 
-		this.translate( distance, this._vector.set( 0, 1, 0 ) );
+				v1.applyEuler( this.rotation, this.eulerOrder );
 
 
-	},
+			}
 
 
-	translateZ: function ( distance ) {
+			v1.multiplyScalar( distance );
 
 
-		this.translate( distance, this._vector.set( 0, 0, 1 ) );
+			this.position.add( v1 );
 
 
-	},
+			return this;
+
+		};
+
+	}(),
+
+	translateX: function () {
+
+		var v1 = new THREE.Vector3( 1, 0, 0 );
+
+		return function ( distance ) {
+
+			return this.translate( distance, v1 );
+
+		};
+
+	}(),
+
+	translateY: function () {
+
+		var v1 = new THREE.Vector3( 0, 1, 0 );
+
+		return function ( distance ) {
+
+			return this.translate( distance, v1 );
+
+		};
+
+	}(),
+
+	translateZ: function () {
+
+		var v1 = new THREE.Vector3( 0, 0, 1 );
+
+		return function ( distance ) {
+
+			return this.translate( distance, v1 );
+
+		};
+
+	}(),
 
 
 	localToWorld: function ( vector ) {
 	localToWorld: function ( vector ) {
 
 
@@ -17887,7333 +17800,7781 @@ THREE.ShaderLib = {
 	}
 	}
 
 
 };
 };
-/**
- * @author supereggbert / http://www.paulbrunt.co.uk/
- * @author mrdoob / http://mrdoob.com/
- * @author alteredq / http://alteredqualia.com/
- * @author szimek / https://github.com/szimek/
- */
-
-THREE.WebGLRenderer = function ( parameters ) {
-
-	console.log( 'THREE.WebGLRenderer', THREE.REVISION );
-
-	parameters = parameters || {};
-
-	var _canvas = parameters.canvas !== undefined ? parameters.canvas : document.createElement( 'canvas' ),
-
-	_precision = parameters.precision !== undefined ? parameters.precision : 'highp',
-
-	_alpha = parameters.alpha !== undefined ? parameters.alpha : true,
-	_premultipliedAlpha = parameters.premultipliedAlpha !== undefined ? parameters.premultipliedAlpha : true,
-	_antialias = parameters.antialias !== undefined ? parameters.antialias : false,
-	_stencil = parameters.stencil !== undefined ? parameters.stencil : true,
-	_preserveDrawingBuffer = parameters.preserveDrawingBuffer !== undefined ? parameters.preserveDrawingBuffer : false,
-
-	_clearColor = parameters.clearColor !== undefined ? new THREE.Color( parameters.clearColor ) : new THREE.Color( 0x000000 ),
-	_clearAlpha = parameters.clearAlpha !== undefined ? parameters.clearAlpha : 0;
-
-	// public properties
-
-	this.domElement = _canvas;
-	this.context = null;
-	this.devicePixelRatio = parameters.devicePixelRatio !== undefined
-				? parameters.devicePixelRatio
-				: window.devicePixelRatio !== undefined
-					? window.devicePixelRatio
-					: 1;
-
-	// clearing
-
-	this.autoClear = true;
-	this.autoClearColor = true;
-	this.autoClearDepth = true;
-	this.autoClearStencil = true;
-
-	// scene graph
-
-	this.sortObjects = true;
-
-	this.autoUpdateObjects = true;
-	this.autoUpdateScene = true;
-
-	// physically based shading
-
-	this.gammaInput = false;
-	this.gammaOutput = false;
-	this.physicallyBasedShading = false;
-
-	// shadow map
-
-	this.shadowMapEnabled = false;
-	this.shadowMapAutoUpdate = true;
-	this.shadowMapType = THREE.PCFShadowMap;
-	this.shadowMapCullFace = THREE.CullFaceFront;
-	this.shadowMapDebug = false;
-	this.shadowMapCascade = false;
-
-	// morphs
-
-	this.maxMorphTargets = 8;
-	this.maxMorphNormals = 4;
-
-	// flags
-
-	this.autoScaleCubemaps = true;
-
-	// custom render plugins
-
-	this.renderPluginsPre = [];
-	this.renderPluginsPost = [];
-
-	// info
-
-	this.info = {
-
-		memory: {
-
-			programs: 0,
-			geometries: 0,
-			textures: 0
-
-		},
-
-		render: {
-
-			calls: 0,
-			vertices: 0,
-			faces: 0,
-			points: 0
-
-		}
-
-	};
-
-	// internal properties
-
-	var _this = this,
-
-	_programs = [],
-	_programs_counter = 0,
-
-	// internal state cache
-
-	_currentProgram = null,
-	_currentFramebuffer = null,
-	_currentMaterialId = -1,
-	_currentGeometryGroupHash = null,
-	_currentCamera = null,
-	_geometryGroupCounter = 0,
-
-	_usedTextureUnits = 0,
-
-	// GL state cache
-
-	_oldDoubleSided = -1,
-	_oldFlipSided = -1,
-
-	_oldBlending = -1,
-
-	_oldBlendEquation = -1,
-	_oldBlendSrc = -1,
-	_oldBlendDst = -1,
-
-	_oldDepthTest = -1,
-	_oldDepthWrite = -1,
-
-	_oldPolygonOffset = null,
-	_oldPolygonOffsetFactor = null,
-	_oldPolygonOffsetUnits = null,
-
-	_oldLineWidth = null,
-
-	_viewportX = 0,
-	_viewportY = 0,
-	_viewportWidth = 0,
-	_viewportHeight = 0,
-	_currentWidth = 0,
-	_currentHeight = 0,
-
-	_enabledAttributes = {},
-
-	// frustum
-
-	_frustum = new THREE.Frustum(),
-
-	 // camera matrices cache
-
-	_projScreenMatrix = new THREE.Matrix4(),
-	_projScreenMatrixPS = new THREE.Matrix4(),
-
-	_vector3 = new THREE.Vector3(),
-
-	// light arrays cache
-
-	_direction = new THREE.Vector3(),
-
-	_lightsNeedUpdate = true,
-
-	_lights = {
-
-		ambient: [ 0, 0, 0 ],
-		directional: { length: 0, colors: new Array(), positions: new Array() },
-		point: { length: 0, colors: new Array(), positions: new Array(), distances: new Array() },
-		spot: { length: 0, colors: new Array(), positions: new Array(), distances: new Array(), directions: new Array(), anglesCos: new Array(), exponents: new Array() },
-		hemi: { length: 0, skyColors: new Array(), groundColors: new Array(), positions: new Array() }
-
-	};
-
-	// initialize
-
-	var _gl;
-
-	var _glExtensionTextureFloat;
-	var _glExtensionStandardDerivatives;
-	var _glExtensionTextureFilterAnisotropic;
-	var _glExtensionCompressedTextureS3TC;
-
-	initGL();
-
-	setDefaultGLState();
-
-	this.context = _gl;
-
-	// GPU capabilities
-
-	var _maxTextures = _gl.getParameter( _gl.MAX_TEXTURE_IMAGE_UNITS );
-	var _maxVertexTextures = _gl.getParameter( _gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS );
-	var _maxTextureSize = _gl.getParameter( _gl.MAX_TEXTURE_SIZE );
-	var _maxCubemapSize = _gl.getParameter( _gl.MAX_CUBE_MAP_TEXTURE_SIZE );
-
-	var _maxAnisotropy = _glExtensionTextureFilterAnisotropic ? _gl.getParameter( _glExtensionTextureFilterAnisotropic.MAX_TEXTURE_MAX_ANISOTROPY_EXT ) : 0;
-
-	var _supportsVertexTextures = ( _maxVertexTextures > 0 );
-	var _supportsBoneTextures = _supportsVertexTextures && _glExtensionTextureFloat;
-
-	var _compressedTextureFormats = _glExtensionCompressedTextureS3TC ? _gl.getParameter( _gl.COMPRESSED_TEXTURE_FORMATS ) : [];
-
-	//
-
-	var _vertexShaderPrecisionHighpFloat = _gl.getShaderPrecisionFormat( _gl.VERTEX_SHADER, _gl.HIGH_FLOAT );
-	var _vertexShaderPrecisionMediumpFloat = _gl.getShaderPrecisionFormat( _gl.VERTEX_SHADER, _gl.MEDIUM_FLOAT );
-	var _vertexShaderPrecisionLowpFloat = _gl.getShaderPrecisionFormat( _gl.VERTEX_SHADER, _gl.LOW_FLOAT );
-
-	var _fragmentShaderPrecisionHighpFloat = _gl.getShaderPrecisionFormat( _gl.FRAGMENT_SHADER, _gl.HIGH_FLOAT );
-	var _fragmentShaderPrecisionMediumpFloat = _gl.getShaderPrecisionFormat( _gl.FRAGMENT_SHADER, _gl.MEDIUM_FLOAT );
-	var _fragmentShaderPrecisionLowpFloat = _gl.getShaderPrecisionFormat( _gl.FRAGMENT_SHADER, _gl.LOW_FLOAT );
-
-	var _vertexShaderPrecisionHighpInt = _gl.getShaderPrecisionFormat( _gl.VERTEX_SHADER, _gl.HIGH_INT );
-	var _vertexShaderPrecisionMediumpInt = _gl.getShaderPrecisionFormat( _gl.VERTEX_SHADER, _gl.MEDIUM_INT );
-	var _vertexShaderPrecisionLowpInt = _gl.getShaderPrecisionFormat( _gl.VERTEX_SHADER, _gl.LOW_INT );
-
-	var _fragmentShaderPrecisionHighpInt = _gl.getShaderPrecisionFormat( _gl.FRAGMENT_SHADER, _gl.HIGH_INT );
-	var _fragmentShaderPrecisionMediumpInt = _gl.getShaderPrecisionFormat( _gl.FRAGMENT_SHADER, _gl.MEDIUM_INT );
-	var _fragmentShaderPrecisionLowpInt = _gl.getShaderPrecisionFormat( _gl.FRAGMENT_SHADER, _gl.LOW_INT );
-
-	// clamp precision to maximum available
-
-	var highpAvailable = _vertexShaderPrecisionHighpFloat.precision > 0 && _fragmentShaderPrecisionHighpFloat.precision > 0;
-	var mediumpAvailable = _vertexShaderPrecisionMediumpFloat.precision > 0 && _fragmentShaderPrecisionMediumpFloat.precision > 0;
-
-	if ( _precision === "highp" && ! highpAvailable ) {
-
-		if ( mediumpAvailable ) {
-
-			_precision = "mediump";
-			console.warn( "WebGLRenderer: highp not supported, using mediump" );
-
-		} else {
-
-			_precision = "lowp";
-			console.warn( "WebGLRenderer: highp and mediump not supported, using lowp" );
-
-		}
-
-	}
-
-	if ( _precision === "mediump" && ! mediumpAvailable ) {
-
-		_precision = "lowp";
-		console.warn( "WebGLRenderer: mediump not supported, using lowp" );
-
-	}
-
-	// API
-
-	this.getContext = function () {
-
-		return _gl;
-
-	};
-
-	this.supportsVertexTextures = function () {
-
-		return _supportsVertexTextures;
-
-	};
-
-	this.supportsFloatTextures = function () {
-
-		return _glExtensionTextureFloat;
-
-	};
-
-	this.supportsStandardDerivatives = function () {
-
-		return _glExtensionStandardDerivatives;
-
-	};
-
-	this.supportsCompressedTextureS3TC = function () {
-
-		return _glExtensionCompressedTextureS3TC;
-
-	};
-
-	this.getMaxAnisotropy  = function () {
-
-		return _maxAnisotropy;
-
-	};
-
-	this.getPrecision = function () {
-
-		return _precision;
-
-	};
-
-	this.setSize = function ( width, height ) {
-
-		_canvas.width = width * this.devicePixelRatio;
-		_canvas.height = height * this.devicePixelRatio;
-
-		_canvas.style.width = width + 'px';
-		_canvas.style.height = height + 'px';
-
-		this.setViewport( 0, 0, _canvas.width, _canvas.height );
-
-	};
-
-	this.setViewport = function ( x, y, width, height ) {
-
-		_viewportX = x !== undefined ? x : 0;
-		_viewportY = y !== undefined ? y : 0;
-
-		_viewportWidth = width !== undefined ? width : _canvas.width;
-		_viewportHeight = height !== undefined ? height : _canvas.height;
-
-		_gl.viewport( _viewportX, _viewportY, _viewportWidth, _viewportHeight );
-
-	};
-
-	this.setScissor = function ( x, y, width, height ) {
-
-		_gl.scissor( x, y, width, height );
-
-	};
-
-	this.enableScissorTest = function ( enable ) {
-
-		enable ? _gl.enable( _gl.SCISSOR_TEST ) : _gl.disable( _gl.SCISSOR_TEST );
-
-	};
-
-	// Clearing
-
-	this.setClearColorHex = function ( hex, alpha ) {
-
-		_clearColor.setHex( hex );
-		_clearAlpha = alpha;
-
-		_gl.clearColor( _clearColor.r, _clearColor.g, _clearColor.b, _clearAlpha );
-
-	};
-
-	this.setClearColor = function ( color, alpha ) {
-
-		_clearColor.copy( color );
-		_clearAlpha = alpha;
-
-		_gl.clearColor( _clearColor.r, _clearColor.g, _clearColor.b, _clearAlpha );
-
-	};
-
-	this.getClearColor = function () {
-
-		return _clearColor;
-
-	};
-
-	this.getClearAlpha = function () {
-
-		return _clearAlpha;
-
-	};
-
-	this.clear = function ( color, depth, stencil ) {
-
-		var bits = 0;
-
-		if ( color === undefined || color ) bits |= _gl.COLOR_BUFFER_BIT;
-		if ( depth === undefined || depth ) bits |= _gl.DEPTH_BUFFER_BIT;
-		if ( stencil === undefined || stencil ) bits |= _gl.STENCIL_BUFFER_BIT;
-
-		_gl.clear( bits );
-
-	};
-
-	this.clearTarget = function ( renderTarget, color, depth, stencil ) {
-
-		this.setRenderTarget( renderTarget );
-		this.clear( color, depth, stencil );
-
-	};
-
-	// Plugins
-
-	this.addPostPlugin = function ( plugin ) {
-
-		plugin.init( this );
-		this.renderPluginsPost.push( plugin );
-
-	};
-
-	this.addPrePlugin = function ( plugin ) {
-
-		plugin.init( this );
-		this.renderPluginsPre.push( plugin );
-
-	};
-
-	// Rendering
-
-	this.updateShadowMap = function ( scene, camera ) {
-
-		_currentProgram = null;
-		_oldBlending = -1;
-		_oldDepthTest = -1;
-		_oldDepthWrite = -1;
-		_currentGeometryGroupHash = -1;
-		_currentMaterialId = -1;
-		_lightsNeedUpdate = true;
-		_oldDoubleSided = -1;
-		_oldFlipSided = -1;
-
-		this.shadowMapPlugin.update( scene, camera );
-
-	};
-
-	// Internal functions
-
-	// Buffer allocation
-
-	function createParticleBuffers ( geometry ) {
-
-		geometry.__webglVertexBuffer = _gl.createBuffer();
-		geometry.__webglColorBuffer = _gl.createBuffer();
-
-		_this.info.memory.geometries ++;
-
-	};
-
-	function createLineBuffers ( geometry ) {
-
-		geometry.__webglVertexBuffer = _gl.createBuffer();
-		geometry.__webglColorBuffer = _gl.createBuffer();
-		geometry.__webglLineDistanceBuffer = _gl.createBuffer();
-
-		_this.info.memory.geometries ++;
-
-	};
-
-	function createRibbonBuffers ( geometry ) {
-
-		geometry.__webglVertexBuffer = _gl.createBuffer();
-		geometry.__webglColorBuffer = _gl.createBuffer();
-		geometry.__webglNormalBuffer = _gl.createBuffer();
-
-		_this.info.memory.geometries ++;
-
-	};
-
-	function createMeshBuffers ( geometryGroup ) {
-
-		geometryGroup.__webglVertexBuffer = _gl.createBuffer();
-		geometryGroup.__webglNormalBuffer = _gl.createBuffer();
-		geometryGroup.__webglTangentBuffer = _gl.createBuffer();
-		geometryGroup.__webglColorBuffer = _gl.createBuffer();
-		geometryGroup.__webglUVBuffer = _gl.createBuffer();
-		geometryGroup.__webglUV2Buffer = _gl.createBuffer();
-
-		geometryGroup.__webglSkinIndicesBuffer = _gl.createBuffer();
-		geometryGroup.__webglSkinWeightsBuffer = _gl.createBuffer();
-
-		geometryGroup.__webglFaceBuffer = _gl.createBuffer();
-		geometryGroup.__webglLineBuffer = _gl.createBuffer();
-
-		var m, ml;
-
-		if ( geometryGroup.numMorphTargets ) {
-
-			geometryGroup.__webglMorphTargetsBuffers = [];
-
-			for ( m = 0, ml = geometryGroup.numMorphTargets; m < ml; m ++ ) {
-
-				geometryGroup.__webglMorphTargetsBuffers.push( _gl.createBuffer() );
-
-			}
-
-		}
-
-		if ( geometryGroup.numMorphNormals ) {
-
-			geometryGroup.__webglMorphNormalsBuffers = [];
-
-			for ( m = 0, ml = geometryGroup.numMorphNormals; m < ml; m ++ ) {
-
-				geometryGroup.__webglMorphNormalsBuffers.push( _gl.createBuffer() );
-
-			}
-
-		}
-
-		_this.info.memory.geometries ++;
-
-	};
-
-	// Events
-
-	var onGeometryDispose = function ( event ) {
-
-		var geometry = event.target;
-
-		geometry.removeEventListener( 'dispose', onGeometryDispose );
-
-		deallocateGeometry( geometry );
-
-		_this.info.memory.geometries --;
-
-	};
-
-	var onTextureDispose = function ( event ) {
-
-		var texture = event.target;
-
-		texture.removeEventListener( 'dispose', onTextureDispose );
-
-		deallocateTexture( texture );
-
-		_this.info.memory.textures --;
-
-
-	};
-
-	var onRenderTargetDispose = function ( event ) {
-
-		var renderTarget = event.target;
-
-		renderTarget.removeEventListener( 'dispose', onRenderTargetDispose );
-
-		deallocateRenderTarget( renderTarget );
-
-		_this.info.memory.textures --;
-
-	};
-
-	var onMaterialDispose = function ( event ) {
-
-		var material = event.target;
-
-		material.removeEventListener( 'dispose', onMaterialDispose );
-
-		deallocateMaterial( material );
-
-	};
-
-	// Buffer deallocation
-
-	var deallocateGeometry = function ( geometry ) {
-
-		geometry.__webglInit = undefined;
-
-		if ( geometry.__webglVertexBuffer !== undefined ) _gl.deleteBuffer( geometry.__webglVertexBuffer );
-		if ( geometry.__webglNormalBuffer !== undefined ) _gl.deleteBuffer( geometry.__webglNormalBuffer );
-		if ( geometry.__webglTangentBuffer !== undefined ) _gl.deleteBuffer( geometry.__webglTangentBuffer );
-		if ( geometry.__webglColorBuffer !== undefined ) _gl.deleteBuffer( geometry.__webglColorBuffer );
-		if ( geometry.__webglUVBuffer !== undefined ) _gl.deleteBuffer( geometry.__webglUVBuffer );
-		if ( geometry.__webglUV2Buffer !== undefined ) _gl.deleteBuffer( geometry.__webglUV2Buffer );
-
-		if ( geometry.__webglSkinIndicesBuffer !== undefined ) _gl.deleteBuffer( geometry.__webglSkinIndicesBuffer );
-		if ( geometry.__webglSkinWeightsBuffer !== undefined ) _gl.deleteBuffer( geometry.__webglSkinWeightsBuffer );
-
-		if ( geometry.__webglFaceBuffer !== undefined ) _gl.deleteBuffer( geometry.__webglFaceBuffer );
-		if ( geometry.__webglLineBuffer !== undefined ) _gl.deleteBuffer( geometry.__webglLineBuffer );
-
-		if ( geometry.__webglLineDistanceBuffer !== undefined ) _gl.deleteBuffer( geometry.__webglLineDistanceBuffer );
-
-		// geometry groups
-
-		if ( geometry.geometryGroups !== undefined ) {
-
-			for ( var g in geometry.geometryGroups ) {
-
-				var geometryGroup = geometry.geometryGroups[ g ];
-
-				if ( geometryGroup.numMorphTargets !== undefined ) {
-
-					for ( var m = 0, ml = geometryGroup.numMorphTargets; m < ml; m ++ ) {
-
-						_gl.deleteBuffer( geometryGroup.__webglMorphTargetsBuffers[ m ] );
-
-					}
-
-				}
-
-				if ( geometryGroup.numMorphNormals !== undefined ) {
-
-					for ( var m = 0, ml = geometryGroup.numMorphNormals; m < ml; m ++ ) {
-
-						_gl.deleteBuffer( geometryGroup.__webglMorphNormalsBuffers[ m ] );
-
-					}
-
-				}
-
-				deleteCustomAttributesBuffers( geometryGroup );
-
-			}
-
-		}
-
-		deleteCustomAttributesBuffers( geometry );
-
-	};
-
-	var deallocateTexture = function ( texture ) {
-
-		if ( texture.image && texture.image.__webglTextureCube ) {
-
-			// cube texture
-
-			_gl.deleteTexture( texture.image.__webglTextureCube );
-
-		} else {
-
-			// 2D texture
-
-			if ( ! texture.__webglInit ) return;
-
-			texture.__webglInit = false;
-			_gl.deleteTexture( texture.__webglTexture );
-
-		}
-
-	};
-
-	var deallocateRenderTarget = function ( renderTarget ) {
-
-		if ( !renderTarget || ! renderTarget.__webglTexture ) return;
-
-		_gl.deleteTexture( renderTarget.__webglTexture );
-
-		if ( renderTarget instanceof THREE.WebGLRenderTargetCube ) {
-
-			for ( var i = 0; i < 6; i ++ ) {
-
-				_gl.deleteFramebuffer( renderTarget.__webglFramebuffer[ i ] );
-				_gl.deleteRenderbuffer( renderTarget.__webglRenderbuffer[ i ] );
-
-			}
-
-		} else {
-
-			_gl.deleteFramebuffer( renderTarget.__webglFramebuffer );
-			_gl.deleteRenderbuffer( renderTarget.__webglRenderbuffer );
-
-		}
-
-	};
-
-	var deallocateMaterial = function ( material ) {
-
-		var program = material.program;
-
-		if ( program === undefined ) return;
-
-		material.program = undefined;
-
-		// only deallocate GL program if this was the last use of shared program
-		// assumed there is only single copy of any program in the _programs list
-		// (that's how it's constructed)
-
-		var i, il, programInfo;
-		var deleteProgram = false;
-
-		for ( i = 0, il = _programs.length; i < il; i ++ ) {
-
-			programInfo = _programs[ i ];
-
-			if ( programInfo.program === program ) {
-
-				programInfo.usedTimes --;
-
-				if ( programInfo.usedTimes === 0 ) {
-
-					deleteProgram = true;
-
-				}
-
-				break;
-
-			}
-
-		}
-
-		if ( deleteProgram === true ) {
-
-			// avoid using array.splice, this is costlier than creating new array from scratch
-
-			var newPrograms = [];
-
-			for ( i = 0, il = _programs.length; i < il; i ++ ) {
-
-				programInfo = _programs[ i ];
-
-				if ( programInfo.program !== program ) {
-
-					newPrograms.push( programInfo );
-
-				}
-
-			}
-
-			_programs = newPrograms;
-
-			_gl.deleteProgram( program );
-
-			_this.info.memory.programs --;
-
-		}
-
-	};
-
-	//
-
-	/*
-	function deleteParticleBuffers ( geometry ) {
-
-		_gl.deleteBuffer( geometry.__webglVertexBuffer );
-		_gl.deleteBuffer( geometry.__webglColorBuffer );
-
-		deleteCustomAttributesBuffers( geometry );
-
-		_this.info.memory.geometries --;
-
-	};
-
-	function deleteLineBuffers ( geometry ) {
-
-		_gl.deleteBuffer( geometry.__webglVertexBuffer );
-		_gl.deleteBuffer( geometry.__webglColorBuffer );
-		_gl.deleteBuffer( geometry.__webglLineDistanceBuffer );
-
-		deleteCustomAttributesBuffers( geometry );
-
-		_this.info.memory.geometries --;
-
-	};
-
-	function deleteRibbonBuffers ( geometry ) {
-
-		_gl.deleteBuffer( geometry.__webglVertexBuffer );
-		_gl.deleteBuffer( geometry.__webglColorBuffer );
-		_gl.deleteBuffer( geometry.__webglNormalBuffer );
-
-		deleteCustomAttributesBuffers( geometry );
-
-		_this.info.memory.geometries --;
-
-	};
-
-	function deleteMeshBuffers ( geometryGroup ) {
-
-		_gl.deleteBuffer( geometryGroup.__webglVertexBuffer );
-		_gl.deleteBuffer( geometryGroup.__webglNormalBuffer );
-		_gl.deleteBuffer( geometryGroup.__webglTangentBuffer );
-		_gl.deleteBuffer( geometryGroup.__webglColorBuffer );
-		_gl.deleteBuffer( geometryGroup.__webglUVBuffer );
-		_gl.deleteBuffer( geometryGroup.__webglUV2Buffer );
-
-		_gl.deleteBuffer( geometryGroup.__webglSkinIndicesBuffer );
-		_gl.deleteBuffer( geometryGroup.__webglSkinWeightsBuffer );
-
-		_gl.deleteBuffer( geometryGroup.__webglFaceBuffer );
-		_gl.deleteBuffer( geometryGroup.__webglLineBuffer );
-
-		var m, ml;
-
-		if ( geometryGroup.numMorphTargets ) {
-
-			for ( m = 0, ml = geometryGroup.numMorphTargets; m < ml; m ++ ) {
-
-				_gl.deleteBuffer( geometryGroup.__webglMorphTargetsBuffers[ m ] );
-
-			}
-
-		}
-
-		if ( geometryGroup.numMorphNormals ) {
-
-			for ( m = 0, ml = geometryGroup.numMorphNormals; m < ml; m ++ ) {
-
-				_gl.deleteBuffer( geometryGroup.__webglMorphNormalsBuffers[ m ] );
-
-			}
-
-		}
-
-		deleteCustomAttributesBuffers( geometryGroup );
-
-		_this.info.memory.geometries --;
-
-	};
-	*/
-
-	function deleteCustomAttributesBuffers( geometry ) {
-
-		if ( geometry.__webglCustomAttributesList ) {
-
-			for ( var id in geometry.__webglCustomAttributesList ) {
-
-				_gl.deleteBuffer( geometry.__webglCustomAttributesList[ id ].buffer );
-
-			}
-
-		}
-
-	};
-
-	// Buffer initialization
-
-	function initCustomAttributes ( geometry, object ) {
-
-		var nvertices = geometry.vertices.length;
-
-		var material = object.material;
-
-		if ( material.attributes ) {
-
-			if ( geometry.__webglCustomAttributesList === undefined ) {
-
-				geometry.__webglCustomAttributesList = [];
-
-			}
-
-			for ( var a in material.attributes ) {
-
-				var attribute = material.attributes[ a ];
-
-				if ( !attribute.__webglInitialized || attribute.createUniqueBuffers ) {
-
-					attribute.__webglInitialized = true;
-
-					var size = 1;		// "f" and "i"
-
-					if ( attribute.type === "v2" ) size = 2;
-					else if ( attribute.type === "v3" ) size = 3;
-					else if ( attribute.type === "v4" ) size = 4;
-					else if ( attribute.type === "c"  ) size = 3;
-
-					attribute.size = size;
-
-					attribute.array = new Float32Array( nvertices * size );
-
-					attribute.buffer = _gl.createBuffer();
-					attribute.buffer.belongsToAttribute = a;
-
-					attribute.needsUpdate = true;
-
-				}
-
-				geometry.__webglCustomAttributesList.push( attribute );
-
-			}
-
-		}
-
-	};
-
-	function initParticleBuffers ( geometry, object ) {
-
-		var nvertices = geometry.vertices.length;
-
-		geometry.__vertexArray = new Float32Array( nvertices * 3 );
-		geometry.__colorArray = new Float32Array( nvertices * 3 );
-
-		geometry.__sortArray = [];
-
-		geometry.__webglParticleCount = nvertices;
-
-		initCustomAttributes ( geometry, object );
-
-	};
-
-	function initLineBuffers ( geometry, object ) {
-
-		var nvertices = geometry.vertices.length;
-
-		geometry.__vertexArray = new Float32Array( nvertices * 3 );
-		geometry.__colorArray = new Float32Array( nvertices * 3 );
-		geometry.__lineDistanceArray = new Float32Array( nvertices * 1 );
-
-		geometry.__webglLineCount = nvertices;
-
-		initCustomAttributes ( geometry, object );
-
-	};
-
-	function initRibbonBuffers ( geometry, object ) {
-
-		var nvertices = geometry.vertices.length;
-
-		geometry.__vertexArray = new Float32Array( nvertices * 3 );
-		geometry.__colorArray = new Float32Array( nvertices * 3 );
-		geometry.__normalArray = new Float32Array( nvertices * 3 );
-
-		geometry.__webglVertexCount = nvertices;
-
-		initCustomAttributes ( geometry, object );
-
-	};
-
-	function initMeshBuffers ( geometryGroup, object ) {
-
-		var geometry = object.geometry,
-			faces3 = geometryGroup.faces3,
-			faces4 = geometryGroup.faces4,
-
-			nvertices = faces3.length * 3 + faces4.length * 4,
-			ntris     = faces3.length * 1 + faces4.length * 2,
-			nlines    = faces3.length * 3 + faces4.length * 4,
-
-			material = getBufferMaterial( object, geometryGroup ),
-
-			uvType = bufferGuessUVType( material ),
-			normalType = bufferGuessNormalType( material ),
-			vertexColorType = bufferGuessVertexColorType( material );
-
-		//console.log( "uvType", uvType, "normalType", normalType, "vertexColorType", vertexColorType, object, geometryGroup, material );
-
-		geometryGroup.__vertexArray = new Float32Array( nvertices * 3 );
-
-		if ( normalType ) {
-
-			geometryGroup.__normalArray = new Float32Array( nvertices * 3 );
-
-		}
-
-		if ( geometry.hasTangents ) {
-
-			geometryGroup.__tangentArray = new Float32Array( nvertices * 4 );
-
-		}
-
-		if ( vertexColorType ) {
-
-			geometryGroup.__colorArray = new Float32Array( nvertices * 3 );
-
-		}
-
-		if ( uvType ) {
-
-			if ( geometry.faceUvs.length > 0 || geometry.faceVertexUvs.length > 0 ) {
-
-				geometryGroup.__uvArray = new Float32Array( nvertices * 2 );
-
-			}
-
-			if ( geometry.faceUvs.length > 1 || geometry.faceVertexUvs.length > 1 ) {
-
-				geometryGroup.__uv2Array = new Float32Array( nvertices * 2 );
-
-			}
-
-		}
-
-		if ( object.geometry.skinWeights.length && object.geometry.skinIndices.length ) {
-
-			geometryGroup.__skinIndexArray = new Float32Array( nvertices * 4 );
-			geometryGroup.__skinWeightArray = new Float32Array( nvertices * 4 );
-
-		}
-
-		geometryGroup.__faceArray = new Uint16Array( ntris * 3 );
-		geometryGroup.__lineArray = new Uint16Array( nlines * 2 );
-
-		var m, ml;
-
-		if ( geometryGroup.numMorphTargets ) {
-
-			geometryGroup.__morphTargetsArrays = [];
-
-			for ( m = 0, ml = geometryGroup.numMorphTargets; m < ml; m ++ ) {
-
-				geometryGroup.__morphTargetsArrays.push( new Float32Array( nvertices * 3 ) );
-
-			}
-
-		}
-
-		if ( geometryGroup.numMorphNormals ) {
-
-			geometryGroup.__morphNormalsArrays = [];
-
-			for ( m = 0, ml = geometryGroup.numMorphNormals; m < ml; m ++ ) {
-
-				geometryGroup.__morphNormalsArrays.push( new Float32Array( nvertices * 3 ) );
-
-			}
-
-		}
-
-		geometryGroup.__webglFaceCount = ntris * 3;
-		geometryGroup.__webglLineCount = nlines * 2;
-
-
-		// custom attributes
-
-		if ( material.attributes ) {
-
-			if ( geometryGroup.__webglCustomAttributesList === undefined ) {
-
-				geometryGroup.__webglCustomAttributesList = [];
-
-			}
-
-			for ( var a in material.attributes ) {
-
-				// Do a shallow copy of the attribute object so different geometryGroup chunks use different
-				// attribute buffers which are correctly indexed in the setMeshBuffers function
-
-				var originalAttribute = material.attributes[ a ];
-
-				var attribute = {};
-
-				for ( var property in originalAttribute ) {
-
-					attribute[ property ] = originalAttribute[ property ];
-
-				}
-
-				if ( !attribute.__webglInitialized || attribute.createUniqueBuffers ) {
-
-					attribute.__webglInitialized = true;
-
-					var size = 1;		// "f" and "i"
-
-					if( attribute.type === "v2" ) size = 2;
-					else if( attribute.type === "v3" ) size = 3;
-					else if( attribute.type === "v4" ) size = 4;
-					else if( attribute.type === "c"  ) size = 3;
-
-					attribute.size = size;
-
-					attribute.array = new Float32Array( nvertices * size );
-
-					attribute.buffer = _gl.createBuffer();
-					attribute.buffer.belongsToAttribute = a;
-
-					originalAttribute.needsUpdate = true;
-					attribute.__original = originalAttribute;
-
-				}
-
-				geometryGroup.__webglCustomAttributesList.push( attribute );
-
-			}
-
-		}
-
-		geometryGroup.__inittedArrays = true;
-
-	};
-
-	function getBufferMaterial( object, geometryGroup ) {
-
-		return object.material instanceof THREE.MeshFaceMaterial
-			? object.material.materials[ geometryGroup.materialIndex ]
-			: object.material;
-
-	};
-
-	function materialNeedsSmoothNormals ( material ) {
-
-		return material && material.shading !== undefined && material.shading === THREE.SmoothShading;
-
-	};
-
-	function bufferGuessNormalType ( material ) {
-
-		// only MeshBasicMaterial and MeshDepthMaterial don't need normals
-
-		if ( ( material instanceof THREE.MeshBasicMaterial && !material.envMap ) || material instanceof THREE.MeshDepthMaterial ) {
-
-			return false;
-
-		}
-
-		if ( materialNeedsSmoothNormals( material ) ) {
-
-			return THREE.SmoothShading;
-
-		} else {
-
-			return THREE.FlatShading;
-
-		}
-
-	};
-
-	function bufferGuessVertexColorType ( material ) {
-
-		if ( material.vertexColors ) {
-
-			return material.vertexColors;
-
-		}
-
-		return false;
-
-	};
-
-	function bufferGuessUVType ( material ) {
-
-		// material must use some texture to require uvs
-
-		if ( material.map || material.lightMap || material.bumpMap || material.normalMap || material.specularMap || material instanceof THREE.ShaderMaterial ) {
-
-			return true;
-
-		}
-
-		return false;
-
-	};
-
-	//
-
-	function initDirectBuffers( geometry ) {
-
-		var a, attribute, type;
-
-		for ( a in geometry.attributes ) {
-
-			if ( a === "index" ) {
-
-				type = _gl.ELEMENT_ARRAY_BUFFER;
-
-			} else {
-
-				type = _gl.ARRAY_BUFFER;
-
-			}
-
-			attribute = geometry.attributes[ a ];
-
-			attribute.buffer = _gl.createBuffer();
-
-			_gl.bindBuffer( type, attribute.buffer );
-			_gl.bufferData( type, attribute.array, _gl.STATIC_DRAW );
-
-		}
-
-	};
-
-	// Buffer setting
-
-	function setParticleBuffers ( geometry, hint, object ) {
-
-		var v, c, vertex, offset, index, color,
-
-		vertices = geometry.vertices,
-		vl = vertices.length,
-
-		colors = geometry.colors,
-		cl = colors.length,
-
-		vertexArray = geometry.__vertexArray,
-		colorArray = geometry.__colorArray,
-
-		sortArray = geometry.__sortArray,
-
-		dirtyVertices = geometry.verticesNeedUpdate,
-		dirtyElements = geometry.elementsNeedUpdate,
-		dirtyColors = geometry.colorsNeedUpdate,
-
-		customAttributes = geometry.__webglCustomAttributesList,
-		i, il,
-		a, ca, cal, value,
-		customAttribute;
-
-		if ( object.sortParticles ) {
-
-			_projScreenMatrixPS.copy( _projScreenMatrix );
-			_projScreenMatrixPS.multiply( object.matrixWorld );
-
-			for ( v = 0; v < vl; v ++ ) {
-
-				vertex = vertices[ v ];
-
-				_vector3.copy( vertex );
-				_vector3.applyProjection( _projScreenMatrixPS );
-
-				sortArray[ v ] = [ _vector3.z, v ];
-
-			}
-
-			sortArray.sort( numericalSort );
-
-			for ( v = 0; v < vl; v ++ ) {
-
-				vertex = vertices[ sortArray[v][1] ];
-
-				offset = v * 3;
-
-				vertexArray[ offset ]     = vertex.x;
-				vertexArray[ offset + 1 ] = vertex.y;
-				vertexArray[ offset + 2 ] = vertex.z;
-
-			}
-
-			for ( c = 0; c < cl; c ++ ) {
-
-				offset = c * 3;
-
-				color = colors[ sortArray[c][1] ];
-
-				colorArray[ offset ]     = color.r;
-				colorArray[ offset + 1 ] = color.g;
-				colorArray[ offset + 2 ] = color.b;
-
-			}
-
-			if ( customAttributes ) {
-
-				for ( i = 0, il = customAttributes.length; i < il; i ++ ) {
-
-					customAttribute = customAttributes[ i ];
-
-					if ( ! ( customAttribute.boundTo === undefined || customAttribute.boundTo === "vertices" ) ) continue;
-
-					offset = 0;
-
-					cal = customAttribute.value.length;
-
-					if ( customAttribute.size === 1 ) {
-
-						for ( ca = 0; ca < cal; ca ++ ) {
-
-							index = sortArray[ ca ][ 1 ];
-
-							customAttribute.array[ ca ] = customAttribute.value[ index ];
-
-						}
-
-					} else if ( customAttribute.size === 2 ) {
-
-						for ( ca = 0; ca < cal; ca ++ ) {
-
-							index = sortArray[ ca ][ 1 ];
-
-							value = customAttribute.value[ index ];
-
-							customAttribute.array[ offset ] 	= value.x;
-							customAttribute.array[ offset + 1 ] = value.y;
-
-							offset += 2;
-
-						}
-
-					} else if ( customAttribute.size === 3 ) {
-
-						if ( customAttribute.type === "c" ) {
-
-							for ( ca = 0; ca < cal; ca ++ ) {
-
-								index = sortArray[ ca ][ 1 ];
-
-								value = customAttribute.value[ index ];
-
-								customAttribute.array[ offset ]     = value.r;
-								customAttribute.array[ offset + 1 ] = value.g;
-								customAttribute.array[ offset + 2 ] = value.b;
-
-								offset += 3;
-
-							}
-
-						} else {
-
-							for ( ca = 0; ca < cal; ca ++ ) {
-
-								index = sortArray[ ca ][ 1 ];
-
-								value = customAttribute.value[ index ];
-
-								customAttribute.array[ offset ] 	= value.x;
-								customAttribute.array[ offset + 1 ] = value.y;
-								customAttribute.array[ offset + 2 ] = value.z;
-
-								offset += 3;
-
-							}
-
-						}
-
-					} else if ( customAttribute.size === 4 ) {
-
-						for ( ca = 0; ca < cal; ca ++ ) {
-
-							index = sortArray[ ca ][ 1 ];
-
-							value = customAttribute.value[ index ];
-
-							customAttribute.array[ offset ]      = value.x;
-							customAttribute.array[ offset + 1  ] = value.y;
-							customAttribute.array[ offset + 2  ] = value.z;
-							customAttribute.array[ offset + 3  ] = value.w;
-
-							offset += 4;
-
-						}
-
-					}
-
-				}
-
-			}
-
-		} else {
-
-			if ( dirtyVertices ) {
-
-				for ( v = 0; v < vl; v ++ ) {
-
-					vertex = vertices[ v ];
-
-					offset = v * 3;
-
-					vertexArray[ offset ]     = vertex.x;
-					vertexArray[ offset + 1 ] = vertex.y;
-					vertexArray[ offset + 2 ] = vertex.z;
-
-				}
-
-			}
-
-			if ( dirtyColors ) {
-
-				for ( c = 0; c < cl; c ++ ) {
-
-					color = colors[ c ];
-
-					offset = c * 3;
-
-					colorArray[ offset ]     = color.r;
-					colorArray[ offset + 1 ] = color.g;
-					colorArray[ offset + 2 ] = color.b;
-
-				}
-
-			}
-
-			if ( customAttributes ) {
-
-				for ( i = 0, il = customAttributes.length; i < il; i ++ ) {
-
-					customAttribute = customAttributes[ i ];
-
-					if ( customAttribute.needsUpdate &&
-						 ( customAttribute.boundTo === undefined ||
-						   customAttribute.boundTo === "vertices") ) {
-
-						cal = customAttribute.value.length;
-
-						offset = 0;
-
-						if ( customAttribute.size === 1 ) {
-
-							for ( ca = 0; ca < cal; ca ++ ) {
-
-								customAttribute.array[ ca ] = customAttribute.value[ ca ];
-
-							}
-
-						} else if ( customAttribute.size === 2 ) {
-
-							for ( ca = 0; ca < cal; ca ++ ) {
-
-								value = customAttribute.value[ ca ];
-
-								customAttribute.array[ offset ] 	= value.x;
-								customAttribute.array[ offset + 1 ] = value.y;
-
-								offset += 2;
-
-							}
-
-						} else if ( customAttribute.size === 3 ) {
-
-							if ( customAttribute.type === "c" ) {
-
-								for ( ca = 0; ca < cal; ca ++ ) {
-
-									value = customAttribute.value[ ca ];
-
-									customAttribute.array[ offset ] 	= value.r;
-									customAttribute.array[ offset + 1 ] = value.g;
-									customAttribute.array[ offset + 2 ] = value.b;
-
-									offset += 3;
-
-								}
-
-							} else {
-
-								for ( ca = 0; ca < cal; ca ++ ) {
-
-									value = customAttribute.value[ ca ];
-
-									customAttribute.array[ offset ] 	= value.x;
-									customAttribute.array[ offset + 1 ] = value.y;
-									customAttribute.array[ offset + 2 ] = value.z;
-
-									offset += 3;
-
-								}
-
-							}
-
-						} else if ( customAttribute.size === 4 ) {
-
-							for ( ca = 0; ca < cal; ca ++ ) {
-
-								value = customAttribute.value[ ca ];
-
-								customAttribute.array[ offset ]      = value.x;
-								customAttribute.array[ offset + 1  ] = value.y;
-								customAttribute.array[ offset + 2  ] = value.z;
-								customAttribute.array[ offset + 3  ] = value.w;
-
-								offset += 4;
-
-							}
-
-						}
-
-					}
-
-				}
-
-			}
-
-		}
-
-		if ( dirtyVertices || object.sortParticles ) {
-
-			_gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webglVertexBuffer );
-			_gl.bufferData( _gl.ARRAY_BUFFER, vertexArray, hint );
-
-		}
-
-		if ( dirtyColors || object.sortParticles ) {
-
-			_gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webglColorBuffer );
-			_gl.bufferData( _gl.ARRAY_BUFFER, colorArray, hint );
-
-		}
-
-		if ( customAttributes ) {
-
-			for ( i = 0, il = customAttributes.length; i < il; i ++ ) {
-
-				customAttribute = customAttributes[ i ];
-
-				if ( customAttribute.needsUpdate || object.sortParticles ) {
-
-					_gl.bindBuffer( _gl.ARRAY_BUFFER, customAttribute.buffer );
-					_gl.bufferData( _gl.ARRAY_BUFFER, customAttribute.array, hint );
-
-				}
-
-			}
-
-		}
-
-
-	};
-
-	function setLineBuffers ( geometry, hint ) {
-
-		var v, c, d, vertex, offset, color,
-
-		vertices = geometry.vertices,
-		colors = geometry.colors,
-		lineDistances = geometry.lineDistances,
-
-		vl = vertices.length,
-		cl = colors.length,
-		dl = lineDistances.length,
-
-		vertexArray = geometry.__vertexArray,
-		colorArray = geometry.__colorArray,
-		lineDistanceArray = geometry.__lineDistanceArray,
-
-		dirtyVertices = geometry.verticesNeedUpdate,
-		dirtyColors = geometry.colorsNeedUpdate,
-		dirtyLineDistances = geometry.lineDistancesNeedUpdate,
-
-		customAttributes = geometry.__webglCustomAttributesList,
-
-		i, il,
-		a, ca, cal, value,
-		customAttribute;
-
-		if ( dirtyVertices ) {
-
-			for ( v = 0; v < vl; v ++ ) {
-
-				vertex = vertices[ v ];
-
-				offset = v * 3;
-
-				vertexArray[ offset ]     = vertex.x;
-				vertexArray[ offset + 1 ] = vertex.y;
-				vertexArray[ offset + 2 ] = vertex.z;
-
-			}
-
-			_gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webglVertexBuffer );
-			_gl.bufferData( _gl.ARRAY_BUFFER, vertexArray, hint );
-
-		}
-
-		if ( dirtyColors ) {
-
-			for ( c = 0; c < cl; c ++ ) {
-
-				color = colors[ c ];
-
-				offset = c * 3;
-
-				colorArray[ offset ]     = color.r;
-				colorArray[ offset + 1 ] = color.g;
-				colorArray[ offset + 2 ] = color.b;
-
-			}
-
-			_gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webglColorBuffer );
-			_gl.bufferData( _gl.ARRAY_BUFFER, colorArray, hint );
-
-		}
-
-		if ( dirtyLineDistances ) {
-
-			for ( d = 0; d < dl; d ++ ) {
-
-				lineDistanceArray[ d ] = lineDistances[ d ];
-
-			}
-
-			_gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webglLineDistanceBuffer );
-			_gl.bufferData( _gl.ARRAY_BUFFER, lineDistanceArray, hint );
-
-		}
-
-		if ( customAttributes ) {
-
-			for ( i = 0, il = customAttributes.length; i < il; i ++ ) {
-
-				customAttribute = customAttributes[ i ];
-
-				if ( customAttribute.needsUpdate &&
-					 ( customAttribute.boundTo === undefined ||
-					   customAttribute.boundTo === "vertices" ) ) {
-
-					offset = 0;
-
-					cal = customAttribute.value.length;
-
-					if ( customAttribute.size === 1 ) {
-
-						for ( ca = 0; ca < cal; ca ++ ) {
-
-							customAttribute.array[ ca ] = customAttribute.value[ ca ];
-
-						}
-
-					} else if ( customAttribute.size === 2 ) {
-
-						for ( ca = 0; ca < cal; ca ++ ) {
-
-							value = customAttribute.value[ ca ];
-
-							customAttribute.array[ offset ] 	= value.x;
-							customAttribute.array[ offset + 1 ] = value.y;
-
-							offset += 2;
-
-						}
-
-					} else if ( customAttribute.size === 3 ) {
-
-						if ( customAttribute.type === "c" ) {
-
-							for ( ca = 0; ca < cal; ca ++ ) {
-
-								value = customAttribute.value[ ca ];
-
-								customAttribute.array[ offset ] 	= value.r;
-								customAttribute.array[ offset + 1 ] = value.g;
-								customAttribute.array[ offset + 2 ] = value.b;
-
-								offset += 3;
-
-							}
-
-						} else {
-
-							for ( ca = 0; ca < cal; ca ++ ) {
-
-								value = customAttribute.value[ ca ];
-
-								customAttribute.array[ offset ] 	= value.x;
-								customAttribute.array[ offset + 1 ] = value.y;
-								customAttribute.array[ offset + 2 ] = value.z;
-
-								offset += 3;
-
-							}
-
-						}
-
-					} else if ( customAttribute.size === 4 ) {
-
-						for ( ca = 0; ca < cal; ca ++ ) {
-
-							value = customAttribute.value[ ca ];
-
-							customAttribute.array[ offset ] 	 = value.x;
-							customAttribute.array[ offset + 1  ] = value.y;
-							customAttribute.array[ offset + 2  ] = value.z;
-							customAttribute.array[ offset + 3  ] = value.w;
-
-							offset += 4;
-
-						}
-
-					}
-
-					_gl.bindBuffer( _gl.ARRAY_BUFFER, customAttribute.buffer );
-					_gl.bufferData( _gl.ARRAY_BUFFER, customAttribute.array, hint );
-
-				}
-
-			}
-
-		}
-
-	};
-
-	function setRibbonBuffers ( geometry, hint ) {
-
-		var v, c, n, vertex, offset, color, normal,
-
-		i, il, ca, cal, customAttribute, value,
-
-		vertices = geometry.vertices,
-		colors = geometry.colors,
-		normals = geometry.normals,
-
-		vl = vertices.length,
-		cl = colors.length,
-		nl = normals.length,
-
-		vertexArray = geometry.__vertexArray,
-		colorArray = geometry.__colorArray,
-		normalArray = geometry.__normalArray,
-
-		dirtyVertices = geometry.verticesNeedUpdate,
-		dirtyColors = geometry.colorsNeedUpdate,
-		dirtyNormals = geometry.normalsNeedUpdate,
-
-		customAttributes = geometry.__webglCustomAttributesList;
-
-		if ( dirtyVertices ) {
-
-			for ( v = 0; v < vl; v ++ ) {
-
-				vertex = vertices[ v ];
-
-				offset = v * 3;
-
-				vertexArray[ offset ]     = vertex.x;
-				vertexArray[ offset + 1 ] = vertex.y;
-				vertexArray[ offset + 2 ] = vertex.z;
-
-			}
-
-			_gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webglVertexBuffer );
-			_gl.bufferData( _gl.ARRAY_BUFFER, vertexArray, hint );
-
-		}
-
-		if ( dirtyColors ) {
-
-			for ( c = 0; c < cl; c ++ ) {
-
-				color = colors[ c ];
-
-				offset = c * 3;
-
-				colorArray[ offset ]     = color.r;
-				colorArray[ offset + 1 ] = color.g;
-				colorArray[ offset + 2 ] = color.b;
-
-			}
-
-			_gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webglColorBuffer );
-			_gl.bufferData( _gl.ARRAY_BUFFER, colorArray, hint );
-
-		}
-
-		if ( dirtyNormals ) {
-
-			for ( n = 0; n < nl; n ++ ) {
-
-				normal = normals[ n ];
-
-				offset = n * 3;
-
-				normalArray[ offset ]     = normal.x;
-				normalArray[ offset + 1 ] = normal.y;
-				normalArray[ offset + 2 ] = normal.z;
-
-			}
-
-			_gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webglNormalBuffer );
-			_gl.bufferData( _gl.ARRAY_BUFFER, normalArray, hint );
-
-		}
-
-		if ( customAttributes ) {
-
-			for ( i = 0, il = customAttributes.length; i < il; i ++ ) {
-
-				customAttribute = customAttributes[ i ];
-
-				if ( customAttribute.needsUpdate &&
-					 ( customAttribute.boundTo === undefined ||
-					   customAttribute.boundTo === "vertices" ) ) {
-
-					offset = 0;
-
-					cal = customAttribute.value.length;
-
-					if ( customAttribute.size === 1 ) {
-
-						for ( ca = 0; ca < cal; ca ++ ) {
-
-							customAttribute.array[ ca ] = customAttribute.value[ ca ];
-
-						}
-
-					} else if ( customAttribute.size === 2 ) {
-
-						for ( ca = 0; ca < cal; ca ++ ) {
-
-							value = customAttribute.value[ ca ];
-
-							customAttribute.array[ offset ] 	= value.x;
-							customAttribute.array[ offset + 1 ] = value.y;
-
-							offset += 2;
-
-						}
-
-					} else if ( customAttribute.size === 3 ) {
-
-						if ( customAttribute.type === "c" ) {
-
-							for ( ca = 0; ca < cal; ca ++ ) {
-
-								value = customAttribute.value[ ca ];
-
-								customAttribute.array[ offset ] 	= value.r;
-								customAttribute.array[ offset + 1 ] = value.g;
-								customAttribute.array[ offset + 2 ] = value.b;
-
-								offset += 3;
-
-							}
-
-						} else {
-
-							for ( ca = 0; ca < cal; ca ++ ) {
-
-								value = customAttribute.value[ ca ];
-
-								customAttribute.array[ offset ] 	= value.x;
-								customAttribute.array[ offset + 1 ] = value.y;
-								customAttribute.array[ offset + 2 ] = value.z;
-
-								offset += 3;
-
-							}
-
-						}
-
-					} else if ( customAttribute.size === 4 ) {
-
-						for ( ca = 0; ca < cal; ca ++ ) {
-
-							value = customAttribute.value[ ca ];
-
-							customAttribute.array[ offset ] 	 = value.x;
-							customAttribute.array[ offset + 1  ] = value.y;
-							customAttribute.array[ offset + 2  ] = value.z;
-							customAttribute.array[ offset + 3  ] = value.w;
-
-							offset += 4;
-
-						}
-
-					}
-
-					_gl.bindBuffer( _gl.ARRAY_BUFFER, customAttribute.buffer );
-					_gl.bufferData( _gl.ARRAY_BUFFER, customAttribute.array, hint );
-
-				}
-
-			}
-
-		}
-
-	};
-
-	function setMeshBuffers( geometryGroup, object, hint, dispose, material ) {
-
-		if ( ! geometryGroup.__inittedArrays ) {
-
-			return;
-
-		}
-
-		var normalType = bufferGuessNormalType( material ),
-		vertexColorType = bufferGuessVertexColorType( material ),
-		uvType = bufferGuessUVType( material ),
-
-		needsSmoothNormals = ( normalType === THREE.SmoothShading );
-
-		var f, fl, fi, face,
-		vertexNormals, faceNormal, normal,
-		vertexColors, faceColor,
-		vertexTangents,
-		uv, uv2, v1, v2, v3, v4, t1, t2, t3, t4, n1, n2, n3, n4,
-		c1, c2, c3, c4,
-		sw1, sw2, sw3, sw4,
-		si1, si2, si3, si4,
-		sa1, sa2, sa3, sa4,
-		sb1, sb2, sb3, sb4,
-		m, ml, i, il,
-		vn, uvi, uv2i,
-		vk, vkl, vka,
-		nka, chf, faceVertexNormals,
-		a,
-
-		vertexIndex = 0,
-
-		offset = 0,
-		offset_uv = 0,
-		offset_uv2 = 0,
-		offset_face = 0,
-		offset_normal = 0,
-		offset_tangent = 0,
-		offset_line = 0,
-		offset_color = 0,
-		offset_skin = 0,
-		offset_morphTarget = 0,
-		offset_custom = 0,
-		offset_customSrc = 0,
-
-		value,
-
-		vertexArray = geometryGroup.__vertexArray,
-		uvArray = geometryGroup.__uvArray,
-		uv2Array = geometryGroup.__uv2Array,
-		normalArray = geometryGroup.__normalArray,
-		tangentArray = geometryGroup.__tangentArray,
-		colorArray = geometryGroup.__colorArray,
-
-		skinIndexArray = geometryGroup.__skinIndexArray,
-		skinWeightArray = geometryGroup.__skinWeightArray,
-
-		morphTargetsArrays = geometryGroup.__morphTargetsArrays,
-		morphNormalsArrays = geometryGroup.__morphNormalsArrays,
-
-		customAttributes = geometryGroup.__webglCustomAttributesList,
-		customAttribute,
-
-		faceArray = geometryGroup.__faceArray,
-		lineArray = geometryGroup.__lineArray,
-
-		geometry = object.geometry, // this is shared for all chunks
-
-		dirtyVertices = geometry.verticesNeedUpdate,
-		dirtyElements = geometry.elementsNeedUpdate,
-		dirtyUvs = geometry.uvsNeedUpdate,
-		dirtyNormals = geometry.normalsNeedUpdate,
-		dirtyTangents = geometry.tangentsNeedUpdate,
-		dirtyColors = geometry.colorsNeedUpdate,
-		dirtyMorphTargets = geometry.morphTargetsNeedUpdate,
-
-		vertices = geometry.vertices,
-		chunk_faces3 = geometryGroup.faces3,
-		chunk_faces4 = geometryGroup.faces4,
-		obj_faces = geometry.faces,
-
-		obj_uvs  = geometry.faceVertexUvs[ 0 ],
-		obj_uvs2 = geometry.faceVertexUvs[ 1 ],
-
-		obj_colors = geometry.colors,
-
-		obj_skinIndices = geometry.skinIndices,
-		obj_skinWeights = geometry.skinWeights,
-
-		morphTargets = geometry.morphTargets,
-		morphNormals = geometry.morphNormals;
-
-		if ( dirtyVertices ) {
-
-			for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
-
-				face = obj_faces[ chunk_faces3[ f ] ];
-
-				v1 = vertices[ face.a ];
-				v2 = vertices[ face.b ];
-				v3 = vertices[ face.c ];
-
-				vertexArray[ offset ]     = v1.x;
-				vertexArray[ offset + 1 ] = v1.y;
-				vertexArray[ offset + 2 ] = v1.z;
-
-				vertexArray[ offset + 3 ] = v2.x;
-				vertexArray[ offset + 4 ] = v2.y;
-				vertexArray[ offset + 5 ] = v2.z;
-
-				vertexArray[ offset + 6 ] = v3.x;
-				vertexArray[ offset + 7 ] = v3.y;
-				vertexArray[ offset + 8 ] = v3.z;
-
-				offset += 9;
-
-			}
-
-			for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
-
-				face = obj_faces[ chunk_faces4[ f ] ];
-
-				v1 = vertices[ face.a ];
-				v2 = vertices[ face.b ];
-				v3 = vertices[ face.c ];
-				v4 = vertices[ face.d ];
-
-				vertexArray[ offset ]     = v1.x;
-				vertexArray[ offset + 1 ] = v1.y;
-				vertexArray[ offset + 2 ] = v1.z;
-
-				vertexArray[ offset + 3 ] = v2.x;
-				vertexArray[ offset + 4 ] = v2.y;
-				vertexArray[ offset + 5 ] = v2.z;
-
-				vertexArray[ offset + 6 ] = v3.x;
-				vertexArray[ offset + 7 ] = v3.y;
-				vertexArray[ offset + 8 ] = v3.z;
-
-				vertexArray[ offset + 9 ]  = v4.x;
-				vertexArray[ offset + 10 ] = v4.y;
-				vertexArray[ offset + 11 ] = v4.z;
-
-				offset += 12;
-
-			}
-
-			_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglVertexBuffer );
-			_gl.bufferData( _gl.ARRAY_BUFFER, vertexArray, hint );
-
-		}
-
-		if ( dirtyMorphTargets ) {
-
-			for ( vk = 0, vkl = morphTargets.length; vk < vkl; vk ++ ) {
-
-				offset_morphTarget = 0;
-
-				for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
-
-					chf = chunk_faces3[ f ];
-					face = obj_faces[ chf ];
-
-					// morph positions
-
-					v1 = morphTargets[ vk ].vertices[ face.a ];
-					v2 = morphTargets[ vk ].vertices[ face.b ];
-					v3 = morphTargets[ vk ].vertices[ face.c ];
-
-					vka = morphTargetsArrays[ vk ];
-
-					vka[ offset_morphTarget ] 	  = v1.x;
-					vka[ offset_morphTarget + 1 ] = v1.y;
-					vka[ offset_morphTarget + 2 ] = v1.z;
-
-					vka[ offset_morphTarget + 3 ] = v2.x;
-					vka[ offset_morphTarget + 4 ] = v2.y;
-					vka[ offset_morphTarget + 5 ] = v2.z;
-
-					vka[ offset_morphTarget + 6 ] = v3.x;
-					vka[ offset_morphTarget + 7 ] = v3.y;
-					vka[ offset_morphTarget + 8 ] = v3.z;
-
-					// morph normals
-
-					if ( material.morphNormals ) {
-
-						if ( needsSmoothNormals ) {
-
-							faceVertexNormals = morphNormals[ vk ].vertexNormals[ chf ];
-
-							n1 = faceVertexNormals.a;
-							n2 = faceVertexNormals.b;
-							n3 = faceVertexNormals.c;
-
-						} else {
-
-							n1 = morphNormals[ vk ].faceNormals[ chf ];
-							n2 = n1;
-							n3 = n1;
-
-						}
-
-						nka = morphNormalsArrays[ vk ];
-
-						nka[ offset_morphTarget ] 	  = n1.x;
-						nka[ offset_morphTarget + 1 ] = n1.y;
-						nka[ offset_morphTarget + 2 ] = n1.z;
-
-						nka[ offset_morphTarget + 3 ] = n2.x;
-						nka[ offset_morphTarget + 4 ] = n2.y;
-						nka[ offset_morphTarget + 5 ] = n2.z;
-
-						nka[ offset_morphTarget + 6 ] = n3.x;
-						nka[ offset_morphTarget + 7 ] = n3.y;
-						nka[ offset_morphTarget + 8 ] = n3.z;
-
-					}
-
-					//
-
-					offset_morphTarget += 9;
-
-				}
-
-				for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
-
-					chf = chunk_faces4[ f ];
-					face = obj_faces[ chf ];
-
-					// morph positions
-
-					v1 = morphTargets[ vk ].vertices[ face.a ];
-					v2 = morphTargets[ vk ].vertices[ face.b ];
-					v3 = morphTargets[ vk ].vertices[ face.c ];
-					v4 = morphTargets[ vk ].vertices[ face.d ];
-
-					vka = morphTargetsArrays[ vk ];
-
-					vka[ offset_morphTarget ] 	  = v1.x;
-					vka[ offset_morphTarget + 1 ] = v1.y;
-					vka[ offset_morphTarget + 2 ] = v1.z;
-
-					vka[ offset_morphTarget + 3 ] = v2.x;
-					vka[ offset_morphTarget + 4 ] = v2.y;
-					vka[ offset_morphTarget + 5 ] = v2.z;
-
-					vka[ offset_morphTarget + 6 ] = v3.x;
-					vka[ offset_morphTarget + 7 ] = v3.y;
-					vka[ offset_morphTarget + 8 ] = v3.z;
-
-					vka[ offset_morphTarget + 9 ]  = v4.x;
-					vka[ offset_morphTarget + 10 ] = v4.y;
-					vka[ offset_morphTarget + 11 ] = v4.z;
-
-					// morph normals
-
-					if ( material.morphNormals ) {
-
-						if ( needsSmoothNormals ) {
-
-							faceVertexNormals = morphNormals[ vk ].vertexNormals[ chf ];
-
-							n1 = faceVertexNormals.a;
-							n2 = faceVertexNormals.b;
-							n3 = faceVertexNormals.c;
-							n4 = faceVertexNormals.d;
-
-						} else {
-
-							n1 = morphNormals[ vk ].faceNormals[ chf ];
-							n2 = n1;
-							n3 = n1;
-							n4 = n1;
-
-						}
-
-						nka = morphNormalsArrays[ vk ];
-
-						nka[ offset_morphTarget ] 	  = n1.x;
-						nka[ offset_morphTarget + 1 ] = n1.y;
-						nka[ offset_morphTarget + 2 ] = n1.z;
-
-						nka[ offset_morphTarget + 3 ] = n2.x;
-						nka[ offset_morphTarget + 4 ] = n2.y;
-						nka[ offset_morphTarget + 5 ] = n2.z;
-
-						nka[ offset_morphTarget + 6 ] = n3.x;
-						nka[ offset_morphTarget + 7 ] = n3.y;
-						nka[ offset_morphTarget + 8 ] = n3.z;
-
-						nka[ offset_morphTarget + 9 ]  = n4.x;
-						nka[ offset_morphTarget + 10 ] = n4.y;
-						nka[ offset_morphTarget + 11 ] = n4.z;
-
-					}
-
-					//
-
-					offset_morphTarget += 12;
-
-				}
-
-				_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphTargetsBuffers[ vk ] );
-				_gl.bufferData( _gl.ARRAY_BUFFER, morphTargetsArrays[ vk ], hint );
-
-				if ( material.morphNormals ) {
-
-					_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphNormalsBuffers[ vk ] );
-					_gl.bufferData( _gl.ARRAY_BUFFER, morphNormalsArrays[ vk ], hint );
-
-				}
-
-			}
-
-		}
-
-		if ( obj_skinWeights.length ) {
-
-			for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
-
-				face = obj_faces[ chunk_faces3[ f ]	];
-
-				// weights
-
-				sw1 = obj_skinWeights[ face.a ];
-				sw2 = obj_skinWeights[ face.b ];
-				sw3 = obj_skinWeights[ face.c ];
-
-				skinWeightArray[ offset_skin ]     = sw1.x;
-				skinWeightArray[ offset_skin + 1 ] = sw1.y;
-				skinWeightArray[ offset_skin + 2 ] = sw1.z;
-				skinWeightArray[ offset_skin + 3 ] = sw1.w;
-
-				skinWeightArray[ offset_skin + 4 ] = sw2.x;
-				skinWeightArray[ offset_skin + 5 ] = sw2.y;
-				skinWeightArray[ offset_skin + 6 ] = sw2.z;
-				skinWeightArray[ offset_skin + 7 ] = sw2.w;
-
-				skinWeightArray[ offset_skin + 8 ]  = sw3.x;
-				skinWeightArray[ offset_skin + 9 ]  = sw3.y;
-				skinWeightArray[ offset_skin + 10 ] = sw3.z;
-				skinWeightArray[ offset_skin + 11 ] = sw3.w;
-
-				// indices
-
-				si1 = obj_skinIndices[ face.a ];
-				si2 = obj_skinIndices[ face.b ];
-				si3 = obj_skinIndices[ face.c ];
-
-				skinIndexArray[ offset_skin ]     = si1.x;
-				skinIndexArray[ offset_skin + 1 ] = si1.y;
-				skinIndexArray[ offset_skin + 2 ] = si1.z;
-				skinIndexArray[ offset_skin + 3 ] = si1.w;
-
-				skinIndexArray[ offset_skin + 4 ] = si2.x;
-				skinIndexArray[ offset_skin + 5 ] = si2.y;
-				skinIndexArray[ offset_skin + 6 ] = si2.z;
-				skinIndexArray[ offset_skin + 7 ] = si2.w;
-
-				skinIndexArray[ offset_skin + 8 ]  = si3.x;
-				skinIndexArray[ offset_skin + 9 ]  = si3.y;
-				skinIndexArray[ offset_skin + 10 ] = si3.z;
-				skinIndexArray[ offset_skin + 11 ] = si3.w;
-
-				offset_skin += 12;
-
-			}
-
-			for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
-
-				face = obj_faces[ chunk_faces4[ f ] ];
-
-				// weights
-
-				sw1 = obj_skinWeights[ face.a ];
-				sw2 = obj_skinWeights[ face.b ];
-				sw3 = obj_skinWeights[ face.c ];
-				sw4 = obj_skinWeights[ face.d ];
-
-				skinWeightArray[ offset_skin ]     = sw1.x;
-				skinWeightArray[ offset_skin + 1 ] = sw1.y;
-				skinWeightArray[ offset_skin + 2 ] = sw1.z;
-				skinWeightArray[ offset_skin + 3 ] = sw1.w;
-
-				skinWeightArray[ offset_skin + 4 ] = sw2.x;
-				skinWeightArray[ offset_skin + 5 ] = sw2.y;
-				skinWeightArray[ offset_skin + 6 ] = sw2.z;
-				skinWeightArray[ offset_skin + 7 ] = sw2.w;
-
-				skinWeightArray[ offset_skin + 8 ]  = sw3.x;
-				skinWeightArray[ offset_skin + 9 ]  = sw3.y;
-				skinWeightArray[ offset_skin + 10 ] = sw3.z;
-				skinWeightArray[ offset_skin + 11 ] = sw3.w;
-
-				skinWeightArray[ offset_skin + 12 ] = sw4.x;
-				skinWeightArray[ offset_skin + 13 ] = sw4.y;
-				skinWeightArray[ offset_skin + 14 ] = sw4.z;
-				skinWeightArray[ offset_skin + 15 ] = sw4.w;
-
-				// indices
-
-				si1 = obj_skinIndices[ face.a ];
-				si2 = obj_skinIndices[ face.b ];
-				si3 = obj_skinIndices[ face.c ];
-				si4 = obj_skinIndices[ face.d ];
-
-				skinIndexArray[ offset_skin ]     = si1.x;
-				skinIndexArray[ offset_skin + 1 ] = si1.y;
-				skinIndexArray[ offset_skin + 2 ] = si1.z;
-				skinIndexArray[ offset_skin + 3 ] = si1.w;
-
-				skinIndexArray[ offset_skin + 4 ] = si2.x;
-				skinIndexArray[ offset_skin + 5 ] = si2.y;
-				skinIndexArray[ offset_skin + 6 ] = si2.z;
-				skinIndexArray[ offset_skin + 7 ] = si2.w;
-
-				skinIndexArray[ offset_skin + 8 ]  = si3.x;
-				skinIndexArray[ offset_skin + 9 ]  = si3.y;
-				skinIndexArray[ offset_skin + 10 ] = si3.z;
-				skinIndexArray[ offset_skin + 11 ] = si3.w;
-
-				skinIndexArray[ offset_skin + 12 ] = si4.x;
-				skinIndexArray[ offset_skin + 13 ] = si4.y;
-				skinIndexArray[ offset_skin + 14 ] = si4.z;
-				skinIndexArray[ offset_skin + 15 ] = si4.w;
-
-				offset_skin += 16;
-
-			}
-
-			if ( offset_skin > 0 ) {
-
-				_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglSkinIndicesBuffer );
-				_gl.bufferData( _gl.ARRAY_BUFFER, skinIndexArray, hint );
-
-				_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglSkinWeightsBuffer );
-				_gl.bufferData( _gl.ARRAY_BUFFER, skinWeightArray, hint );
-
-			}
-
-		}
-
-		if ( dirtyColors && vertexColorType ) {
-
-			for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
-
-				face = obj_faces[ chunk_faces3[ f ]	];
-
-				vertexColors = face.vertexColors;
-				faceColor = face.color;
-
-				if ( vertexColors.length === 3 && vertexColorType === THREE.VertexColors ) {
-
-					c1 = vertexColors[ 0 ];
-					c2 = vertexColors[ 1 ];
-					c3 = vertexColors[ 2 ];
-
-				} else {
-
-					c1 = faceColor;
-					c2 = faceColor;
-					c3 = faceColor;
-
-				}
-
-				colorArray[ offset_color ]     = c1.r;
-				colorArray[ offset_color + 1 ] = c1.g;
-				colorArray[ offset_color + 2 ] = c1.b;
-
-				colorArray[ offset_color + 3 ] = c2.r;
-				colorArray[ offset_color + 4 ] = c2.g;
-				colorArray[ offset_color + 5 ] = c2.b;
-
-				colorArray[ offset_color + 6 ] = c3.r;
-				colorArray[ offset_color + 7 ] = c3.g;
-				colorArray[ offset_color + 8 ] = c3.b;
-
-				offset_color += 9;
-
-			}
-
-			for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
-
-				face = obj_faces[ chunk_faces4[ f ] ];
-
-				vertexColors = face.vertexColors;
-				faceColor = face.color;
-
-				if ( vertexColors.length === 4 && vertexColorType === THREE.VertexColors ) {
-
-					c1 = vertexColors[ 0 ];
-					c2 = vertexColors[ 1 ];
-					c3 = vertexColors[ 2 ];
-					c4 = vertexColors[ 3 ];
-
-				} else {
-
-					c1 = faceColor;
-					c2 = faceColor;
-					c3 = faceColor;
-					c4 = faceColor;
-
-				}
-
-				colorArray[ offset_color ]     = c1.r;
-				colorArray[ offset_color + 1 ] = c1.g;
-				colorArray[ offset_color + 2 ] = c1.b;
-
-				colorArray[ offset_color + 3 ] = c2.r;
-				colorArray[ offset_color + 4 ] = c2.g;
-				colorArray[ offset_color + 5 ] = c2.b;
-
-				colorArray[ offset_color + 6 ] = c3.r;
-				colorArray[ offset_color + 7 ] = c3.g;
-				colorArray[ offset_color + 8 ] = c3.b;
-
-				colorArray[ offset_color + 9 ]  = c4.r;
-				colorArray[ offset_color + 10 ] = c4.g;
-				colorArray[ offset_color + 11 ] = c4.b;
-
-				offset_color += 12;
-
-			}
-
-			if ( offset_color > 0 ) {
-
-				_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglColorBuffer );
-				_gl.bufferData( _gl.ARRAY_BUFFER, colorArray, hint );
-
-			}
-
-		}
-
-		if ( dirtyTangents && geometry.hasTangents ) {
-
-			for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
-
-				face = obj_faces[ chunk_faces3[ f ]	];
-
-				vertexTangents = face.vertexTangents;
-
-				t1 = vertexTangents[ 0 ];
-				t2 = vertexTangents[ 1 ];
-				t3 = vertexTangents[ 2 ];
-
-				tangentArray[ offset_tangent ]     = t1.x;
-				tangentArray[ offset_tangent + 1 ] = t1.y;
-				tangentArray[ offset_tangent + 2 ] = t1.z;
-				tangentArray[ offset_tangent + 3 ] = t1.w;
-
-				tangentArray[ offset_tangent + 4 ] = t2.x;
-				tangentArray[ offset_tangent + 5 ] = t2.y;
-				tangentArray[ offset_tangent + 6 ] = t2.z;
-				tangentArray[ offset_tangent + 7 ] = t2.w;
-
-				tangentArray[ offset_tangent + 8 ]  = t3.x;
-				tangentArray[ offset_tangent + 9 ]  = t3.y;
-				tangentArray[ offset_tangent + 10 ] = t3.z;
-				tangentArray[ offset_tangent + 11 ] = t3.w;
-
-				offset_tangent += 12;
-
-			}
-
-			for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
-
-				face = obj_faces[ chunk_faces4[ f ] ];
-
-				vertexTangents = face.vertexTangents;
-
-				t1 = vertexTangents[ 0 ];
-				t2 = vertexTangents[ 1 ];
-				t3 = vertexTangents[ 2 ];
-				t4 = vertexTangents[ 3 ];
-
-				tangentArray[ offset_tangent ]     = t1.x;
-				tangentArray[ offset_tangent + 1 ] = t1.y;
-				tangentArray[ offset_tangent + 2 ] = t1.z;
-				tangentArray[ offset_tangent + 3 ] = t1.w;
-
-				tangentArray[ offset_tangent + 4 ] = t2.x;
-				tangentArray[ offset_tangent + 5 ] = t2.y;
-				tangentArray[ offset_tangent + 6 ] = t2.z;
-				tangentArray[ offset_tangent + 7 ] = t2.w;
-
-				tangentArray[ offset_tangent + 8 ]  = t3.x;
-				tangentArray[ offset_tangent + 9 ]  = t3.y;
-				tangentArray[ offset_tangent + 10 ] = t3.z;
-				tangentArray[ offset_tangent + 11 ] = t3.w;
-
-				tangentArray[ offset_tangent + 12 ] = t4.x;
-				tangentArray[ offset_tangent + 13 ] = t4.y;
-				tangentArray[ offset_tangent + 14 ] = t4.z;
-				tangentArray[ offset_tangent + 15 ] = t4.w;
-
-				offset_tangent += 16;
-
-			}
-
-			_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglTangentBuffer );
-			_gl.bufferData( _gl.ARRAY_BUFFER, tangentArray, hint );
-
-		}
-
-		if ( dirtyNormals && normalType ) {
-
-			for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
-
-				face = obj_faces[ chunk_faces3[ f ]	];
-
-				vertexNormals = face.vertexNormals;
-				faceNormal = face.normal;
-
-				if ( vertexNormals.length === 3 && needsSmoothNormals ) {
-
-					for ( i = 0; i < 3; i ++ ) {
-
-						vn = vertexNormals[ i ];
-
-						normalArray[ offset_normal ]     = vn.x;
-						normalArray[ offset_normal + 1 ] = vn.y;
-						normalArray[ offset_normal + 2 ] = vn.z;
-
-						offset_normal += 3;
-
-					}
-
-				} else {
-
-					for ( i = 0; i < 3; i ++ ) {
-
-						normalArray[ offset_normal ]     = faceNormal.x;
-						normalArray[ offset_normal + 1 ] = faceNormal.y;
-						normalArray[ offset_normal + 2 ] = faceNormal.z;
-
-						offset_normal += 3;
-
-					}
-
-				}
-
-			}
-
-			for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
-
-				face = obj_faces[ chunk_faces4[ f ] ];
-
-				vertexNormals = face.vertexNormals;
-				faceNormal = face.normal;
-
-				if ( vertexNormals.length === 4 && needsSmoothNormals ) {
-
-					for ( i = 0; i < 4; i ++ ) {
-
-						vn = vertexNormals[ i ];
-
-						normalArray[ offset_normal ]     = vn.x;
-						normalArray[ offset_normal + 1 ] = vn.y;
-						normalArray[ offset_normal + 2 ] = vn.z;
-
-						offset_normal += 3;
-
-					}
-
-				} else {
-
-					for ( i = 0; i < 4; i ++ ) {
-
-						normalArray[ offset_normal ]     = faceNormal.x;
-						normalArray[ offset_normal + 1 ] = faceNormal.y;
-						normalArray[ offset_normal + 2 ] = faceNormal.z;
-
-						offset_normal += 3;
-
-					}
-
-				}
-
-			}
-
-			_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglNormalBuffer );
-			_gl.bufferData( _gl.ARRAY_BUFFER, normalArray, hint );
-
-		}
-
-		if ( dirtyUvs && obj_uvs && uvType ) {
-
-			for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
-
-				fi = chunk_faces3[ f ];
-
-				uv = obj_uvs[ fi ];
-
-				if ( uv === undefined ) continue;
-
-				for ( i = 0; i < 3; i ++ ) {
-
-					uvi = uv[ i ];
-
-					uvArray[ offset_uv ]     = uvi.x;
-					uvArray[ offset_uv + 1 ] = uvi.y;
-
-					offset_uv += 2;
-
-				}
-
-			}
-
-			for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
-
-				fi = chunk_faces4[ f ];
-
-				uv = obj_uvs[ fi ];
-
-				if ( uv === undefined ) continue;
-
-				for ( i = 0; i < 4; i ++ ) {
-
-					uvi = uv[ i ];
-
-					uvArray[ offset_uv ]     = uvi.x;
-					uvArray[ offset_uv + 1 ] = uvi.y;
-
-					offset_uv += 2;
-
-				}
-
-			}
-
-			if ( offset_uv > 0 ) {
-
-				_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglUVBuffer );
-				_gl.bufferData( _gl.ARRAY_BUFFER, uvArray, hint );
-
-			}
-
-		}
-
-		if ( dirtyUvs && obj_uvs2 && uvType ) {
-
-			for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
-
-				fi = chunk_faces3[ f ];
-
-				uv2 = obj_uvs2[ fi ];
-
-				if ( uv2 === undefined ) continue;
-
-				for ( i = 0; i < 3; i ++ ) {
-
-					uv2i = uv2[ i ];
-
-					uv2Array[ offset_uv2 ]     = uv2i.x;
-					uv2Array[ offset_uv2 + 1 ] = uv2i.y;
-
-					offset_uv2 += 2;
-
-				}
-
-			}
-
-			for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
-
-				fi = chunk_faces4[ f ];
-
-				uv2 = obj_uvs2[ fi ];
-
-				if ( uv2 === undefined ) continue;
-
-				for ( i = 0; i < 4; i ++ ) {
-
-					uv2i = uv2[ i ];
-
-					uv2Array[ offset_uv2 ]     = uv2i.x;
-					uv2Array[ offset_uv2 + 1 ] = uv2i.y;
-
-					offset_uv2 += 2;
-
-				}
-
-			}
-
-			if ( offset_uv2 > 0 ) {
-
-				_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglUV2Buffer );
-				_gl.bufferData( _gl.ARRAY_BUFFER, uv2Array, hint );
-
-			}
-
-		}
-
-		if ( dirtyElements ) {
-
-			for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
-
-				faceArray[ offset_face ] 	 = vertexIndex;
-				faceArray[ offset_face + 1 ] = vertexIndex + 1;
-				faceArray[ offset_face + 2 ] = vertexIndex + 2;
-
-				offset_face += 3;
-
-				lineArray[ offset_line ]     = vertexIndex;
-				lineArray[ offset_line + 1 ] = vertexIndex + 1;
-
-				lineArray[ offset_line + 2 ] = vertexIndex;
-				lineArray[ offset_line + 3 ] = vertexIndex + 2;
-
-				lineArray[ offset_line + 4 ] = vertexIndex + 1;
-				lineArray[ offset_line + 5 ] = vertexIndex + 2;
-
-				offset_line += 6;
-
-				vertexIndex += 3;
-
-			}
-
-			for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
-
-				faceArray[ offset_face ]     = vertexIndex;
-				faceArray[ offset_face + 1 ] = vertexIndex + 1;
-				faceArray[ offset_face + 2 ] = vertexIndex + 3;
-
-				faceArray[ offset_face + 3 ] = vertexIndex + 1;
-				faceArray[ offset_face + 4 ] = vertexIndex + 2;
-				faceArray[ offset_face + 5 ] = vertexIndex + 3;
-
-				offset_face += 6;
-
-				lineArray[ offset_line ]     = vertexIndex;
-				lineArray[ offset_line + 1 ] = vertexIndex + 1;
-
-				lineArray[ offset_line + 2 ] = vertexIndex;
-				lineArray[ offset_line + 3 ] = vertexIndex + 3;
-
-				lineArray[ offset_line + 4 ] = vertexIndex + 1;
-				lineArray[ offset_line + 5 ] = vertexIndex + 2;
-
-				lineArray[ offset_line + 6 ] = vertexIndex + 2;
-				lineArray[ offset_line + 7 ] = vertexIndex + 3;
-
-				offset_line += 8;
-
-				vertexIndex += 4;
-
-			}
-
-			_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, geometryGroup.__webglFaceBuffer );
-			_gl.bufferData( _gl.ELEMENT_ARRAY_BUFFER, faceArray, hint );
-
-			_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, geometryGroup.__webglLineBuffer );
-			_gl.bufferData( _gl.ELEMENT_ARRAY_BUFFER, lineArray, hint );
-
-		}
-
-		if ( customAttributes ) {
-
-			for ( i = 0, il = customAttributes.length; i < il; i ++ ) {
-
-				customAttribute = customAttributes[ i ];
-
-				if ( ! customAttribute.__original.needsUpdate ) continue;
-
-				offset_custom = 0;
-				offset_customSrc = 0;
-
-				if ( customAttribute.size === 1 ) {
-
-					if ( customAttribute.boundTo === undefined || customAttribute.boundTo === "vertices" ) {
-
-						for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
-
-							face = obj_faces[ chunk_faces3[ f ]	];
-
-							customAttribute.array[ offset_custom ] 	   = customAttribute.value[ face.a ];
-							customAttribute.array[ offset_custom + 1 ] = customAttribute.value[ face.b ];
-							customAttribute.array[ offset_custom + 2 ] = customAttribute.value[ face.c ];
-
-							offset_custom += 3;
-
-						}
-
-						for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
-
-							face = obj_faces[ chunk_faces4[ f ] ];
-
-							customAttribute.array[ offset_custom ] 	   = customAttribute.value[ face.a ];
-							customAttribute.array[ offset_custom + 1 ] = customAttribute.value[ face.b ];
-							customAttribute.array[ offset_custom + 2 ] = customAttribute.value[ face.c ];
-							customAttribute.array[ offset_custom + 3 ] = customAttribute.value[ face.d ];
-
-							offset_custom += 4;
-
-						}
-
-					} else if ( customAttribute.boundTo === "faces" ) {
-
-						for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
-
-							value = customAttribute.value[ chunk_faces3[ f ] ];
-
-							customAttribute.array[ offset_custom ] 	   = value;
-							customAttribute.array[ offset_custom + 1 ] = value;
-							customAttribute.array[ offset_custom + 2 ] = value;
-
-							offset_custom += 3;
-
-						}
-
-						for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
-
-							value = customAttribute.value[ chunk_faces4[ f ] ];
-
-							customAttribute.array[ offset_custom ] 	   = value;
-							customAttribute.array[ offset_custom + 1 ] = value;
-							customAttribute.array[ offset_custom + 2 ] = value;
-							customAttribute.array[ offset_custom + 3 ] = value;
-
-							offset_custom += 4;
-
-						}
-
-					}
-
-				} else if ( customAttribute.size === 2 ) {
-
-					if ( customAttribute.boundTo === undefined || customAttribute.boundTo === "vertices" ) {
-
-						for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
-
-							face = obj_faces[ chunk_faces3[ f ]	];
-
-							v1 = customAttribute.value[ face.a ];
-							v2 = customAttribute.value[ face.b ];
-							v3 = customAttribute.value[ face.c ];
-
-							customAttribute.array[ offset_custom ] 	   = v1.x;
-							customAttribute.array[ offset_custom + 1 ] = v1.y;
-
-							customAttribute.array[ offset_custom + 2 ] = v2.x;
-							customAttribute.array[ offset_custom + 3 ] = v2.y;
-
-							customAttribute.array[ offset_custom + 4 ] = v3.x;
-							customAttribute.array[ offset_custom + 5 ] = v3.y;
-
-							offset_custom += 6;
-
-						}
-
-						for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
-
-							face = obj_faces[ chunk_faces4[ f ] ];
-
-							v1 = customAttribute.value[ face.a ];
-							v2 = customAttribute.value[ face.b ];
-							v3 = customAttribute.value[ face.c ];
-							v4 = customAttribute.value[ face.d ];
-
-							customAttribute.array[ offset_custom ] 	   = v1.x;
-							customAttribute.array[ offset_custom + 1 ] = v1.y;
-
-							customAttribute.array[ offset_custom + 2 ] = v2.x;
-							customAttribute.array[ offset_custom + 3 ] = v2.y;
-
-							customAttribute.array[ offset_custom + 4 ] = v3.x;
-							customAttribute.array[ offset_custom + 5 ] = v3.y;
-
-							customAttribute.array[ offset_custom + 6 ] = v4.x;
-							customAttribute.array[ offset_custom + 7 ] = v4.y;
-
-							offset_custom += 8;
-
-						}
-
-					} else if ( customAttribute.boundTo === "faces" ) {
-
-						for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
-
-							value = customAttribute.value[ chunk_faces3[ f ] ];
-
-							v1 = value;
-							v2 = value;
-							v3 = value;
-
-							customAttribute.array[ offset_custom ] 	   = v1.x;
-							customAttribute.array[ offset_custom + 1 ] = v1.y;
-
-							customAttribute.array[ offset_custom + 2 ] = v2.x;
-							customAttribute.array[ offset_custom + 3 ] = v2.y;
-
-							customAttribute.array[ offset_custom + 4 ] = v3.x;
-							customAttribute.array[ offset_custom + 5 ] = v3.y;
-
-							offset_custom += 6;
-
-						}
-
-						for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
-
-							value = customAttribute.value[ chunk_faces4[ f ] ];
-
-							v1 = value;
-							v2 = value;
-							v3 = value;
-							v4 = value;
-
-							customAttribute.array[ offset_custom ] 	   = v1.x;
-							customAttribute.array[ offset_custom + 1 ] = v1.y;
-
-							customAttribute.array[ offset_custom + 2 ] = v2.x;
-							customAttribute.array[ offset_custom + 3 ] = v2.y;
-
-							customAttribute.array[ offset_custom + 4 ] = v3.x;
-							customAttribute.array[ offset_custom + 5 ] = v3.y;
-
-							customAttribute.array[ offset_custom + 6 ] = v4.x;
-							customAttribute.array[ offset_custom + 7 ] = v4.y;
-
-							offset_custom += 8;
-
-						}
-
-					}
-
-				} else if ( customAttribute.size === 3 ) {
-
-					var pp;
-
-					if ( customAttribute.type === "c" ) {
-
-						pp = [ "r", "g", "b" ];
-
-					} else {
-
-						pp = [ "x", "y", "z" ];
-
-					}
-
-					if ( customAttribute.boundTo === undefined || customAttribute.boundTo === "vertices" ) {
-
-						for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
-
-							face = obj_faces[ chunk_faces3[ f ]	];
-
-							v1 = customAttribute.value[ face.a ];
-							v2 = customAttribute.value[ face.b ];
-							v3 = customAttribute.value[ face.c ];
-
-							customAttribute.array[ offset_custom ] 	   = v1[ pp[ 0 ] ];
-							customAttribute.array[ offset_custom + 1 ] = v1[ pp[ 1 ] ];
-							customAttribute.array[ offset_custom + 2 ] = v1[ pp[ 2 ] ];
-
-							customAttribute.array[ offset_custom + 3 ] = v2[ pp[ 0 ] ];
-							customAttribute.array[ offset_custom + 4 ] = v2[ pp[ 1 ] ];
-							customAttribute.array[ offset_custom + 5 ] = v2[ pp[ 2 ] ];
-
-							customAttribute.array[ offset_custom + 6 ] = v3[ pp[ 0 ] ];
-							customAttribute.array[ offset_custom + 7 ] = v3[ pp[ 1 ] ];
-							customAttribute.array[ offset_custom + 8 ] = v3[ pp[ 2 ] ];
-
-							offset_custom += 9;
-
-						}
-
-						for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
-
-							face = obj_faces[ chunk_faces4[ f ] ];
-
-							v1 = customAttribute.value[ face.a ];
-							v2 = customAttribute.value[ face.b ];
-							v3 = customAttribute.value[ face.c ];
-							v4 = customAttribute.value[ face.d ];
-
-							customAttribute.array[ offset_custom  ] 	= v1[ pp[ 0 ] ];
-							customAttribute.array[ offset_custom + 1  ] = v1[ pp[ 1 ] ];
-							customAttribute.array[ offset_custom + 2  ] = v1[ pp[ 2 ] ];
-
-							customAttribute.array[ offset_custom + 3  ] = v2[ pp[ 0 ] ];
-							customAttribute.array[ offset_custom + 4  ] = v2[ pp[ 1 ] ];
-							customAttribute.array[ offset_custom + 5  ] = v2[ pp[ 2 ] ];
-
-							customAttribute.array[ offset_custom + 6  ] = v3[ pp[ 0 ] ];
-							customAttribute.array[ offset_custom + 7  ] = v3[ pp[ 1 ] ];
-							customAttribute.array[ offset_custom + 8  ] = v3[ pp[ 2 ] ];
-
-							customAttribute.array[ offset_custom + 9  ] = v4[ pp[ 0 ] ];
-							customAttribute.array[ offset_custom + 10 ] = v4[ pp[ 1 ] ];
-							customAttribute.array[ offset_custom + 11 ] = v4[ pp[ 2 ] ];
-
-							offset_custom += 12;
-
-						}
-
-					} else if ( customAttribute.boundTo === "faces" ) {
-
-						for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
-
-							value = customAttribute.value[ chunk_faces3[ f ] ];
-
-							v1 = value;
-							v2 = value;
-							v3 = value;
-
-							customAttribute.array[ offset_custom ] 	   = v1[ pp[ 0 ] ];
-							customAttribute.array[ offset_custom + 1 ] = v1[ pp[ 1 ] ];
-							customAttribute.array[ offset_custom + 2 ] = v1[ pp[ 2 ] ];
-
-							customAttribute.array[ offset_custom + 3 ] = v2[ pp[ 0 ] ];
-							customAttribute.array[ offset_custom + 4 ] = v2[ pp[ 1 ] ];
-							customAttribute.array[ offset_custom + 5 ] = v2[ pp[ 2 ] ];
-
-							customAttribute.array[ offset_custom + 6 ] = v3[ pp[ 0 ] ];
-							customAttribute.array[ offset_custom + 7 ] = v3[ pp[ 1 ] ];
-							customAttribute.array[ offset_custom + 8 ] = v3[ pp[ 2 ] ];
-
-							offset_custom += 9;
-
-						}
-
-						for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
-
-							value = customAttribute.value[ chunk_faces4[ f ] ];
-
-							v1 = value;
-							v2 = value;
-							v3 = value;
-							v4 = value;
-
-							customAttribute.array[ offset_custom  ] 	= v1[ pp[ 0 ] ];
-							customAttribute.array[ offset_custom + 1  ] = v1[ pp[ 1 ] ];
-							customAttribute.array[ offset_custom + 2  ] = v1[ pp[ 2 ] ];
-
-							customAttribute.array[ offset_custom + 3  ] = v2[ pp[ 0 ] ];
-							customAttribute.array[ offset_custom + 4  ] = v2[ pp[ 1 ] ];
-							customAttribute.array[ offset_custom + 5  ] = v2[ pp[ 2 ] ];
-
-							customAttribute.array[ offset_custom + 6  ] = v3[ pp[ 0 ] ];
-							customAttribute.array[ offset_custom + 7  ] = v3[ pp[ 1 ] ];
-							customAttribute.array[ offset_custom + 8  ] = v3[ pp[ 2 ] ];
-
-							customAttribute.array[ offset_custom + 9  ] = v4[ pp[ 0 ] ];
-							customAttribute.array[ offset_custom + 10 ] = v4[ pp[ 1 ] ];
-							customAttribute.array[ offset_custom + 11 ] = v4[ pp[ 2 ] ];
-
-							offset_custom += 12;
-
-						}
-
-					} else if ( customAttribute.boundTo === "faceVertices" ) {
-
-						for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
-
-							value = customAttribute.value[ chunk_faces3[ f ] ];
-
-							v1 = value[ 0 ];
-							v2 = value[ 1 ];
-							v3 = value[ 2 ];
-
-							customAttribute.array[ offset_custom ] 	   = v1[ pp[ 0 ] ];
-							customAttribute.array[ offset_custom + 1 ] = v1[ pp[ 1 ] ];
-							customAttribute.array[ offset_custom + 2 ] = v1[ pp[ 2 ] ];
-
-							customAttribute.array[ offset_custom + 3 ] = v2[ pp[ 0 ] ];
-							customAttribute.array[ offset_custom + 4 ] = v2[ pp[ 1 ] ];
-							customAttribute.array[ offset_custom + 5 ] = v2[ pp[ 2 ] ];
-
-							customAttribute.array[ offset_custom + 6 ] = v3[ pp[ 0 ] ];
-							customAttribute.array[ offset_custom + 7 ] = v3[ pp[ 1 ] ];
-							customAttribute.array[ offset_custom + 8 ] = v3[ pp[ 2 ] ];
-
-							offset_custom += 9;
-
-						}
-
-						for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
-
-							value = customAttribute.value[ chunk_faces4[ f ] ];
-
-							v1 = value[ 0 ];
-							v2 = value[ 1 ];
-							v3 = value[ 2 ];
-							v4 = value[ 3 ];
-
-							customAttribute.array[ offset_custom  ] 	= v1[ pp[ 0 ] ];
-							customAttribute.array[ offset_custom + 1  ] = v1[ pp[ 1 ] ];
-							customAttribute.array[ offset_custom + 2  ] = v1[ pp[ 2 ] ];
-
-							customAttribute.array[ offset_custom + 3  ] = v2[ pp[ 0 ] ];
-							customAttribute.array[ offset_custom + 4  ] = v2[ pp[ 1 ] ];
-							customAttribute.array[ offset_custom + 5  ] = v2[ pp[ 2 ] ];
-
-							customAttribute.array[ offset_custom + 6  ] = v3[ pp[ 0 ] ];
-							customAttribute.array[ offset_custom + 7  ] = v3[ pp[ 1 ] ];
-							customAttribute.array[ offset_custom + 8  ] = v3[ pp[ 2 ] ];
-
-							customAttribute.array[ offset_custom + 9  ] = v4[ pp[ 0 ] ];
-							customAttribute.array[ offset_custom + 10 ] = v4[ pp[ 1 ] ];
-							customAttribute.array[ offset_custom + 11 ] = v4[ pp[ 2 ] ];
-
-							offset_custom += 12;
-
-						}
-
-					}
-
-				} else if ( customAttribute.size === 4 ) {
-
-					if ( customAttribute.boundTo === undefined || customAttribute.boundTo === "vertices" ) {
-
-						for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
-
-							face = obj_faces[ chunk_faces3[ f ]	];
-
-							v1 = customAttribute.value[ face.a ];
-							v2 = customAttribute.value[ face.b ];
-							v3 = customAttribute.value[ face.c ];
-
-							customAttribute.array[ offset_custom  ] 	= v1.x;
-							customAttribute.array[ offset_custom + 1  ] = v1.y;
-							customAttribute.array[ offset_custom + 2  ] = v1.z;
-							customAttribute.array[ offset_custom + 3  ] = v1.w;
-
-							customAttribute.array[ offset_custom + 4  ] = v2.x;
-							customAttribute.array[ offset_custom + 5  ] = v2.y;
-							customAttribute.array[ offset_custom + 6  ] = v2.z;
-							customAttribute.array[ offset_custom + 7  ] = v2.w;
-
-							customAttribute.array[ offset_custom + 8  ] = v3.x;
-							customAttribute.array[ offset_custom + 9  ] = v3.y;
-							customAttribute.array[ offset_custom + 10 ] = v3.z;
-							customAttribute.array[ offset_custom + 11 ] = v3.w;
-
-							offset_custom += 12;
-
-						}
-
-						for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
-
-							face = obj_faces[ chunk_faces4[ f ] ];
-
-							v1 = customAttribute.value[ face.a ];
-							v2 = customAttribute.value[ face.b ];
-							v3 = customAttribute.value[ face.c ];
-							v4 = customAttribute.value[ face.d ];
-
-							customAttribute.array[ offset_custom  ] 	= v1.x;
-							customAttribute.array[ offset_custom + 1  ] = v1.y;
-							customAttribute.array[ offset_custom + 2  ] = v1.z;
-							customAttribute.array[ offset_custom + 3  ] = v1.w;
-
-							customAttribute.array[ offset_custom + 4  ] = v2.x;
-							customAttribute.array[ offset_custom + 5  ] = v2.y;
-							customAttribute.array[ offset_custom + 6  ] = v2.z;
-							customAttribute.array[ offset_custom + 7  ] = v2.w;
-
-							customAttribute.array[ offset_custom + 8  ] = v3.x;
-							customAttribute.array[ offset_custom + 9  ] = v3.y;
-							customAttribute.array[ offset_custom + 10 ] = v3.z;
-							customAttribute.array[ offset_custom + 11 ] = v3.w;
-
-							customAttribute.array[ offset_custom + 12 ] = v4.x;
-							customAttribute.array[ offset_custom + 13 ] = v4.y;
-							customAttribute.array[ offset_custom + 14 ] = v4.z;
-							customAttribute.array[ offset_custom + 15 ] = v4.w;
-
-							offset_custom += 16;
-
-						}
-
-					} else if ( customAttribute.boundTo === "faces" ) {
-
-						for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
-
-							value = customAttribute.value[ chunk_faces3[ f ] ];
-
-							v1 = value;
-							v2 = value;
-							v3 = value;
-
-							customAttribute.array[ offset_custom  ] 	= v1.x;
-							customAttribute.array[ offset_custom + 1  ] = v1.y;
-							customAttribute.array[ offset_custom + 2  ] = v1.z;
-							customAttribute.array[ offset_custom + 3  ] = v1.w;
-
-							customAttribute.array[ offset_custom + 4  ] = v2.x;
-							customAttribute.array[ offset_custom + 5  ] = v2.y;
-							customAttribute.array[ offset_custom + 6  ] = v2.z;
-							customAttribute.array[ offset_custom + 7  ] = v2.w;
-
-							customAttribute.array[ offset_custom + 8  ] = v3.x;
-							customAttribute.array[ offset_custom + 9  ] = v3.y;
-							customAttribute.array[ offset_custom + 10 ] = v3.z;
-							customAttribute.array[ offset_custom + 11 ] = v3.w;
-
-							offset_custom += 12;
-
-						}
-
-						for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
-
-							value = customAttribute.value[ chunk_faces4[ f ] ];
-
-							v1 = value;
-							v2 = value;
-							v3 = value;
-							v4 = value;
-
-							customAttribute.array[ offset_custom  ] 	= v1.x;
-							customAttribute.array[ offset_custom + 1  ] = v1.y;
-							customAttribute.array[ offset_custom + 2  ] = v1.z;
-							customAttribute.array[ offset_custom + 3  ] = v1.w;
-
-							customAttribute.array[ offset_custom + 4  ] = v2.x;
-							customAttribute.array[ offset_custom + 5  ] = v2.y;
-							customAttribute.array[ offset_custom + 6  ] = v2.z;
-							customAttribute.array[ offset_custom + 7  ] = v2.w;
-
-							customAttribute.array[ offset_custom + 8  ] = v3.x;
-							customAttribute.array[ offset_custom + 9  ] = v3.y;
-							customAttribute.array[ offset_custom + 10 ] = v3.z;
-							customAttribute.array[ offset_custom + 11 ] = v3.w;
-
-							customAttribute.array[ offset_custom + 12 ] = v4.x;
-							customAttribute.array[ offset_custom + 13 ] = v4.y;
-							customAttribute.array[ offset_custom + 14 ] = v4.z;
-							customAttribute.array[ offset_custom + 15 ] = v4.w;
-
-							offset_custom += 16;
-
-						}
-
-					} else if ( customAttribute.boundTo === "faceVertices" ) {
-
-						for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
-
-							value = customAttribute.value[ chunk_faces3[ f ] ];
-
-							v1 = value[ 0 ];
-							v2 = value[ 1 ];
-							v3 = value[ 2 ];
-
-							customAttribute.array[ offset_custom  ] 	= v1.x;
-							customAttribute.array[ offset_custom + 1  ] = v1.y;
-							customAttribute.array[ offset_custom + 2  ] = v1.z;
-							customAttribute.array[ offset_custom + 3  ] = v1.w;
-
-							customAttribute.array[ offset_custom + 4  ] = v2.x;
-							customAttribute.array[ offset_custom + 5  ] = v2.y;
-							customAttribute.array[ offset_custom + 6  ] = v2.z;
-							customAttribute.array[ offset_custom + 7  ] = v2.w;
-
-							customAttribute.array[ offset_custom + 8  ] = v3.x;
-							customAttribute.array[ offset_custom + 9  ] = v3.y;
-							customAttribute.array[ offset_custom + 10 ] = v3.z;
-							customAttribute.array[ offset_custom + 11 ] = v3.w;
-
-							offset_custom += 12;
-
-						}
-
-						for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
-
-							value = customAttribute.value[ chunk_faces4[ f ] ];
-
-							v1 = value[ 0 ];
-							v2 = value[ 1 ];
-							v3 = value[ 2 ];
-							v4 = value[ 3 ];
-
-							customAttribute.array[ offset_custom  ] 	= v1.x;
-							customAttribute.array[ offset_custom + 1  ] = v1.y;
-							customAttribute.array[ offset_custom + 2  ] = v1.z;
-							customAttribute.array[ offset_custom + 3  ] = v1.w;
-
-							customAttribute.array[ offset_custom + 4  ] = v2.x;
-							customAttribute.array[ offset_custom + 5  ] = v2.y;
-							customAttribute.array[ offset_custom + 6  ] = v2.z;
-							customAttribute.array[ offset_custom + 7  ] = v2.w;
-
-							customAttribute.array[ offset_custom + 8  ] = v3.x;
-							customAttribute.array[ offset_custom + 9  ] = v3.y;
-							customAttribute.array[ offset_custom + 10 ] = v3.z;
-							customAttribute.array[ offset_custom + 11 ] = v3.w;
-
-							customAttribute.array[ offset_custom + 12 ] = v4.x;
-							customAttribute.array[ offset_custom + 13 ] = v4.y;
-							customAttribute.array[ offset_custom + 14 ] = v4.z;
-							customAttribute.array[ offset_custom + 15 ] = v4.w;
-
-							offset_custom += 16;
-
-						}
-
-					}
-
-				}
-
-				_gl.bindBuffer( _gl.ARRAY_BUFFER, customAttribute.buffer );
-				_gl.bufferData( _gl.ARRAY_BUFFER, customAttribute.array, hint );
-
-			}
-
-		}
-
-		if ( dispose ) {
-
-			delete geometryGroup.__inittedArrays;
-			delete geometryGroup.__colorArray;
-			delete geometryGroup.__normalArray;
-			delete geometryGroup.__tangentArray;
-			delete geometryGroup.__uvArray;
-			delete geometryGroup.__uv2Array;
-			delete geometryGroup.__faceArray;
-			delete geometryGroup.__vertexArray;
-			delete geometryGroup.__lineArray;
-			delete geometryGroup.__skinIndexArray;
-			delete geometryGroup.__skinWeightArray;
-
-		}
-
-	};
-
-	function setDirectBuffers ( geometry, hint, dispose ) {
-
-		var attributes = geometry.attributes;
-
-		var attributeName, attributeItem;
-
-		for ( attributeName in attributes ) {
-
-			attributeItem = attributes[ attributeName ];
-
-			if ( attributeItem.needsUpdate ) {
-
-				if ( attributeName === 'index' ) {
-
-					_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, attributeItem.buffer );
-					_gl.bufferData( _gl.ELEMENT_ARRAY_BUFFER, attributeItem.array, hint );
-
-				} else {
-
-					_gl.bindBuffer( _gl.ARRAY_BUFFER, attributeItem.buffer );
-					_gl.bufferData( _gl.ARRAY_BUFFER, attributeItem.array, hint );
-
-				}
-
-				attributeItem.needsUpdate = false;
-
-			}
-
-			if ( dispose && ! attributeItem.dynamic ) {
-
-				delete attributeItem.array;
-
-			}
-
-		}
-
-	};
-
-	// Buffer rendering
-
-	this.renderBufferImmediate = function ( object, program, material ) {
-
-		if ( object.hasPositions && ! object.__webglVertexBuffer ) object.__webglVertexBuffer = _gl.createBuffer();
-		if ( object.hasNormals && ! object.__webglNormalBuffer ) object.__webglNormalBuffer = _gl.createBuffer();
-		if ( object.hasUvs && ! object.__webglUvBuffer ) object.__webglUvBuffer = _gl.createBuffer();
-		if ( object.hasColors && ! object.__webglColorBuffer ) object.__webglColorBuffer = _gl.createBuffer();
-
-		if ( object.hasPositions ) {
-
-			_gl.bindBuffer( _gl.ARRAY_BUFFER, object.__webglVertexBuffer );
-			_gl.bufferData( _gl.ARRAY_BUFFER, object.positionArray, _gl.DYNAMIC_DRAW );
-			_gl.enableVertexAttribArray( program.attributes.position );
-			_gl.vertexAttribPointer( program.attributes.position, 3, _gl.FLOAT, false, 0, 0 );
-
-		}
-
-		if ( object.hasNormals ) {
-
-			_gl.bindBuffer( _gl.ARRAY_BUFFER, object.__webglNormalBuffer );
-
-			if ( material.shading === THREE.FlatShading ) {
-
-				var nx, ny, nz,
-					nax, nbx, ncx, nay, nby, ncy, naz, nbz, ncz,
-					normalArray,
-					i, il = object.count * 3;
-
-				for( i = 0; i < il; i += 9 ) {
-
-					normalArray = object.normalArray;
-
-					nax  = normalArray[ i ];
-					nay  = normalArray[ i + 1 ];
-					naz  = normalArray[ i + 2 ];
-
-					nbx  = normalArray[ i + 3 ];
-					nby  = normalArray[ i + 4 ];
-					nbz  = normalArray[ i + 5 ];
-
-					ncx  = normalArray[ i + 6 ];
-					ncy  = normalArray[ i + 7 ];
-					ncz  = normalArray[ i + 8 ];
-
-					nx = ( nax + nbx + ncx ) / 3;
-					ny = ( nay + nby + ncy ) / 3;
-					nz = ( naz + nbz + ncz ) / 3;
-
-					normalArray[ i ] 	 = nx;
-					normalArray[ i + 1 ] = ny;
-					normalArray[ i + 2 ] = nz;
-
-					normalArray[ i + 3 ] = nx;
-					normalArray[ i + 4 ] = ny;
-					normalArray[ i + 5 ] = nz;
-
-					normalArray[ i + 6 ] = nx;
-					normalArray[ i + 7 ] = ny;
-					normalArray[ i + 8 ] = nz;
-
-				}
-
-			}
-
-			_gl.bufferData( _gl.ARRAY_BUFFER, object.normalArray, _gl.DYNAMIC_DRAW );
-			_gl.enableVertexAttribArray( program.attributes.normal );
-			_gl.vertexAttribPointer( program.attributes.normal, 3, _gl.FLOAT, false, 0, 0 );
-
-		}
-
-		if ( object.hasUvs && material.map ) {
-
-			_gl.bindBuffer( _gl.ARRAY_BUFFER, object.__webglUvBuffer );
-			_gl.bufferData( _gl.ARRAY_BUFFER, object.uvArray, _gl.DYNAMIC_DRAW );
-			_gl.enableVertexAttribArray( program.attributes.uv );
-			_gl.vertexAttribPointer( program.attributes.uv, 2, _gl.FLOAT, false, 0, 0 );
-
-		}
-
-		if ( object.hasColors && material.vertexColors !== THREE.NoColors ) {
-
-			_gl.bindBuffer( _gl.ARRAY_BUFFER, object.__webglColorBuffer );
-			_gl.bufferData( _gl.ARRAY_BUFFER, object.colorArray, _gl.DYNAMIC_DRAW );
-			_gl.enableVertexAttribArray( program.attributes.color );
-			_gl.vertexAttribPointer( program.attributes.color, 3, _gl.FLOAT, false, 0, 0 );
-
-		}
-
-		_gl.drawArrays( _gl.TRIANGLES, 0, object.count );
-
-		object.count = 0;
-
-	};
-
-	this.renderBufferDirect = function ( camera, lights, fog, material, geometry, object ) {
-
-		if ( material.visible === false ) return;
-
-		var program, programAttributes, linewidth, primitives, a, attribute, geometryAttributes;
-		var attributeItem, attributeName, attributePointer, attributeSize;
-
-		program = setProgram( camera, lights, fog, material, object );
-
-		programAttributes = program.attributes;
-		geometryAttributes = geometry.attributes;
-
-		var updateBuffers = false,
-			wireframeBit = material.wireframe ? 1 : 0,
-			geometryHash = ( geometry.id * 0xffffff ) + ( program.id * 2 ) + wireframeBit;
-
-		if ( geometryHash !== _currentGeometryGroupHash ) {
-
-			_currentGeometryGroupHash = geometryHash;
-			updateBuffers = true;
-
-		}
-
-		if ( updateBuffers ) {
-
-			disableAttributes();
-
-		}
-
-		// render mesh
-
-		if ( object instanceof THREE.Mesh ) {
-
-			var index = geometryAttributes[ "index" ];
-
-			// indexed triangles
-
-			if ( index ) {
-
-				var offsets = geometry.offsets;
-
-				// if there is more than 1 chunk
-				// must set attribute pointers to use new offsets for each chunk
-				// even if geometry and materials didn't change
-
-				if ( offsets.length > 1 ) updateBuffers = true;
-
-				for ( var i = 0, il = offsets.length; i < il; i ++ ) {
-
-					var startIndex = offsets[ i ].index;
-
-					if ( updateBuffers ) {
-
-						for ( attributeName in geometryAttributes ) {
-
-							if ( attributeName === 'index' ) continue;
-
-							attributePointer = programAttributes[ attributeName ];
-							attributeItem = geometryAttributes[ attributeName ];
-							attributeSize = attributeItem.itemSize;
-
-							if ( attributePointer >= 0 ) {
-
-								_gl.bindBuffer( _gl.ARRAY_BUFFER, attributeItem.buffer );
-								enableAttribute( attributePointer );
-								_gl.vertexAttribPointer( attributePointer, attributeSize, _gl.FLOAT, false, 0, startIndex * attributeSize * 4 ); // 4 bytes per Float32
-
-							}
-
-						}
-
-						// indices
-
-						_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, index.buffer );
-
-					}
-
-					// render indexed triangles
-
-					_gl.drawElements( _gl.TRIANGLES, offsets[ i ].count, _gl.UNSIGNED_SHORT, offsets[ i ].start * 2 ); // 2 bytes per Uint16
-
-					_this.info.render.calls ++;
-					_this.info.render.vertices += offsets[ i ].count; // not really true, here vertices can be shared
-					_this.info.render.faces += offsets[ i ].count / 3;
-
-				}
-
-			// non-indexed triangles
-
-			} else {
-
-				if ( updateBuffers ) {
-
-					for ( attributeName in geometryAttributes ) {
-
-						if ( attributeName === 'index') continue;
-
-						attributePointer = programAttributes[ attributeName ];
-						attributeItem = geometryAttributes[ attributeName ];
-						attributeSize = attributeItem.itemSize;
-
-						if ( attributePointer >= 0 ) {
-
-							_gl.bindBuffer( _gl.ARRAY_BUFFER, attributeItem.buffer );
-							enableAttribute( attributePointer );
-							_gl.vertexAttribPointer( attributePointer, attributeSize, _gl.FLOAT, false, 0, 0 );
-
-						}
-
-					}
-
-				}
-
-				var position = geometry.attributes[ "position" ];
-
-				// render non-indexed triangles
-
-				_gl.drawArrays( _gl.TRIANGLES, 0, position.numItems / 3 );
-
-				_this.info.render.calls ++;
-				_this.info.render.vertices += position.numItems / 3;
-				_this.info.render.faces += position.numItems / 3 / 3;
-
-			}
-
-		// render particles
-
-		} else if ( object instanceof THREE.ParticleSystem ) {
-
-			if ( updateBuffers ) {
-
-				for ( attributeName in geometryAttributes ) {
-
-					attributePointer = programAttributes[ attributeName ];
-					attributeItem = geometryAttributes[ attributeName ];
-					attributeSize = attributeItem.itemSize;
-
-					if ( attributePointer >= 0 ) {
-
-						_gl.bindBuffer( _gl.ARRAY_BUFFER, attributeItem.buffer );
-						enableAttribute( attributePointer );
-						_gl.vertexAttribPointer( attributePointer, attributeSize, _gl.FLOAT, false, 0, 0 );
-
-					}
-
-				}
-
-				var position = geometryAttributes[ "position" ];
-
-				// render particles
-
-				_gl.drawArrays( _gl.POINTS, 0, position.numItems / 3 );
-
-				_this.info.render.calls ++;
-				_this.info.render.points += position.numItems / 3;
-
-			}
-
-		} else if ( object instanceof THREE.Line ) {
-
-			if ( updateBuffers ) {
-
-				for ( attributeName in geometryAttributes ) {
-
-					attributePointer = programAttributes[ attributeName ];
-					attributeItem = geometryAttributes[ attributeName ];
-					attributeSize = attributeItem.itemSize;
-
-					if ( attributePointer >= 0 ) {
-
-						_gl.bindBuffer( _gl.ARRAY_BUFFER, attributeItem.buffer );
-						enableAttribute( attributePointer );
-						_gl.vertexAttribPointer( attributePointer, attributeSize, _gl.FLOAT, false, 0, 0 );
-
-					}
-
-				}
-
-				// render lines
-
-				setLineWidth( material.linewidth );
-
-				var position = geometryAttributes[ "position" ];
-
-				_gl.drawArrays( _gl.LINE_STRIP, 0, position.numItems / 3 );
-
-				_this.info.render.calls ++;
-				_this.info.render.points += position.numItems;
-
-			}
-
-    	}
-
-	};
-
-	this.renderBuffer = function ( camera, lights, fog, material, geometryGroup, object ) {
-
-		if ( material.visible === false ) return;
-
-		var program, attributes, linewidth, primitives, a, attribute, i, il;
-
-		program = setProgram( camera, lights, fog, material, object );
-
-		attributes = program.attributes;
-
-		var updateBuffers = false,
-			wireframeBit = material.wireframe ? 1 : 0,
-			geometryGroupHash = ( geometryGroup.id * 0xffffff ) + ( program.id * 2 ) + wireframeBit;
-
-		if ( geometryGroupHash !== _currentGeometryGroupHash ) {
-
-			_currentGeometryGroupHash = geometryGroupHash;
-			updateBuffers = true;
-
-		}
-
-		if ( updateBuffers ) {
-
-			disableAttributes();
-
-		}
-
-		// vertices
-
-		if ( !material.morphTargets && attributes.position >= 0 ) {
-
-			if ( updateBuffers ) {
-
-				_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglVertexBuffer );
-				enableAttribute( attributes.position );
-				_gl.vertexAttribPointer( attributes.position, 3, _gl.FLOAT, false, 0, 0 );
-
-			}
-
-		} else {
-
-			if ( object.morphTargetBase ) {
-
-				setupMorphTargets( material, geometryGroup, object );
-
-			}
-
-		}
-
-
-		if ( updateBuffers ) {
-
-			// custom attributes
-
-			// Use the per-geometryGroup custom attribute arrays which are setup in initMeshBuffers
-
-			if ( geometryGroup.__webglCustomAttributesList ) {
-
-				for ( i = 0, il = geometryGroup.__webglCustomAttributesList.length; i < il; i ++ ) {
-
-					attribute = geometryGroup.__webglCustomAttributesList[ i ];
-
-					if ( attributes[ attribute.buffer.belongsToAttribute ] >= 0 ) {
-
-						_gl.bindBuffer( _gl.ARRAY_BUFFER, attribute.buffer );
-						enableAttribute( attributes[ attribute.buffer.belongsToAttribute ] );
-						_gl.vertexAttribPointer( attributes[ attribute.buffer.belongsToAttribute ], attribute.size, _gl.FLOAT, false, 0, 0 );
-
-					}
-
-				}
-
-			}
-
-
-			// colors
-
-			if ( attributes.color >= 0 ) {
-
-				_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglColorBuffer );
-				enableAttribute( attributes.color );
-				_gl.vertexAttribPointer( attributes.color, 3, _gl.FLOAT, false, 0, 0 );
-
-			}
-
-			// normals
-
-			if ( attributes.normal >= 0 ) {
-
-				_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglNormalBuffer );
-				enableAttribute( attributes.normal );
-				_gl.vertexAttribPointer( attributes.normal, 3, _gl.FLOAT, false, 0, 0 );
-
-			}
-
-			// tangents
-
-			if ( attributes.tangent >= 0 ) {
-
-				_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglTangentBuffer );
-				enableAttribute( attributes.tangent );
-				_gl.vertexAttribPointer( attributes.tangent, 4, _gl.FLOAT, false, 0, 0 );
-
-			}
-
-			// uvs
-
-			if ( attributes.uv >= 0 ) {
-
-				_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglUVBuffer );
-				enableAttribute( attributes.uv );
-				_gl.vertexAttribPointer( attributes.uv, 2, _gl.FLOAT, false, 0, 0 );
-
-			}
-
-			if ( attributes.uv2 >= 0 ) {
-
-				_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglUV2Buffer );
-				enableAttribute( attributes.uv2 );
-				_gl.vertexAttribPointer( attributes.uv2, 2, _gl.FLOAT, false, 0, 0 );
-
-			}
-
-			if ( material.skinning &&
-				 attributes.skinIndex >= 0 && attributes.skinWeight >= 0 ) {
-
-				_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglSkinIndicesBuffer );
-				enableAttribute( attributes.skinIndex );
-				_gl.vertexAttribPointer( attributes.skinIndex, 4, _gl.FLOAT, false, 0, 0 );
+/**
+ * @author supereggbert / http://www.paulbrunt.co.uk/
+ * @author mrdoob / http://mrdoob.com/
+ * @author alteredq / http://alteredqualia.com/
+ * @author szimek / https://github.com/szimek/
+ * @author gero3 / https://github.com/gero3/
+ */
+
+THREE.WebGLRenderer = function ( parameters ) {
+
+	console.log( 'THREE.WebGLRenderer', THREE.REVISION );
+
+	parameters = parameters || {};
+
+	var info = {
+
+		memory: {
+
+			programs: 0,
+			geometries: 0,
+			textures: 0
+
+		},
+
+		render: {
+
+			calls: 0,
+			vertices: 0,
+			faces: 0,
+			points: 0
+
+		}
+
+	};
+
+
+	var renderer = new THREE.WebGLRenderer.LowLevelRenderer(parameters);
+	var meshRenderer = new THREE.WebGLRenderer.MeshRenderer(renderer, info);
+	var particleRenderer = new THREE.WebGLRenderer.ParticleRenderer(renderer, info);
+	var lineRenderer = new THREE.WebGLRenderer.LineRenderer(renderer, info);
+	var ribbonRenderer = new THREE.WebGLRenderer.RibbonRenderer(renderer, info);
+
+	var shaderBuilder = new THREE.WebGLRenderer.ShaderBuilder(renderer, info);
+
+	// clearing
+
+	this.autoClear = true;
+	this.autoClearColor = true;
+	this.autoClearDepth = true;
+	this.autoClearStencil = true;
+
+	// scene graph
+
+	this.sortObjects = true;
+
+	this.autoUpdateObjects = true;
+	this.autoUpdateScene = true;
+
+	// physically based shading
+
+	this.gammaInput = false;
+	this.gammaOutput = false;
+	this.physicallyBasedShading = false;
+
+	// shadow map
+
+	this.shadowMapEnabled = false;
+	this.shadowMapAutoUpdate = true;
+	this.shadowMapType = THREE.PCFShadowMap;
+	this.shadowMapCullFace = THREE.CullFaceFront;
+	this.shadowMapDebug = false;
+	this.shadowMapCascade = false;
+
+	// morphs
+
+	this.maxMorphTargets = 8;
+	this.maxMorphNormals = 4;
+
+	// flags
+
+	this.autoScaleCubemaps = true;
+
+	// custom render plugins
+
+	this.renderPluginsPre = [];
+	this.renderPluginsPost = [];
+
+	// info
+
+	this.info = info;
+
+
+	// internal properties
+
+	var _this = this,
+
+	// internal state cache
+
+	_currentProgram = null,
+	_currentFramebuffer = null,
+	_currentMaterialId = -1,
+	_currentGeometryGroupHash = null,
+	_currentCamera = null,
+	_geometryGroupCounter = 0,
+
+	_usedTextureUnits = 0,
+
+	// GL state
+
+	_viewportX = 0,
+	_viewportY = 0,
+	_viewportWidth = 0,
+	_viewportHeight = 0,
+	_currentWidth = 0,
+	_currentHeight = 0,
+
+	_enabledAttributes = {},
+
+	// frustum
+
+	_frustum = new THREE.Frustum(),
+
+	 // camera matrices cache
+
+	_projScreenMatrix = new THREE.Matrix4(),
+	_projScreenMatrixPS = new THREE.Matrix4(),
+
+	_vector3 = new THREE.Vector3(),
+
+	// light arrays cache
+
+	_direction = new THREE.Vector3(),
+
+	_lightsNeedUpdate = true,
+
+	_lights = {
+
+		ambient: [ 0, 0, 0 ],
+		directional: { length: 0, colors: [], positions: [] },
+		point: { length: 0, colors: [], positions: [], distances: [] },
+		spot: { length: 0, colors: [], positions: [], distances: [], directions: [], anglesCos: [], exponents: [] },
+		hemi: { length: 0, skyColors: [], groundColors: [], positions: [] }
+
+	};
+
+	// initialize
+
+	this.context = renderer.getContext();
+	this.domElement = renderer.getDomElement();
+	this.getPrecision = renderer.getPrecision;
+
+	// low level API
+
+	this.getPrecision = renderer.getPrecision;
+	this.getContext = renderer.getContext;
+	this.supportsVertexTextures = renderer.supportsVertexTextures;
+	this.supportsFloatTextures = renderer.supportsFloatTextures;
+	this.supportsStandardDerivatives = renderer.supportsStandardDerivatives;
+	this.supportsCompressedTextureS3TC = renderer.supportsCompressedTextureS3TC;
+	this.getMaxAnisotropy  = renderer.getMaxAnisotropy;
+	this.setSize = renderer.setSize;
+	this.setViewport = renderer.setViewport;
+	this.setScissor = renderer.setScissor;
+	this.enableScissorTest = renderer.enableScissorTest;
+	this.setDepthWrite = renderer.setDepthWrite;
+	this.setDepthTest = renderer.setDepthTest;
+	this.setRenderTarget = renderer.setRenderTarget;
+	this.setBlending = renderer.setBlending;
+	this.setTexture = renderer.setTexture;
+	this.setMaterialFaces = renderer.setMaterialFaces;
+	this.setFaceCulling = renderer.setFaceCulling;
+
+	// Clearing
+
+	this.setClearColorHex = renderer.setClearColorHex;
+	this.setClearColor = renderer.setClearColor;
+	this.getClearColor = renderer.getClearColor;
+	this.getClearAlpha = renderer.getClearAlpha;
+	this.clear = renderer.clear;
+	this.clearTarget = renderer.clearTarget;
+
+	// Plugins
+
+	this.addPostPlugin = function ( plugin ) {
+
+		plugin.init( this );
+		this.renderPluginsPost.push( plugin );
+
+	};
+
+	this.addPrePlugin = function ( plugin ) {
+
+		plugin.init( this );
+		this.renderPluginsPre.push( plugin );
+
+	};
+
+	// Rendering
+
+	this.updateShadowMap = function ( scene, camera ) {
+
+		_currentProgram = null;
+		_currentGeometryGroupHash = -1;
+		_currentMaterialId = -1;
+		_lightsNeedUpdate = true;
+
+		renderer.resetState();
+
+
+		this.shadowMapPlugin.update( scene, camera );
+
+	};
+
+	// Events
+
+	var onGeometryDispose = function ( event ) {
+
+		var geometry = event.target;
+
+		geometry.removeEventListener( 'dispose', onGeometryDispose );
+
+		deallocateGeometry( geometry );
+
+		_this.info.memory.geometries --;
+
+	};
+
+	var onTextureDispose = function ( event ) {
+
+		var texture = event.target;
+
+		texture.removeEventListener( 'dispose', onTextureDispose );
+
+		deallocateTexture( texture );
+
+		_this.info.memory.textures --;
+
+
+	};
+
+	var onRenderTargetDispose = function ( event ) {
+
+		var renderTarget = event.target;
+
+		renderTarget.removeEventListener( 'dispose', onRenderTargetDispose );
+
+		deallocateRenderTarget( renderTarget );
+
+		_this.info.memory.textures --;
+
+	};
+
+	var onMaterialDispose = function ( event ) {
+
+		var material = event.target;
+
+		material.removeEventListener( 'dispose', onMaterialDispose );
+
+		deallocateMaterial( material );
+
+	};
+
+	// Buffer deallocation
+
+	var deallocateGeometry = function ( geometry ) {
+
+		var m,ml;
+		geometry.__webglInit = undefined;
+
+		if ( geometry.__webglVertexBuffer !== undefined ) renderer.deleteBuffer( geometry.__webglVertexBuffer );
+		if ( geometry.__webglNormalBuffer !== undefined ) renderer.deleteBuffer( geometry.__webglNormalBuffer );
+		if ( geometry.__webglTangentBuffer !== undefined ) renderer.deleteBuffer( geometry.__webglTangentBuffer );
+		if ( geometry.__webglColorBuffer !== undefined ) renderer.deleteBuffer( geometry.__webglColorBuffer );
+		if ( geometry.__webglUVBuffer !== undefined ) renderer.deleteBuffer( geometry.__webglUVBuffer );
+		if ( geometry.__webglUV2Buffer !== undefined ) renderer.deleteBuffer( geometry.__webglUV2Buffer );
+
+		if ( geometry.__webglSkinIndicesBuffer !== undefined ) renderer.deleteBuffer( geometry.__webglSkinIndicesBuffer );
+		if ( geometry.__webglSkinWeightsBuffer !== undefined ) renderer.deleteBuffer( geometry.__webglSkinWeightsBuffer );
+
+		if ( geometry.__webglFaceBuffer !== undefined ) renderer.deleteBuffer( geometry.__webglFaceBuffer );
+		if ( geometry.__webglLineBuffer !== undefined ) renderer.deleteBuffer( geometry.__webglLineBuffer );
+
+		if ( geometry.__webglLineDistanceBuffer !== undefined ) renderer.deleteBuffer( geometry.__webglLineDistanceBuffer );
+
+		// geometry groups
+
+		if ( geometry.geometryGroups !== undefined ) {
+
+			for ( var g in geometry.geometryGroups ) {
+
+				var geometryGroup = geometry.geometryGroups[ g ];
+
+				if ( geometryGroup.numMorphTargets !== undefined ) {
+
+					for ( m = 0, ml = geometryGroup.numMorphTargets; m < ml; m ++ ) {
+
+						renderer.deleteBuffer( geometryGroup.__webglMorphTargetsBuffers[ m ] );
+
+					}
+
+				}
+
+				if ( geometryGroup.numMorphNormals !== undefined ) {
+
+					for ( m = 0, ml = geometryGroup.numMorphNormals; m < ml; m ++ ) {
+
+						renderer.deleteBuffer( geometryGroup.__webglMorphNormalsBuffers[ m ] );
+
+					}
+
+				}
+
+				deleteCustomAttributesBuffers( geometryGroup );
+
+			}
+
+		}
+
+		deleteCustomAttributesBuffers( geometry );
+
+	};
+
+	var deallocateTexture = function ( texture ) {
+
+		if ( texture.image && texture.image.__webglTextureCube ) {
+
+			// cube texture
+
+			renderer.deleteTexture( texture.image.__webglTextureCube );
+
+		} else {
+
+			// 2D texture
+
+			if ( ! texture.__webglInit ) return;
+
+			texture.__webglInit = false;
+			renderer.deleteTexture( texture.__webglTexture );
+
+		}
+
+	};
+
+	var deallocateRenderTarget = function ( renderTarget ) {
+
+		if ( !renderTarget || ! renderTarget.__webglTexture ) return;
+
+		renderer.deleteTexture( renderTarget.__webglTexture );
+
+		if ( renderTarget instanceof THREE.WebGLRenderTargetCube ) {
+
+			for ( var i = 0; i < 6; i ++ ) {
+
+				renderer.deleteFramebuffer( renderTarget.__webglFramebuffer[ i ] );
+				renderer.deleteRenderbuffer( renderTarget.__webglRenderbuffer[ i ] );
+
+			}
+
+		} else {
+
+			renderer.deleteFramebuffer( renderTarget.__webglFramebuffer );
+			renderer.deleteRenderbuffer( renderTarget.__webglRenderbuffer );
+
+		}
+
+	};
+
+	var deallocateMaterial = function ( material ) {
+
+		var program = material.program;
+
+		if ( program === undefined ) return;
+
+		material.program = undefined;
+
+		// only deallocate GL program if this was the last use of shared program
+		// assumed there is only single copy of any program in the _programs list
+		// (that's how it's constructed)
+
+		shaderBuilder.removeProgram(program)
+
+	};
+
+
+	function deleteCustomAttributesBuffers( geometry ) {
+
+		if ( geometry.__webglCustomAttributesList ) {
+
+			for ( var id in geometry.__webglCustomAttributesList ) {
+
+				renderer.deleteBuffer( geometry.__webglCustomAttributesList[ id ].buffer );
+
+			}
+
+		}
+
+	};
+
+	// Buffer initialization
+
+	function initCustomAttributes ( geometry, object ) {
+
+		var nvertices = geometry.vertices.length;
+
+		var material = object.material;
+
+		if ( material.attributes ) {
+
+			if ( geometry.__webglCustomAttributesList === undefined ) {
+
+				geometry.__webglCustomAttributesList = [];
+
+			}
+
+			for ( var a in material.attributes ) {
+
+				var attribute = material.attributes[ a ];
+
+				if ( !attribute.__webglInitialized || attribute.createUniqueBuffers ) {
+
+					attribute.__webglInitialized = true;
+
+					var size = 1;		// "f" and "i"
+
+					if ( attribute.type === "v2" ) size = 2;
+					else if ( attribute.type === "v3" ) size = 3;
+					else if ( attribute.type === "v4" ) size = 4;
+					else if ( attribute.type === "c"  ) size = 3;
+
+					attribute.size = size;
+
+					attribute.array = new Float32Array( nvertices * size );
+
+					attribute.buffer = renderer.createBuffer();
+					attribute.buffer.belongsToAttribute = a;
+
+					attribute.needsUpdate = true;
+
+				}
+
+				geometry.__webglCustomAttributesList.push( attribute );
+
+			}
+
+		}
+
+	};
+
+	function getBufferMaterial( object, geometryGroup ) {
+
+		return object.material instanceof THREE.MeshFaceMaterial
+			? object.material.materials[ geometryGroup.materialIndex ]
+			: object.material;
+
+	};
+
+	//
+
+	function initDirectBuffers( geometry ) {
+
+		var a, attribute;
+
+		for ( a in geometry.attributes ) {
+
+			attribute = geometry.attributes[ a ];
+
+			attribute.buffer = renderer.createBuffer();
+
+			if ( a === "index" ) {
+
+				renderer.setStaticIndexBuffer(attribute.buffer,attribute.array);
+
+			} else {
+
+				renderer.setStaticArrayBuffer(attribute.buffer,attribute.array);
+
+			}
+
+		}
+
+	};
+
+	// Buffer setting
+
+	function setDirectBuffers ( geometry, dispose ) {
+
+		var attributes = geometry.attributes;
+
+		var attributeName, attributeItem;
+
+		for ( attributeName in attributes ) {
+
+			attributeItem = attributes[ attributeName ];
+
+			if ( attributeItem.needsUpdate ) {
+
+				if ( attributeName === 'index' ) {
+
+					renderer.setDynamicIndexBuffer(	attributeItem.buffer, attributeItem.array );
+
+				} else {
+
+					renderer.setDynamicArrayBuffer( attributeItem.buffer,  attributeItem.array );
+
+				}
+
+				attributeItem.needsUpdate = false;
+
+			}
+
+			if ( dispose && ! attributeItem.dynamic ) {
+
+				delete attributeItem.array;
+
+			}
+
+		}
+
+	};
+
+	// Buffer rendering
+
+	this.renderBufferImmediate = function ( object, program, material ) {
+
+		if ( object.hasPositions && ! object.__webglVertexBuffer ) object.__webglVertexBuffer = renderer.createBuffer();
+		if ( object.hasNormals && ! object.__webglNormalBuffer ) object.__webglNormalBuffer = renderer.createBuffer();
+		if ( object.hasUvs && ! object.__webglUvBuffer ) object.__webglUvBuffer = renderer.createBuffer();
+		if ( object.hasColors && ! object.__webglColorBuffer ) object.__webglColorBuffer = renderer.createBuffer();
+
+		if ( object.hasPositions ) {
+
+			renderer.setDynamicArrayBuffer( object.__webglVertexBuffer, object.positionArray);
+			renderer.setFloatAttribute(program.attributes.position, object.__webglVertexBuffer, 3, 0);
+
+		}
+
+		if ( object.hasNormals ) {
+
+			if ( material.shading === THREE.FlatShading ) {
+
+				var nx, ny, nz,
+					nax, nbx, ncx, nay, nby, ncy, naz, nbz, ncz,
+					normalArray,
+					i, il = object.count * 3;
+
+				for( i = 0; i < il; i += 9 ) {
+
+					normalArray = object.normalArray;
+
+					nax  = normalArray[ i ];
+					nay  = normalArray[ i + 1 ];
+					naz  = normalArray[ i + 2 ];
+
+					nbx  = normalArray[ i + 3 ];
+					nby  = normalArray[ i + 4 ];
+					nbz  = normalArray[ i + 5 ];
+
+					ncx  = normalArray[ i + 6 ];
+					ncy  = normalArray[ i + 7 ];
+					ncz  = normalArray[ i + 8 ];
+
+					nx = ( nax + nbx + ncx ) / 3;
+					ny = ( nay + nby + ncy ) / 3;
+					nz = ( naz + nbz + ncz ) / 3;
+
+					normalArray[ i ] 	 = nx;
+					normalArray[ i + 1 ] = ny;
+					normalArray[ i + 2 ] = nz;
+
+					normalArray[ i + 3 ] = nx;
+					normalArray[ i + 4 ] = ny;
+					normalArray[ i + 5 ] = nz;
+
+					normalArray[ i + 6 ] = nx;
+					normalArray[ i + 7 ] = ny;
+					normalArray[ i + 8 ] = nz;
+
+				}
+
+			}
+
+			renderer.setDynamicArrayBuffer( object.__webglNormalBuffer, object.normalArray);
+			renderer.setFloatAttribute(program.attributes.normal, object.__webglNormalBuffer, 3, 0);
+
+		}
+
+		if ( object.hasUvs && material.map ) {
+
+			renderer.setDynamicArrayBuffer( object.__webglUvBuffer, object.uvArray);
+			renderer.setFloatAttribute(program.attributes.uv, object.__webglUvBuffer, 2, 0);
+
+		}
+
+		if ( object.hasColors && material.vertexColors !== THREE.NoColors ) {
+
+			renderer.setDynamicArrayBuffer( object.__webglColorBuffer, object.colorArray);
+			renderer.setFloatAttribute(program.attributes.color, object.__webglColorBuffer, 3, 0);
+
+		}
+
+		renderer.drawTriangles(object.count );
+		object.count = 0;
+
+	};
+
+	this.renderBufferDirect = function ( camera, lights, fog, material, geometry, object ) {
+
+		if ( material.visible === false ) return;
+
+		var program, programAttributes, linewidth, primitives, a, attribute, geometryAttributes;
+		var attributeItem, attributeName, attributePointer, attributeSize;
+
+		program = setProgram( camera, lights, fog, material, object );
+
+		programAttributes = program.attributes;
+		geometryAttributes = geometry.attributes;
+
+		var updateBuffers = false,
+			wireframeBit = material.wireframe ? 1 : 0,
+			geometryHash = ( geometry.id * 0xffffff ) + ( program.id * 2 ) + wireframeBit;
+
+		if ( geometryHash !== _currentGeometryGroupHash ) {
+
+			_currentGeometryGroupHash = geometryHash;
+			updateBuffers = true;
+
+		}
+
+		if ( updateBuffers ) {
+
+			renderer.disableAttributes();
+
+		}
+
+		// render mesh
+
+		if ( object instanceof THREE.Mesh ) {
+
+			var index = geometryAttributes[ "index" ];
+
+			// indexed triangles
+
+			if ( index ) {
+
+				var offsets = geometry.offsets;
+
+				// if there is more than 1 chunk
+				// must set attribute pointers to use new offsets for each chunk
+				// even if geometry and materials didn't change
+
+				if ( offsets.length > 1 ) updateBuffers = true;
+
+				for ( var i = 0, il = offsets.length; i < il; i ++ ) {
+
+					var startIndex = offsets[ i ].index;
+
+					if ( updateBuffers ) {
+
+						for ( attributeName in geometryAttributes ) {
+
+							if ( attributeName === 'index' ) continue;
+
+							attributePointer = programAttributes[ attributeName ];
+							attributeItem = geometryAttributes[ attributeName ];
+							attributeSize = attributeItem.itemSize;
+
+							if ( attributePointer >= 0 ) {
+
+								renderer.setFloatAttribute( attributePointer , attributeItem.buffer, attributeSize, startIndex * attributeSize * 4 );
+
+							}
+
+						}
+					}
+
+					// render indexed triangles
+
+					renderer.drawTriangleElements(index.buffer, offsets[ i ].count, offsets[ i ].start * 2);
+
+					_this.info.render.calls ++;
+					_this.info.render.vertices += offsets[ i ].count; // not really true, here vertices can be shared
+					_this.info.render.faces += offsets[ i ].count / 3;
+
+				}
+
+			// non-indexed triangles
+
+			} else {
+
+				if ( updateBuffers ) {
+
+					for ( attributeName in geometryAttributes ) {
+
+						attributePointer = programAttributes[ attributeName ];
+						attributeItem = geometryAttributes[ attributeName ];
+						attributeSize = attributeItem.itemSize;
+
+						if ( attributePointer >= 0 ) {
+
+							renderer.setFloatAttribute( attributePointer , attributeItem.buffer, attributeSize, 0 );
+
+						}
+
+					}
+
+				}
+
+				var position = geometry.attributes[ "position" ];
+
+				// render non-indexed triangles
+
+				renderer.drawTriangles( position.numItems / 3)
+
+				_this.info.render.calls ++;
+				_this.info.render.vertices += position.numItems / 3;
+				_this.info.render.faces += position.numItems / 3 / 3;
+
+			}
+
+		// render particles
+
+		} else if ( object instanceof THREE.ParticleSystem ) {
+
+			if ( updateBuffers ) {
+
+				for ( attributeName in geometryAttributes ) {
+
+					attributePointer = programAttributes[ attributeName ];
+					attributeItem = geometryAttributes[ attributeName ];
+					attributeSize = attributeItem.itemSize;
+
+					if ( attributePointer >= 0 ) {
+
+						renderer.setFloatAttribute( attributePointer , attributeItem.buffer, attributeSize, 0 );
+
+					}
+
+				}
+
+				var position = geometryAttributes[ "position" ];
+
+				// render particles
+				renderer.drawPoints(position.numItems / 3);
+
+				_this.info.render.calls ++;
+				_this.info.render.points += position.numItems / 3;
+
+			}
+
+		} else if ( object instanceof THREE.Line ) {
+
+			if ( updateBuffers ) {
+
+				for ( attributeName in geometryAttributes ) {
+
+					attributePointer = programAttributes[ attributeName ];
+					attributeItem = geometryAttributes[ attributeName ];
+					attributeSize = attributeItem.itemSize;
+
+					if ( attributePointer >= 0 ) {
+
+						renderer.setFloatAttribute( attributePointer , attributeItem.buffer, attributeSize, 0 );
+
+					}
+
+				}
+
+				var position = geometryAttributes[ "position" ];
+
+				// render lines
+				renderer.setLineWidth( material.linewidth );
+				renderer.drawLineStrip(position.numItems / 3);
+
+				_this.info.render.calls ++;
+				_this.info.render.points += position.numItems;
+
+			}
+
+		}
+
+	};
+
+	this.renderBuffer = function ( camera, lights, fog, material, geometryGroup, object ) {
+
+		if ( material.visible === false ) return;
+
+		var program, attributes, linewidth, primitives, a, attribute, i, il;
+
+		program = setProgram( camera, lights, fog, material, object );
+
+		attributes = program.attributes;
+
+		var updateBuffers = false,
+			wireframeBit = material.wireframe ? 1 : 0,
+			geometryGroupHash = ( geometryGroup.id * 0xffffff ) + ( program.id * 2 ) + wireframeBit;
+
+		if ( geometryGroupHash !== _currentGeometryGroupHash ) {
+
+			_currentGeometryGroupHash = geometryGroupHash;
+			updateBuffers = true;
+
+		}
+
+		if ( updateBuffers ) {
+
+			renderer.disableAttributes();
+
+		}
+
+		// vertices
+
+		if ( !material.morphTargets && attributes.position >= 0 ) {
+
+			if ( updateBuffers ) {
+
+				renderer.setFloatAttribute(attributes.position , geometryGroup.__webglVertexBuffer, 3, 0);
+
+			}
+
+		} else {
+
+			if ( object.morphTargetBase ) {
+
+				setupMorphTargets( material, geometryGroup, object );
+
+			}
+
+		}
+
+
+		if ( updateBuffers ) {
+
+			// custom attributes
+
+			// Use the per-geometryGroup custom attribute arrays which are setup in initMeshBuffers
+
+			if ( geometryGroup.__webglCustomAttributesList ) {
+
+				for ( i = 0, il = geometryGroup.__webglCustomAttributesList.length; i < il; i ++ ) {
+
+					attribute = geometryGroup.__webglCustomAttributesList[ i ];
+
+					if ( attributes[ attribute.buffer.belongsToAttribute ] >= 0 ) {
+
+						renderer.setFloatAttribute(attributes[ attribute.buffer.belongsToAttribute ] , attribute.buffer, attribute.size, 0);
+
+					}
+
+				}
+
+			}
+
+
+			// colors
+
+			if ( attributes.color >= 0 ) {
+
+				renderer.setFloatAttribute(attributes.color , geometryGroup.__webglColorBuffer,3, 0);
+
+			}
+
+			// normals
+
+			if ( attributes.normal >= 0 ) {
+
+				renderer.setFloatAttribute(attributes.normal, geometryGroup.__webglNormalBuffer, 3, 0);
+
+			}
+
+			// tangents
+
+			if ( attributes.tangent >= 0 ) {
+
+				renderer.setFloatAttribute(attributes.tangent, geometryGroup.__webglTangentBuffer, 4, 0);
+
+			}
+
+			// uvs
+
+			if ( attributes.uv >= 0 ) {
+
+				renderer.setFloatAttribute(attributes.uv, geometryGroup.__webglUVBuffer, 2, 0);
+
+			}
+
+			if ( attributes.uv2 >= 0 ) {
+
+				renderer.setFloatAttribute(attributes.uv2, geometryGroup.__webglUV2Buffer, 2, 0);
+
+			}
+
+			if ( material.skinning &&
+				 attributes.skinIndex >= 0 && attributes.skinWeight >= 0 ) {
+
+				renderer.setFloatAttribute(attributes.skinIndex, geometryGroup.__webglSkinIndicesBuffer, 4, 0);
+				renderer.setFloatAttribute(attributes.skinWeight, geometryGroup.__webglSkinWeightsBuffer, 4, 0);
+
+			}
+
+			// line distances
+
+			if ( attributes.lineDistance >= 0 ) {
+
+				renderer.setFloatAttribute(attributes.lineDistance, geometryGroup.__webglLineDistanceBuffer, 1, 0);
+
+			}
+
+		}
+
+		// render mesh
+
+		if ( object instanceof THREE.Mesh ) {
+
+			// wireframe
+
+			if ( material.wireframe ) {
+
+				renderer.setLineWidth( material.wireframeLinewidth );
+				renderer.drawLineElements(geometryGroup.__webglLineBuffer,geometryGroup.__webglLineCount,0);
+
+			// triangles
+
+			} else {
+
+				renderer.drawTriangleElements( geometryGroup.__webglFaceBuffer, geometryGroup.__webglFaceCount, 0);
+
+			}
+
+			_this.info.render.calls ++;
+			_this.info.render.vertices += geometryGroup.__webglFaceCount;
+			_this.info.render.faces += geometryGroup.__webglFaceCount / 3;
+
+		// render lines
+
+		} else if ( object instanceof THREE.Line ) {
+
+			renderer.setLineWidth( material.linewidth );
+
+			if (object.type === THREE.LineStrip) {
+
+				renderer.drawLineStrip(geometryGroup.__webglLineCount);
+
+			} else {
+
+				renderer.drawLines(geometryGroup.__webglLineCount);
+
+			}
+
+			_this.info.render.calls ++;
+
+		// render particles
+
+		} else if ( object instanceof THREE.ParticleSystem ) {
+
+			renderer.drawPoints(geometryGroup.__webglParticleCount);
+
+			_this.info.render.calls ++;
+			_this.info.render.points += geometryGroup.__webglParticleCount;
+
+		// render ribbon
+
+		} else if ( object instanceof THREE.Ribbon ) {
+
+			renderer.drawTriangleStrip(geometryGroup.__webglVertexCount);
+
+			_this.info.render.calls ++;
+
+		}
+
+	};
+
+	function setupMorphTargets ( material, geometryGroup, object ) {
+
+		// set base
+
+		var attributes = material.program.attributes;
+
+		if ( object.morphTargetBase !== -1 && attributes.position >= 0 ) {
+
+			renderer.setFloatAttribute(attributes.position, geometryGroup.__webglMorphTargetsBuffers[ object.morphTargetBase ], 3, 0);
+
+		} else if ( attributes.position >= 0 ) {
+
+			renderer.setFloatAttribute(attributes.position, geometryGroup.__webglVertexBuffer, 3, 0);
+
+		}
+
+		if ( object.morphTargetForcedOrder.length ) {
+
+			// set forced order
+
+			var m = 0;
+			var order = object.morphTargetForcedOrder;
+			var influences = object.morphTargetInfluences;
+
+			while ( m < material.numSupportedMorphTargets && m < order.length ) {
+
+				if ( attributes[ "morphTarget" + m ] >= 0 ) {
+
+					renderer.setFloatAttribute(attributes[ "morphTarget" + m ], geometryGroup.__webglMorphTargetsBuffers[ order[ m ] ], 3, 0);
+
+				}
+
+				if ( attributes[ "morphNormal" + m ] >= 0 && material.morphNormals ) {
+
+					renderer.setFloatAttribute(attributes[ "morphNormal" + m ], geometryGroup.__webglMorphNormalsBuffers[ order[ m ] ], 3, 0);
+
+				}
+
+				object.__webglMorphTargetInfluences[ m ] = influences[ order[ m ] ];
+
+				m ++;
+			}
+
+		} else {
+
+			// find the most influencing
+
+			var influence, activeInfluenceIndices = [];
+			var influences = object.morphTargetInfluences;
+			var i, il = influences.length;
+
+			for ( i = 0; i < il; i ++ ) {
+
+				influence = influences[ i ];
+
+				if ( influence > 0 ) {
+
+					activeInfluenceIndices.push( [ influence, i ] );
+
+				}
+
+			}
+
+			if ( activeInfluenceIndices.length > material.numSupportedMorphTargets ) {
+
+				activeInfluenceIndices.sort( numericalSort );
+				activeInfluenceIndices.length = material.numSupportedMorphTargets;
+
+			} else if ( activeInfluenceIndices.length > material.numSupportedMorphNormals ) {
+
+				activeInfluenceIndices.sort( numericalSort );
+
+			} else if ( activeInfluenceIndices.length === 0 ) {
+
+				activeInfluenceIndices.push( [ 0, 0 ] );
+
+			};
+
+			var influenceIndex, m = 0;
+
+			while ( m < material.numSupportedMorphTargets ) {
+
+				if ( activeInfluenceIndices[ m ] ) {
+
+					influenceIndex = activeInfluenceIndices[ m ][ 1 ];
+
+					if ( attributes[ "morphTarget" + m ] >= 0 ) {
+
+						renderer.setFloatAttribute(attributes[ "morphTarget" + m ], geometryGroup.__webglMorphTargetsBuffers[ influenceIndex ], 3, 0);
+
+					}
+
+					if ( attributes[ "morphNormal" + m ] >= 0 && material.morphNormals ) {
+
+						renderer.setFloatAttribute(attributes[ "morphNormal" + m ], geometryGroup.__webglMorphNormalsBuffers[ influenceIndex ], 3, 0);
+
+					}
+
+					object.__webglMorphTargetInfluences[ m ] = influences[ influenceIndex ];
+
+				} else {
+
+					/*
+					_gl.vertexAttribPointer( attributes[ "morphTarget" + m ], 3, _gl.FLOAT, false, 0, 0 );
+
+					if ( material.morphNormals ) {
+
+						_gl.vertexAttribPointer( attributes[ "morphNormal" + m ], 3, _gl.FLOAT, false, 0, 0 );
+
+					}
+					*/
+
+					object.__webglMorphTargetInfluences[ m ] = 0;
+
+				}
+
+				m ++;
+
+			}
+
+		}
+
+		// load updated influences uniform
+
+		if ( material.program.uniforms.morphTargetInfluences !== null ) {
+
+			renderer.uniform1fv( material.program.uniforms.morphTargetInfluences, object.__webglMorphTargetInfluences );
+
+		}
+
+	};
+
+	// Sorting
+
+	function painterSortStable ( a, b ) {
+
+		if ( a.z !== b.z ) {
+
+			return b.z - a.z;
+
+		} else {
+
+			return a.id - b.id;
+
+		}
+
+	};
+
+	function numericalSort ( a, b ) {
+
+		return b[ 0 ] - a[ 0 ];
+
+	};
+
+
+	// Rendering
+
+	this.render = function ( scene, camera, renderTarget, forceClear ) {
+
+		if ( camera instanceof THREE.Camera === false ) {
+
+			console.error( 'THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.' );
+			return;
+
+		}
+
+		var i, il,
+
+		webglObject, object,
+		renderList,
+
+		lights = scene.__lights,
+		fog = scene.fog;
+
+		// reset caching for this frame
+
+		_currentMaterialId = -1;
+		_lightsNeedUpdate = true;
+
+		// update scene graph
+
+		if ( this.autoUpdateScene ) scene.updateMatrixWorld();
+
+		// update camera matrices and frustum
+
+		if ( camera.parent === undefined ) camera.updateMatrixWorld();
+
+		camera.matrixWorldInverse.getInverse( camera.matrixWorld );
+
+		_projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
+		_frustum.setFromMatrix( _projScreenMatrix );
+
+		// update WebGL objects
+
+		if ( this.autoUpdateObjects ) this.initWebGLObjects( scene );
+
+		// custom render plugins (pre pass)
+
+		renderPlugins( this.renderPluginsPre, scene, camera );
+
+		//
+
+		_this.info.render.calls = 0;
+		_this.info.render.vertices = 0;
+		_this.info.render.faces = 0;
+		_this.info.render.points = 0;
+
+		renderer.setRenderTarget( renderTarget );
+
+		if ( this.autoClear || forceClear ) {
+
+			this.clear( this.autoClearColor, this.autoClearDepth, this.autoClearStencil );
+
+		}
+
+		// set matrices for regular objects (frustum culled)
+
+		renderList = scene.__webglObjects;
+
+		for ( i = 0, il = renderList.length; i < il; i ++ ) {
+
+			webglObject = renderList[ i ];
+			object = webglObject.object;
+
+			webglObject.id = i;
+			webglObject.render = false;
+
+			if ( object.visible ) {
+
+				if ( ! ( object instanceof THREE.Mesh || object instanceof THREE.ParticleSystem ) || ! ( object.frustumCulled ) || _frustum.intersectsObject( object ) ) {
+
+					setupMatrices( object, camera );
+
+					unrollBufferMaterial( webglObject );
+
+					webglObject.render = true;
+
+					if ( this.sortObjects === true ) {
+
+						if ( object.renderDepth !== null ) {
+
+							webglObject.z = object.renderDepth;
+
+						} else {
+
+							_vector3.getPositionFromMatrix( object.matrixWorld );
+							_vector3.applyProjection(_projScreenMatrix);
+
+							webglObject.z = _vector3.z;
+
+						}
+
+					}
+
+				}
+
+			}
+
+		}
+
+		if ( this.sortObjects ) {
+
+			renderList.sort( painterSortStable );
+
+		}
+
+		// set matrices for immediate objects
+
+		renderList = scene.__webglObjectsImmediate;
+
+		for ( i = 0, il = renderList.length; i < il; i ++ ) {
+
+			webglObject = renderList[ i ];
+			object = webglObject.object;
+
+			if ( object.visible ) {
+
+				setupMatrices( object, camera );
+
+				unrollImmediateBufferMaterial( webglObject );
+
+			}
+
+		}
+
+		if ( scene.overrideMaterial ) {
+
+			var material = scene.overrideMaterial;
+
+			renderer.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst );
+			renderer.setDepthTest( material.depthTest );
+			renderer.setDepthWrite( material.depthWrite );
+			renderer.setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );
+
+			renderObjects( scene.__webglObjects, false, "", camera, lights, fog, true, material );
+			renderObjectsImmediate( scene.__webglObjectsImmediate, "", camera, lights, fog, false, material );
+
+		} else {
+
+			var material = null;
+
+			// opaque pass (front-to-back order)
+
+			renderer.setBlending( THREE.NoBlending );
+
+			renderObjects( scene.__webglObjects, true, "opaque", camera, lights, fog, false, material );
+			renderObjectsImmediate( scene.__webglObjectsImmediate, "opaque", camera, lights, fog, false, material );
+
+			// transparent pass (back-to-front order)
+
+			renderObjects( scene.__webglObjects, false, "transparent", camera, lights, fog, true, material );
+			renderObjectsImmediate( scene.__webglObjectsImmediate, "transparent", camera, lights, fog, true, material );
+
+		}
+
+		// custom render plugins (post pass)
+
+		renderPlugins( this.renderPluginsPost, scene, camera );
+
+
+		// Generate mipmap if we're using any kind of mipmap filtering
+
+		if ( renderTarget && renderTarget.generateMipmaps && renderTarget.minFilter !== THREE.NearestFilter && renderTarget.minFilter !== THREE.LinearFilter ) {
+
+			renderer.updateRenderTargetMipmap( renderTarget );
+
+		}
+
+		// Ensure depth buffer writing is enabled so it can be cleared on next render
+
+		renderer.setDepthTest( true );
+		renderer.setDepthWrite( true );
+
+		// _gl.finish();
+
+	};
+
+	function renderPlugins( plugins, scene, camera ) {
+
+		if ( ! plugins.length ) return;
+
+		for ( var i = 0, il = plugins.length; i < il; i ++ ) {
+
+			// reset state for plugin (to start from clean slate)
+
+			_currentProgram = null;
+			_currentCamera = null;
+			_currentGeometryGroupHash = -1;
+			_currentMaterialId = -1;
+			_lightsNeedUpdate = true;
+			renderer.resetState();
+
+			plugins[ i ].render( scene, camera, renderer.getCurrentWidth(), renderer.getCurrentWidth() );
+
+			// reset state after plugin (anything could have changed)
+
+			_currentProgram = null;
+			_currentCamera = null;
+			_currentGeometryGroupHash = -1;
+			_currentMaterialId = -1;
+			_lightsNeedUpdate = true;
+			renderer.resetState();
+
+		}
+
+	};
+
+	function renderObjects ( renderList, reverse, materialType, camera, lights, fog, useBlending, overrideMaterial ) {
+
+		var webglObject, object, buffer, material, start, end, delta;
+
+		if ( reverse ) {
+
+			start = renderList.length - 1;
+			end = -1;
+			delta = -1;
+
+		} else {
+
+			start = 0;
+			end = renderList.length;
+			delta = 1;
+		}
+
+		for ( var i = start; i !== end; i += delta ) {
+
+			webglObject = renderList[ i ];
+
+			if ( webglObject.render ) {
+
+				object = webglObject.object;
+				buffer = webglObject.buffer;
+
+				if ( overrideMaterial ) {
+
+					material = overrideMaterial;
+
+				} else {
+
+					material = webglObject[ materialType ];
+
+					if ( ! material ) continue;
+
+					if ( useBlending ) renderer.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst );
+
+					renderer.setDepthTest( material.depthTest );
+					renderer.setDepthWrite( material.depthWrite );
+					renderer.setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );
+
+				}
+
+				renderer.setMaterialFaces( material );
+
+				if ( buffer instanceof THREE.BufferGeometry ) {
+
+					_this.renderBufferDirect( camera, lights, fog, material, buffer, object );
+
+				} else {
+
+					_this.renderBuffer( camera, lights, fog, material, buffer, object );
+
+				}
+
+			}
+
+		}
+
+	};
+
+	function renderObjectsImmediate ( renderList, materialType, camera, lights, fog, useBlending, overrideMaterial ) {
+
+		var webglObject, object, material, program;
+
+		for ( var i = 0, il = renderList.length; i < il; i ++ ) {
+
+			webglObject = renderList[ i ];
+			object = webglObject.object;
+
+			if ( object.visible ) {
+
+				if ( overrideMaterial ) {
+
+					material = overrideMaterial;
+
+				} else {
+
+					material = webglObject[ materialType ];
+
+					if ( ! material ) continue;
+
+					if ( useBlending ) renderer.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst );
+
+					renderer.setDepthTest( material.depthTest );
+					renderer.setDepthWrite( material.depthWrite );
+					renderer.setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );
+
+				}
+
+				_this.renderImmediateObject( camera, lights, fog, material, object );
+
+			}
+
+		}
+
+	};
+
+	this.renderImmediateObject = function ( camera, lights, fog, material, object ) {
+
+		var program = setProgram( camera, lights, fog, material, object );
+
+		_currentGeometryGroupHash = -1;
+
+		renderer.setMaterialFaces( material );
+
+		if ( object.immediateRenderCallback ) {
+
+			object.immediateRenderCallback( program, renderer.getContext(), _frustum );
+
+		} else {
+
+			object.render( function( object ) { _this.renderBufferImmediate( object, program, material ); } );
+
+		}
+
+	};
+
+	function unrollImmediateBufferMaterial ( globject ) {
+
+		var object = globject.object,
+			material = object.material;
+
+		if ( material.transparent ) {
+
+			globject.transparent = material;
+			globject.opaque = null;
+
+		} else {
+
+			globject.opaque = material;
+			globject.transparent = null;
+
+		}
+
+	};
+
+	function unrollBufferMaterial ( globject ) {
+
+		var object = globject.object,
+			buffer = globject.buffer,
+			material, materialIndex, meshMaterial;
+
+		meshMaterial = object.material;
+
+		if ( meshMaterial instanceof THREE.MeshFaceMaterial ) {
+
+			materialIndex = buffer.materialIndex;
+
+			material = meshMaterial.materials[ materialIndex ];
+
+			if ( material.transparent ) {
+
+				globject.transparent = material;
+				globject.opaque = null;
+
+			} else {
+
+				globject.opaque = material;
+				globject.transparent = null;
+
+			}
+
+		} else {
+
+			material = meshMaterial;
+
+			if ( material ) {
+
+				if ( material.transparent ) {
+
+					globject.transparent = material;
+					globject.opaque = null;
+
+				} else {
+
+					globject.opaque = material;
+					globject.transparent = null;
+
+				}
+
+			}
+
+		}
+
+	};
+
+	// Geometry splitting
+
+	function sortFacesByMaterial ( geometry, material ) {
+
+		var f, fl, face, materialIndex, vertices,
+			groupHash, hash_map = {};
+
+		var numMorphTargets = geometry.morphTargets.length;
+		var numMorphNormals = geometry.morphNormals.length;
+
+		var usesFaceMaterial = material instanceof THREE.MeshFaceMaterial;
+
+		geometry.geometryGroups = {};
+
+		for ( f = 0, fl = geometry.faces.length; f < fl; f ++ ) {
+
+			face = geometry.faces[ f ];
+			materialIndex = usesFaceMaterial ? face.materialIndex : 0;
+
+			if ( hash_map[ materialIndex ] === undefined ) {
+
+				hash_map[ materialIndex ] = { 'hash': materialIndex, 'counter': 0 };
+
+			}
+
+			groupHash = hash_map[ materialIndex ].hash + '_' + hash_map[ materialIndex ].counter;
+
+			if ( geometry.geometryGroups[ groupHash ] === undefined ) {
+
+				geometry.geometryGroups[ groupHash ] = { 'faces3': [], 'faces4': [], 'materialIndex': materialIndex, 'vertices': 0, 'numMorphTargets': numMorphTargets, 'numMorphNormals': numMorphNormals };
+
+			}
+
+			vertices = face instanceof THREE.Face3 ? 3 : 4;
+
+			if ( geometry.geometryGroups[ groupHash ].vertices + vertices > 65535 ) {
+
+				hash_map[ materialIndex ].counter += 1;
+				groupHash = hash_map[ materialIndex ].hash + '_' + hash_map[ materialIndex ].counter;
+
+				if ( geometry.geometryGroups[ groupHash ] === undefined ) {
+
+					geometry.geometryGroups[ groupHash ] = { 'faces3': [], 'faces4': [], 'materialIndex': materialIndex, 'vertices': 0, 'numMorphTargets': numMorphTargets, 'numMorphNormals': numMorphNormals };
+
+				}
+
+			}
+
+			if ( face instanceof THREE.Face3 ) {
+
+				geometry.geometryGroups[ groupHash ].faces3.push( f );
+
+			} else {
+
+				geometry.geometryGroups[ groupHash ].faces4.push( f );
+
+			}
+
+			geometry.geometryGroups[ groupHash ].vertices += vertices;
+
+		}
+
+		geometry.geometryGroupsList = [];
+
+		for ( var g in geometry.geometryGroups ) {
+
+			geometry.geometryGroups[ g ].id = _geometryGroupCounter ++;
+
+			geometry.geometryGroupsList.push( geometry.geometryGroups[ g ] );
+
+		}
+
+	};
+
+	// Objects refresh
+
+	this.initWebGLObjects = function ( scene ) {
+
+		if ( !scene.__webglObjects ) {
+
+			scene.__webglObjects = [];
+			scene.__webglObjectsImmediate = [];
+			scene.__webglSprites = [];
+			scene.__webglFlares = [];
+
+		}
+
+		while ( scene.__objectsAdded.length ) {
+
+			addObject( scene.__objectsAdded[ 0 ], scene );
+			scene.__objectsAdded.splice( 0, 1 );
+
+		}
+
+		while ( scene.__objectsRemoved.length ) {
+
+			removeObject( scene.__objectsRemoved[ 0 ], scene );
+			scene.__objectsRemoved.splice( 0, 1 );
+
+		}
+
+		// update must be called after objects adding / removal
+
+		for ( var o = 0, ol = scene.__webglObjects.length; o < ol; o ++ ) {
+
+			updateObject( scene.__webglObjects[ o ].object );
+
+		}
+
+	};
+
+	// Objects adding
+
+	function addObject( object, scene ) {
+
+		var g, geometry, material, geometryGroup;
+
+		if ( ! object.__webglInit ) {
+
+			object.__webglInit = true;
+
+			object._modelViewMatrix = new THREE.Matrix4();
+			object._normalMatrix = new THREE.Matrix3();
+
+			if ( object.geometry !== undefined && object.geometry.__webglInit === undefined ) {
+
+				object.geometry.__webglInit = true;
+				object.geometry.addEventListener( 'dispose', onGeometryDispose );
+
+			}
+
+			if ( object instanceof THREE.Mesh ) {
+
+				geometry = object.geometry;
+				material = object.material;
+
+				if ( geometry instanceof THREE.Geometry ) {
+
+					if ( geometry.geometryGroups === undefined ) {
+
+						sortFacesByMaterial( geometry, material );
+
+					}
+
+					// create separate VBOs per geometry chunk
+
+					for ( g in geometry.geometryGroups ) {
+
+						geometryGroup = geometry.geometryGroups[ g ];
+
+						// initialise VBO on the first access
+
+						if ( ! geometryGroup.__webglVertexBuffer ) {
+
+							meshRenderer.createBuffers( geometryGroup );
+							meshRenderer.initBuffers( geometryGroup, object );
+
+							geometry.verticesNeedUpdate = true;
+							geometry.morphTargetsNeedUpdate = true;
+							geometry.elementsNeedUpdate = true;
+							geometry.uvsNeedUpdate = true;
+							geometry.normalsNeedUpdate = true;
+							geometry.tangentsNeedUpdate = true;
+							geometry.colorsNeedUpdate = true;
+
+						}
+
+					}
+
+				} else if ( geometry instanceof THREE.BufferGeometry ) {
+
+					initDirectBuffers( geometry );
+
+				}
+
+			} else if ( object instanceof THREE.Ribbon ) {
+
+				geometry = object.geometry;
+
+				if ( ! geometry.__webglVertexBuffer ) {
+
+					ribbonRenderer.createBuffers( geometry );
+					ribbonRenderer.initBuffers( geometry, object );
+
+					geometry.verticesNeedUpdate = true;
+					geometry.colorsNeedUpdate = true;
+					geometry.normalsNeedUpdate = true;
+
+				}
+
+			} else if ( object instanceof THREE.Line ) {
+
+				geometry = object.geometry;
+
+				if ( ! geometry.__webglVertexBuffer ) {
+
+					if ( geometry instanceof THREE.Geometry ) {
+
+						lineRenderer.createBuffers( geometry );
+						lineRenderer.initBuffers( geometry, object );
+
+						geometry.verticesNeedUpdate = true;
+						geometry.colorsNeedUpdate = true;
+						geometry.lineDistancesNeedUpdate = true;
+
+					} else if ( geometry instanceof THREE.BufferGeometry ) {
+
+						initDirectBuffers( geometry );
+
+					}
+
+				}
+
+			} else if ( object instanceof THREE.ParticleSystem ) {
+
+				geometry = object.geometry;
+
+				if ( ! geometry.__webglVertexBuffer ) {
+
+					if ( geometry instanceof THREE.Geometry ) {
+
+						particleRenderer.createBuffers( geometry );
+						particleRenderer.initBuffers( geometry, object );
+
+						geometry.verticesNeedUpdate = true;
+						geometry.colorsNeedUpdate = true;
+
+					} else if ( geometry instanceof THREE.BufferGeometry ) {
+
+						initDirectBuffers( geometry );
+
+					}
+
+
+				}
+
+			}
+
+		}
+
+		if ( ! object.__webglActive ) {
+
+			if ( object instanceof THREE.Mesh ) {
+
+				geometry = object.geometry;
+
+				if ( geometry instanceof THREE.BufferGeometry ) {
+
+					addBuffer( scene.__webglObjects, geometry, object );
+
+				} else if ( geometry instanceof THREE.Geometry ) {
+
+					for ( g in geometry.geometryGroups ) {
+
+						geometryGroup = geometry.geometryGroups[ g ];
+
+						addBuffer( scene.__webglObjects, geometryGroup, object );
+
+					}
+
+				}
+
+			} else if ( object instanceof THREE.Ribbon ||
+						object instanceof THREE.Line ||
+						object instanceof THREE.ParticleSystem ) {
+
+				geometry = object.geometry;
+				addBuffer( scene.__webglObjects, geometry, object );
+
+			} else if ( object instanceof THREE.ImmediateRenderObject || object.immediateRenderCallback ) {
+
+				addBufferImmediate( scene.__webglObjectsImmediate, object );
+
+			} else if ( object instanceof THREE.Sprite ) {
+
+				scene.__webglSprites.push( object );
+
+			} else if ( object instanceof THREE.LensFlare ) {
+
+				scene.__webglFlares.push( object );
+
+			}
+
+			object.__webglActive = true;
+
+		}
+
+	};
+
+	function addBuffer ( objlist, buffer, object ) {
+
+		objlist.push(
+			{
+				id: null,
+				buffer: buffer,
+				object: object,
+				opaque: null,
+				transparent: null,
+				render: false,
+				z: 0
+			}
+		);
+
+	};
+
+	function addBufferImmediate ( objlist, object ) {
+
+		objlist.push(
+			{
+				object: object,
+				opaque: null,
+				transparent: null
+			}
+		);
+
+	};
+
+	// Objects updates
+
+	function updateObject ( object ) {
+
+		var geometry = object.geometry,
+			geometryGroup, customAttributesDirty, material;
+
+		if ( object instanceof THREE.Mesh ) {
+
+			if ( geometry instanceof THREE.BufferGeometry ) {
+
+				if ( geometry.verticesNeedUpdate || geometry.elementsNeedUpdate ||
+					 geometry.uvsNeedUpdate || geometry.normalsNeedUpdate ||
+					 geometry.colorsNeedUpdate || geometry.tangentsNeedUpdate ) {
+
+					setDirectBuffers( geometry, !geometry.dynamic );
+
+				}
+
+				geometry.verticesNeedUpdate = false;
+				geometry.elementsNeedUpdate = false;
+				geometry.uvsNeedUpdate = false;
+				geometry.normalsNeedUpdate = false;
+				geometry.colorsNeedUpdate = false;
+				geometry.tangentsNeedUpdate = false;
+
+			} else {
+
+				// check all geometry groups
+
+				for( var i = 0, il = geometry.geometryGroupsList.length; i < il; i ++ ) {
+
+					geometryGroup = geometry.geometryGroupsList[ i ];
+
+					material = getBufferMaterial( object, geometryGroup );
+
+					if ( geometry.buffersNeedUpdate ) {
+
+						meshRenderer.initBuffers( geometryGroup, object );
+
+					}
+
+					customAttributesDirty = material.attributes && areCustomAttributesDirty( material );
+
+					if ( geometry.verticesNeedUpdate || geometry.morphTargetsNeedUpdate || geometry.elementsNeedUpdate ||
+						 geometry.uvsNeedUpdate || geometry.normalsNeedUpdate ||
+						 geometry.colorsNeedUpdate || geometry.tangentsNeedUpdate || customAttributesDirty ) {
+
+						meshRenderer.setBuffers( geometryGroup, object, !geometry.dynamic, material );
+
+					}
+
+				}
+
+				geometry.verticesNeedUpdate = false;
+				geometry.morphTargetsNeedUpdate = false;
+				geometry.elementsNeedUpdate = false;
+				geometry.uvsNeedUpdate = false;
+				geometry.normalsNeedUpdate = false;
+				geometry.colorsNeedUpdate = false;
+				geometry.tangentsNeedUpdate = false;
+
+				geometry.buffersNeedUpdate = false;
+
+				material.attributes && clearCustomAttributes( material );
+
+			}
+
+		} else if ( object instanceof THREE.Ribbon ) {
+
+			material = getBufferMaterial( object, geometry );
+
+			customAttributesDirty = material.attributes && areCustomAttributesDirty( material );
+
+			if ( geometry.verticesNeedUpdate || geometry.colorsNeedUpdate || geometry.normalsNeedUpdate || customAttributesDirty ) {
+
+				ribbonRenderer.setBuffers( geometry);
+
+			}
+
+			geometry.verticesNeedUpdate = false;
+			geometry.colorsNeedUpdate = false;
+			geometry.normalsNeedUpdate = false;
+
+			material.attributes && clearCustomAttributes( material );
+
+		} else if ( object instanceof THREE.Line ) {
+
+			if ( geometry instanceof THREE.BufferGeometry ) {
+
+				if ( geometry.verticesNeedUpdate || geometry.colorsNeedUpdate ) {
+
+					setDirectBuffers( geometry,  !geometry.dynamic );
+
+				}
+
+				geometry.verticesNeedUpdate = false;
+				geometry.colorsNeedUpdate = false;
+
+			} else {
+
+				material = getBufferMaterial( object, geometry );
+
+				customAttributesDirty = material.attributes && areCustomAttributesDirty( material );
+
+				if ( geometry.verticesNeedUpdate || geometry.colorsNeedUpdate || geometry.lineDistancesNeedUpdate || customAttributesDirty ) {
+
+					lineRenderer.setBuffers( geometry);
+
+				}
+
+				geometry.verticesNeedUpdate = false;
+				geometry.colorsNeedUpdate = false;
+				geometry.lineDistancesNeedUpdate = false;
+
+				material.attributes && clearCustomAttributes( material );
+
+			}
+
+		} else if ( object instanceof THREE.ParticleSystem ) {
+
+			if ( geometry instanceof THREE.BufferGeometry ) {
+
+				if ( geometry.verticesNeedUpdate || geometry.colorsNeedUpdate ) {
+
+					setDirectBuffers( geometry, !geometry.dynamic );
+
+				}
+
+				geometry.verticesNeedUpdate = false;
+				geometry.colorsNeedUpdate = false;
+
+			} else {
+
+				material = getBufferMaterial( object, geometry );
+
+				customAttributesDirty = material.attributes && areCustomAttributesDirty( material );
+
+				if ( geometry.verticesNeedUpdate || geometry.colorsNeedUpdate || object.sortParticles || customAttributesDirty ) {
+
+					particleRenderer.setBuffers( geometry, object, _projScreenMatrix);
+
+				}
+
+				geometry.verticesNeedUpdate = false;
+				geometry.colorsNeedUpdate = false;
+
+				material.attributes && clearCustomAttributes( material );
+
+			}
+
+		}
+
+	};
+
+	// Objects updates - custom attributes check
+
+	function areCustomAttributesDirty ( material ) {
+
+		for ( var a in material.attributes ) {
+
+			if ( material.attributes[ a ].needsUpdate ) return true;
+
+		}
+
+		return false;
+
+	};
+
+	function clearCustomAttributes ( material ) {
+
+		for ( var a in material.attributes ) {
+
+			material.attributes[ a ].needsUpdate = false;
+
+		}
+
+	};
+
+	// Objects removal
+
+	function removeObject ( object, scene ) {
+
+		if ( object instanceof THREE.Mesh  ||
+			 object instanceof THREE.ParticleSystem ||
+			 object instanceof THREE.Ribbon ||
+			 object instanceof THREE.Line ) {
+
+			removeInstances( scene.__webglObjects, object );
+
+		} else if ( object instanceof THREE.Sprite ) {
+
+			removeInstancesDirect( scene.__webglSprites, object );
+
+		} else if ( object instanceof THREE.LensFlare ) {
+
+			removeInstancesDirect( scene.__webglFlares, object );
+
+		} else if ( object instanceof THREE.ImmediateRenderObject || object.immediateRenderCallback ) {
+
+			removeInstances( scene.__webglObjectsImmediate, object );
+
+		}
+
+		object.__webglActive = false;
+
+	};
+
+	function removeInstances ( objlist, object ) {
+
+		for ( var o = objlist.length - 1; o >= 0; o -- ) {
+
+			if ( objlist[ o ].object === object ) {
+
+				objlist.splice( o, 1 );
+
+			}
+
+		}
+
+	};
+
+	function removeInstancesDirect ( objlist, object ) {
+
+		for ( var o = objlist.length - 1; o >= 0; o -- ) {
+
+			if ( objlist[ o ] === object ) {
+
+				objlist.splice( o, 1 );
+
+			}
+
+		}
+
+	};
+
+	// Materials
+
+	this.initMaterial = function ( material, lights, fog, object ) {
+
+		material.addEventListener( 'dispose', onMaterialDispose );
+
+		var u, a, identifiers, i, parameters, maxLightCount, maxBones, maxShadows, shaderID;
+
+		if ( material instanceof THREE.MeshDepthMaterial ) {
+
+			shaderID = 'depth';
+
+		} else if ( material instanceof THREE.MeshNormalMaterial ) {
+
+			shaderID = 'normal';
+
+		} else if ( material instanceof THREE.MeshBasicMaterial ) {
+
+			shaderID = 'basic';
+
+		} else if ( material instanceof THREE.MeshLambertMaterial ) {
+
+			shaderID = 'lambert';
+
+		} else if ( material instanceof THREE.MeshPhongMaterial ) {
+
+			shaderID = 'phong';
+
+		} else if ( material instanceof THREE.LineBasicMaterial ) {
+
+			shaderID = 'basic';
+
+		} else if ( material instanceof THREE.LineDashedMaterial ) {
+
+			shaderID = 'dashed';
+
+		} else if ( material instanceof THREE.ParticleBasicMaterial ) {
+
+			shaderID = 'particle_basic';
+
+		}
+
+		if ( shaderID ) {
+
+			setMaterialShaders( material, THREE.ShaderLib[ shaderID ] );
+
+		}
+
+		// heuristics to create shader parameters according to lights in the scene
+		// (not to blow over maxLights budget)
+
+		maxLightCount = allocateLights( lights );
+
+		maxShadows = allocateShadows( lights );
+
+		maxBones = allocateBones( object );
+
+		parameters = {
+
+			map: !!material.map,
+			envMap: !!material.envMap,
+			lightMap: !!material.lightMap,
+			bumpMap: !!material.bumpMap,
+			normalMap: !!material.normalMap,
+			specularMap: !!material.specularMap,
+
+			vertexColors: material.vertexColors,
+
+			fog: fog,
+			useFog: material.fog,
+			fogExp: fog instanceof THREE.FogExp2,
+
+			sizeAttenuation: material.sizeAttenuation,
+
+			skinning: material.skinning,
+			maxBones: maxBones,
+			useVertexTexture: renderer.supportsBoneTextures && object && object.useVertexTexture,
+			boneTextureWidth: object && object.boneTextureWidth,
+			boneTextureHeight: object && object.boneTextureHeight,
+
+			morphTargets: material.morphTargets,
+			morphNormals: material.morphNormals,
+			maxMorphTargets: this.maxMorphTargets,
+			maxMorphNormals: this.maxMorphNormals,
+
+			maxDirLights: maxLightCount.directional,
+			maxPointLights: maxLightCount.point,
+			maxSpotLights: maxLightCount.spot,
+			maxHemiLights: maxLightCount.hemi,
+
+			maxShadows: maxShadows,
+			shadowMapEnabled: this.shadowMapEnabled && object.receiveShadow,
+			shadowMapType: this.shadowMapType,
+			shadowMapDebug: this.shadowMapDebug,
+			shadowMapCascade: this.shadowMapCascade,
+
+			alphaTest: material.alphaTest,
+			metal: material.metal,
+			perPixel: material.perPixel,
+			wrapAround: material.wrapAround,
+			doubleSided: material.side === THREE.DoubleSide,
+			flipSided: material.side === THREE.BackSide,
+
+			gammaInput : this.gammaInput,
+			gammaOutput  : this.gammaOutput ,
+			physicallyBasedShading : this.physicallyBasedShading
+
+		};
+
+		material.program = shaderBuilder.buildProgram( shaderID, material.fragmentShader, material.vertexShader, material.uniforms, material.attributes, material.defines, parameters );
+
+		var attributes = material.program.attributes;
+
+		if ( material.morphTargets ) {
+
+			material.numSupportedMorphTargets = 0;
+
+			var id, base = "morphTarget";
+
+			for ( i = 0; i < this.maxMorphTargets; i ++ ) {
+
+				id = base + i;
+
+				if ( attributes[ id ] >= 0 ) {
+
+					material.numSupportedMorphTargets ++;
+
+				}
+
+			}
+
+		}
+
+		if ( material.morphNormals ) {
+
+			material.numSupportedMorphNormals = 0;
+
+			var id, base = "morphNormal";
+
+			for ( i = 0; i < this.maxMorphNormals; i ++ ) {
+
+				id = base + i;
+
+				if ( attributes[ id ] >= 0 ) {
+
+					material.numSupportedMorphNormals ++;
+
+				}
+
+			}
+
+		}
+
+		material.uniformsList = [];
+
+		for ( u in material.uniforms ) {
+
+			material.uniformsList.push( [ material.uniforms[ u ], u ] );
+
+		}
+
+	};
+
+	function setMaterialShaders( material, shaders ) {
+
+		material.uniforms = THREE.UniformsUtils.clone( shaders.uniforms );
+		material.vertexShader = shaders.vertexShader;
+		material.fragmentShader = shaders.fragmentShader;
+
+	};
+
+	function setProgram( camera, lights, fog, material, object ) {
+
+		_usedTextureUnits = 0;
+
+		if ( material.needsUpdate ) {
+
+			if ( material.program ) deallocateMaterial( material );
+
+			_this.initMaterial( material, lights, fog, object );
+			material.needsUpdate = false;
+
+		}
+
+		if ( material.morphTargets ) {
+
+			if ( ! object.__webglMorphTargetInfluences ) {
+
+				object.__webglMorphTargetInfluences = new Float32Array( _this.maxMorphTargets );
+
+			}
+
+		}
+
+		var refreshMaterial = false;
+
+		var program = material.program,
+			p_uniforms = program.uniforms,
+			m_uniforms = material.uniforms;
+
+		if ( program !== _currentProgram ) {
+
+			renderer.useProgram( program );
+			_currentProgram = program;
+
+			refreshMaterial = true;
+
+		}
+
+		if ( material.id !== _currentMaterialId ) {
+
+			_currentMaterialId = material.id;
+			refreshMaterial = true;
+
+		}
+
+		if ( refreshMaterial || camera !== _currentCamera ) {
+
+			renderer.uniformMatrix4fv( p_uniforms.projectionMatrix, camera.projectionMatrix.elements );
+
+			if ( camera !== _currentCamera ) _currentCamera = camera;
+
+		}
+
+		// skinning uniforms must be set even if material didn't change
+		// auto-setting of texture unit for bone texture must go before other textures
+		// not sure why, but otherwise weird things happen
+
+		if ( material.skinning ) {
+
+			if ( renderer.supportsBoneTextures && object.useVertexTexture ) {
+
+				if ( p_uniforms.boneTexture !== null ) {
+
+					var textureUnit = getTextureUnit();
+
+					renderer.uniform1i( p_uniforms.boneTexture, textureUnit );
+					renderer.setTexture( object.boneTexture, textureUnit );
+
+				}
+
+			} else {
+
+				if ( p_uniforms.boneGlobalMatrices !== null ) {
+
+					renderer.uniformMatrix4fv( p_uniforms.boneGlobalMatrices, object.boneMatrices );
+
+				}
+
+			}
+
+		}
+
+		if ( refreshMaterial ) {
+
+			// refresh uniforms common to several materials
+
+			if ( fog && material.fog ) {
+
+				refreshUniformsFog( m_uniforms, fog );
+
+			}
+
+			if ( material instanceof THREE.MeshPhongMaterial ||
+				 material instanceof THREE.MeshLambertMaterial ||
+				 material.lights ) {
+
+				if ( _lightsNeedUpdate ) {
+
+					setupLights( program, lights );
+					_lightsNeedUpdate = false;
+
+				}
+
+				refreshUniformsLights( m_uniforms, _lights );
+
+			}
+
+			if ( material instanceof THREE.MeshBasicMaterial ||
+				 material instanceof THREE.MeshLambertMaterial ||
+				 material instanceof THREE.MeshPhongMaterial ) {
+
+				refreshUniformsCommon( m_uniforms, material );
+
+			}
+
+			// refresh single material specific uniforms
+
+			if ( material instanceof THREE.LineBasicMaterial ) {
+
+				refreshUniformsLine( m_uniforms, material );
+
+			} else if ( material instanceof THREE.LineDashedMaterial ) {
+
+				refreshUniformsLine( m_uniforms, material );
+				refreshUniformsDash( m_uniforms, material );
+
+			} else if ( material instanceof THREE.ParticleBasicMaterial ) {
+
+				refreshUniformsParticle( m_uniforms, material );
+
+			} else if ( material instanceof THREE.MeshPhongMaterial ) {
+
+				refreshUniformsPhong( m_uniforms, material );
+
+			} else if ( material instanceof THREE.MeshLambertMaterial ) {
+
+				refreshUniformsLambert( m_uniforms, material );
+
+			} else if ( material instanceof THREE.MeshDepthMaterial ) {
+
+				m_uniforms.mNear.value = camera.near;
+				m_uniforms.mFar.value = camera.far;
+				m_uniforms.opacity.value = material.opacity;
+
+			} else if ( material instanceof THREE.MeshNormalMaterial ) {
+
+				m_uniforms.opacity.value = material.opacity;
+
+			}
+
+			if ( object.receiveShadow && ! material._shadowPass ) {
+
+				refreshUniformsShadow( m_uniforms, lights );
+
+			}
+
+			// load common uniforms
+
+			loadUniformsGeneric( program, material.uniformsList );
+
+			// load material specific uniforms
+			// (shader material also gets them for the sake of genericity)
+
+			if ( material instanceof THREE.ShaderMaterial ||
+				 material instanceof THREE.MeshPhongMaterial ||
+				 material.envMap ) {
+
+				if ( p_uniforms.cameraPosition !== null ) {
+
+					_vector3.getPositionFromMatrix( camera.matrixWorld );
+					renderer.uniform3f( p_uniforms.cameraPosition, _vector3.x, _vector3.y, _vector3.z );
+
+				}
+
+			}
+
+			if ( material instanceof THREE.MeshPhongMaterial ||
+				 material instanceof THREE.MeshLambertMaterial ||
+				 material instanceof THREE.ShaderMaterial ||
+				 material.skinning ) {
+
+				if ( p_uniforms.viewMatrix !== null ) {
+
+					renderer.uniformMatrix4fv( p_uniforms.viewMatrix, camera.matrixWorldInverse.elements );
+
+				}
+
+			}
+
+		}
+
+		loadUniformsMatrices( p_uniforms, object );
+
+		if ( p_uniforms.modelMatrix !== null ) {
+
+			renderer.uniformMatrix4fv( p_uniforms.modelMatrix, object.matrixWorld.elements );
+
+		}
+
+		return program;
+
+	};
+
+	// Uniforms (refresh uniforms objects)
+
+	function refreshUniformsCommon ( uniforms, material ) {
+
+		uniforms.opacity.value = material.opacity;
+
+		if ( _this.gammaInput ) {
+
+			uniforms.diffuse.value.copyGammaToLinear( material.color );
+
+		} else {
+
+			uniforms.diffuse.value = material.color;
+
+		}
+
+		uniforms.map.value = material.map;
+		uniforms.lightMap.value = material.lightMap;
+		uniforms.specularMap.value = material.specularMap;
+
+		if ( material.bumpMap ) {
+
+			uniforms.bumpMap.value = material.bumpMap;
+			uniforms.bumpScale.value = material.bumpScale;
+
+		}
+
+		if ( material.normalMap ) {
+
+			uniforms.normalMap.value = material.normalMap;
+			uniforms.normalScale.value.copy( material.normalScale );
+
+		}
+
+		// uv repeat and offset setting priorities
+		//	1. color map
+		//	2. specular map
+		//	3. normal map
+		//	4. bump map
+
+		var uvScaleMap;
+
+		if ( material.map ) {
+
+			uvScaleMap = material.map;
+
+		} else if ( material.specularMap ) {
+
+			uvScaleMap = material.specularMap;
+
+		} else if ( material.normalMap ) {
+
+			uvScaleMap = material.normalMap;
+
+		} else if ( material.bumpMap ) {
+
+			uvScaleMap = material.bumpMap;
+
+		}
+
+		if ( uvScaleMap !== undefined ) {
+
+			var offset = uvScaleMap.offset;
+			var repeat = uvScaleMap.repeat;
+
+			uniforms.offsetRepeat.value.set( offset.x, offset.y, repeat.x, repeat.y );
+
+		}
+
+		uniforms.envMap.value = material.envMap;
+		uniforms.flipEnvMap.value = ( material.envMap instanceof THREE.WebGLRenderTargetCube ) ? 1 : -1;
+
+		if ( _this.gammaInput ) {
+
+			//uniforms.reflectivity.value = material.reflectivity * material.reflectivity;
+			uniforms.reflectivity.value = material.reflectivity;
+
+		} else {
+
+			uniforms.reflectivity.value = material.reflectivity;
+
+		}
+
+		uniforms.refractionRatio.value = material.refractionRatio;
+		uniforms.combine.value = material.combine;
+		uniforms.useRefract.value = material.envMap && material.envMap.mapping instanceof THREE.CubeRefractionMapping;
+
+	};
+
+	function refreshUniformsLine ( uniforms, material ) {
+
+		uniforms.diffuse.value = material.color;
+		uniforms.opacity.value = material.opacity;
+
+	};
+
+	function refreshUniformsDash ( uniforms, material ) {
+
+		uniforms.dashSize.value = material.dashSize;
+		uniforms.totalSize.value = material.dashSize + material.gapSize;
+		uniforms.scale.value = material.scale;
+
+	};
+
+	function refreshUniformsParticle ( uniforms, material ) {
+
+		uniforms.psColor.value = material.color;
+		uniforms.opacity.value = material.opacity;
+		uniforms.size.value = material.size;
+		uniforms.scale.value = renderer.getDomElement().height / 2.0; // TODO: Cache this.
+
+		uniforms.map.value = material.map;
+
+	};
+
+	function refreshUniformsFog ( uniforms, fog ) {
+
+		uniforms.fogColor.value = fog.color;
+
+		if ( fog instanceof THREE.Fog ) {
+
+			uniforms.fogNear.value = fog.near;
+			uniforms.fogFar.value = fog.far;
+
+		} else if ( fog instanceof THREE.FogExp2 ) {
+
+			uniforms.fogDensity.value = fog.density;
+
+		}
+
+	};
+
+	function refreshUniformsPhong ( uniforms, material ) {
+
+		uniforms.shininess.value = material.shininess;
+
+		if ( _this.gammaInput ) {
+
+			uniforms.ambient.value.copyGammaToLinear( material.ambient );
+			uniforms.emissive.value.copyGammaToLinear( material.emissive );
+			uniforms.specular.value.copyGammaToLinear( material.specular );
+
+		} else {
+
+			uniforms.ambient.value = material.ambient;
+			uniforms.emissive.value = material.emissive;
+			uniforms.specular.value = material.specular;
+
+		}
+
+		if ( material.wrapAround ) {
+
+			uniforms.wrapRGB.value.copy( material.wrapRGB );
+
+		}
+
+	};
+
+	function refreshUniformsLambert ( uniforms, material ) {
+
+		if ( _this.gammaInput ) {
+
+			uniforms.ambient.value.copyGammaToLinear( material.ambient );
+			uniforms.emissive.value.copyGammaToLinear( material.emissive );
+
+		} else {
+
+			uniforms.ambient.value = material.ambient;
+			uniforms.emissive.value = material.emissive;
+
+		}
+
+		if ( material.wrapAround ) {
+
+			uniforms.wrapRGB.value.copy( material.wrapRGB );
+
+		}
+
+	};
+
+	function refreshUniformsLights ( uniforms, lights ) {
+
+		uniforms.ambientLightColor.value = lights.ambient;
+
+		uniforms.directionalLightColor.value = lights.directional.colors;
+		uniforms.directionalLightDirection.value = lights.directional.positions;
+
+		uniforms.pointLightColor.value = lights.point.colors;
+		uniforms.pointLightPosition.value = lights.point.positions;
+		uniforms.pointLightDistance.value = lights.point.distances;
+
+		uniforms.spotLightColor.value = lights.spot.colors;
+		uniforms.spotLightPosition.value = lights.spot.positions;
+		uniforms.spotLightDistance.value = lights.spot.distances;
+		uniforms.spotLightDirection.value = lights.spot.directions;
+		uniforms.spotLightAngleCos.value = lights.spot.anglesCos;
+		uniforms.spotLightExponent.value = lights.spot.exponents;
+
+		uniforms.hemisphereLightSkyColor.value = lights.hemi.skyColors;
+		uniforms.hemisphereLightGroundColor.value = lights.hemi.groundColors;
+		uniforms.hemisphereLightDirection.value = lights.hemi.positions;
+
+	};
+
+	function refreshUniformsShadow ( uniforms, lights ) {
+
+		if ( uniforms.shadowMatrix ) {
+
+			var j = 0;
+
+			for ( var i = 0, il = lights.length; i < il; i ++ ) {
+
+				var light = lights[ i ];
+
+				if ( ! light.castShadow ) continue;
+
+				if ( light instanceof THREE.SpotLight || ( light instanceof THREE.DirectionalLight && ! light.shadowCascade ) ) {
+
+					uniforms.shadowMap.value[ j ] = light.shadowMap;
+					uniforms.shadowMapSize.value[ j ] = light.shadowMapSize;
+
+					uniforms.shadowMatrix.value[ j ] = light.shadowMatrix;
+
+					uniforms.shadowDarkness.value[ j ] = light.shadowDarkness;
+					uniforms.shadowBias.value[ j ] = light.shadowBias;
+
+					j ++;
+
+				}
+
+			}
+
+		}
+
+	};
+
+	// Uniforms (load to GPU)
+
+	function loadUniformsMatrices ( uniforms, object ) {
+
+		renderer.uniformMatrix4fv( uniforms.modelViewMatrix, object._modelViewMatrix.elements );
+
+		if ( uniforms.normalMatrix ) {
+
+			renderer.uniformMatrix3fv( uniforms.normalMatrix, object._normalMatrix.elements );
+
+		}
+
+	};
+
+	function getTextureUnit() {
+
+		var textureUnit = _usedTextureUnits;
+
+		if ( textureUnit >= renderer.maxTextures ) {
+
+			console.warn( "WebGLRenderer: trying to use " + textureUnit + " texture units while this GPU supports only " + renderer.maxTextures );
+
+		}
+
+		_usedTextureUnits += 1;
+
+		return textureUnit;
+
+	};
+
+	function loadUniformsGeneric ( program, uniforms ) {
+
+		var uniform, value, type, location, texture, textureUnit, i, il, j, jl, offset;
+
+		for ( j = 0, jl = uniforms.length; j < jl; j ++ ) {
+
+			location = program.uniforms[ uniforms[ j ][ 1 ] ];
+			if ( !location ) continue;
+
+			uniform = uniforms[ j ][ 0 ];
+
+			type = uniform.type;
+			value = uniform.value;
+
+			if ( type === "i" ) { // single integer
+
+				renderer.uniform1i( location, value );
+
+			} else if ( type === "f" ) { // single float
+
+				renderer.uniform1f( location, value );
+
+			} else if ( type === "v2" ) { // single THREE.Vector2
+
+				renderer.uniform2f( location, value.x, value.y );
+
+			} else if ( type === "v3" ) { // single THREE.Vector3
+
+				renderer.uniform3f( location, value.x, value.y, value.z );
+
+			} else if ( type === "v4" ) { // single THREE.Vector4
+
+				renderer.uniform4f( location, value.x, value.y, value.z, value.w );
+
+			} else if ( type === "c" ) { // single THREE.Color
+
+				renderer.uniform3f( location, value.r, value.g, value.b );
+
+			} else if ( type === "iv1" ) { // flat array of integers (JS or typed array)
+
+				renderer.uniform1iv( location, value );
+
+			} else if ( type === "iv" ) { // flat array of integers with 3 x N size (JS or typed array)
+
+				renderer.uniform3iv( location, value );
+
+			} else if ( type === "fv1" ) { // flat array of floats (JS or typed array)
+
+				renderer.uniform1fv( location, value );
+
+			} else if ( type === "fv" ) { // flat array of floats with 3 x N size (JS or typed array)
+
+				renderer.uniform3fv( location, value );
+
+			} else if ( type === "v2v" ) { // array of THREE.Vector2
+
+				if ( uniform._array === undefined ) {
+
+					uniform._array = new Float32Array( 2 * value.length );
+
+				}
+
+				for ( i = 0, il = value.length; i < il; i ++ ) {
+
+					offset = i * 2;
+
+					uniform._array[ offset ] 	 = value[ i ].x;
+					uniform._array[ offset + 1 ] = value[ i ].y;
+
+				}
+
+				renderer.uniform2fv( location, uniform._array );
+
+			} else if ( type === "v3v" ) { // array of THREE.Vector3
+
+				if ( uniform._array === undefined ) {
+
+					uniform._array = new Float32Array( 3 * value.length );
+
+				}
+
+				for ( i = 0, il = value.length; i < il; i ++ ) {
+
+					offset = i * 3;
+
+					uniform._array[ offset ] 	 = value[ i ].x;
+					uniform._array[ offset + 1 ] = value[ i ].y;
+					uniform._array[ offset + 2 ] = value[ i ].z;
+
+				}
+
+				renderer.uniform3fv( location, uniform._array );
+
+			} else if ( type === "v4v" ) { // array of THREE.Vector4
+
+				if ( uniform._array === undefined ) {
+
+					uniform._array = new Float32Array( 4 * value.length );
+
+				}
+
+				for ( i = 0, il = value.length; i < il; i ++ ) {
+
+					offset = i * 4;
+
+					uniform._array[ offset ] 	 = value[ i ].x;
+					uniform._array[ offset + 1 ] = value[ i ].y;
+					uniform._array[ offset + 2 ] = value[ i ].z;
+					uniform._array[ offset + 3 ] = value[ i ].w;
+
+				}
+
+				renderer.uniform4fv( location, uniform._array );
+
+			} else if ( type === "m4") { // single THREE.Matrix4
+
+				if ( uniform._array === undefined ) {
+
+					uniform._array = new Float32Array( 16 );
+
+				}
+
+				value.flattenToArray( uniform._array );
+				renderer.uniformMatrix4fv( location, uniform._array );
+
+			} else if ( type === "m4v" ) { // array of THREE.Matrix4
+
+				if ( uniform._array === undefined ) {
+
+					uniform._array = new Float32Array( 16 * value.length );
+
+				}
+
+				for ( i = 0, il = value.length; i < il; i ++ ) {
+
+					value[ i ].flattenToArrayOffset( uniform._array, i * 16 );
+
+				}
+
+				renderer.uniformMatrix4fv( location, uniform._array );
+
+			} else if ( type === "t" ) { // single THREE.Texture (2d or cube)
+
+				texture = value;
+				textureUnit = getTextureUnit();
+
+				renderer.uniform1i( location, textureUnit );
+
+				if ( !texture ) continue;
+
+				if ( texture.image instanceof Array && texture.image.length === 6 ) {
+
+					renderer.setCubeTexture( texture, textureUnit );
+
+				} else if ( texture instanceof THREE.WebGLRenderTargetCube ) {
+
+					renderer.setCubeTextureDynamic( texture, textureUnit );
+
+				} else {
+
+					renderer.setTexture( texture, textureUnit );
+
+				}
+
+			} else if ( type === "tv" ) { // array of THREE.Texture (2d)
+
+				if ( uniform._array === undefined ) {
+
+					uniform._array = [];
+
+				}
+
+				for( i = 0, il = uniform.value.length; i < il; i ++ ) {
+
+					uniform._array[ i ] = getTextureUnit();
+
+				}
+
+				renderer.uniform1iv( location, uniform._array );
+
+				for( i = 0, il = uniform.value.length; i < il; i ++ ) {
+
+					texture = uniform.value[ i ];
+					textureUnit = uniform._array[ i ];
+
+					if ( !texture ) continue;
+
+					renderer.setTexture( texture, textureUnit );
+
+				}
+
+			}
+
+		}
+
+	};
+
+	function setupMatrices ( object, camera ) {
+
+		object._modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld );
+
+		object._normalMatrix.getInverse( object._modelViewMatrix );
+		object._normalMatrix.transpose();
+
+	};
+
+	//
+
+	function setColorGamma( array, offset, color, intensitySq ) {
+
+		array[ offset ]     = color.r * color.r * intensitySq;
+		array[ offset + 1 ] = color.g * color.g * intensitySq;
+		array[ offset + 2 ] = color.b * color.b * intensitySq;
+
+	};
+
+	function setColorLinear( array, offset, color, intensity ) {
+
+		array[ offset ]     = color.r * intensity;
+		array[ offset + 1 ] = color.g * intensity;
+		array[ offset + 2 ] = color.b * intensity;
+
+	};
+
+	function setupLights ( program, lights ) {
+
+		var l, ll, light, n,
+		r = 0, g = 0, b = 0,
+		color, skyColor, groundColor,
+		intensity,  intensitySq,
+		position,
+		distance,
+
+		zlights = _lights,
+
+		dirColors = zlights.directional.colors,
+		dirPositions = zlights.directional.positions,
+
+		pointColors = zlights.point.colors,
+		pointPositions = zlights.point.positions,
+		pointDistances = zlights.point.distances,
+
+		spotColors = zlights.spot.colors,
+		spotPositions = zlights.spot.positions,
+		spotDistances = zlights.spot.distances,
+		spotDirections = zlights.spot.directions,
+		spotAnglesCos = zlights.spot.anglesCos,
+		spotExponents = zlights.spot.exponents,
+
+		hemiSkyColors = zlights.hemi.skyColors,
+		hemiGroundColors = zlights.hemi.groundColors,
+		hemiPositions = zlights.hemi.positions,
+
+		dirLength = 0,
+		pointLength = 0,
+		spotLength = 0,
+		hemiLength = 0,
+
+		dirCount = 0,
+		pointCount = 0,
+		spotCount = 0,
+		hemiCount = 0,
+
+		dirOffset = 0,
+		pointOffset = 0,
+		spotOffset = 0,
+		hemiOffset = 0;
+
+		for ( l = 0, ll = lights.length; l < ll; l ++ ) {
+
+			light = lights[ l ];
+
+			if ( light.onlyShadow ) continue;
+
+			color = light.color;
+			intensity = light.intensity;
+			distance = light.distance;
+
+			if ( light instanceof THREE.AmbientLight ) {
+
+				if ( ! light.visible ) continue;
+
+				if ( _this.gammaInput ) {
+
+					r += color.r * color.r;
+					g += color.g * color.g;
+					b += color.b * color.b;
+
+				} else {
+
+					r += color.r;
+					g += color.g;
+					b += color.b;
+
+				}
+
+			} else if ( light instanceof THREE.DirectionalLight ) {
+
+				dirCount += 1;
+
+				if ( ! light.visible ) continue;
+
+				_direction.getPositionFromMatrix( light.matrixWorld );
+				_vector3.getPositionFromMatrix( light.target.matrixWorld );
+				_direction.sub( _vector3 );
+				_direction.normalize();
+
+				// skip lights with undefined direction
+				// these create troubles in OpenGL (making pixel black)
+
+				if ( _direction.x === 0 && _direction.y === 0 && _direction.z === 0 ) continue;
+
+				dirOffset = dirLength * 3;
+
+				dirPositions[ dirOffset ]     = _direction.x;
+				dirPositions[ dirOffset + 1 ] = _direction.y;
+				dirPositions[ dirOffset + 2 ] = _direction.z;
+
+				if ( _this.gammaInput ) {
+
+					setColorGamma( dirColors, dirOffset, color, intensity * intensity );
+
+				} else {
+
+					setColorLinear( dirColors, dirOffset, color, intensity );
+
+				}
+
+				dirLength += 1;
+
+			} else if ( light instanceof THREE.PointLight ) {
+
+				pointCount += 1;
+
+				if ( ! light.visible ) continue;
+
+				pointOffset = pointLength * 3;
+
+				if ( _this.gammaInput ) {
+
+					setColorGamma( pointColors, pointOffset, color, intensity * intensity );
+
+				} else {
+
+					setColorLinear( pointColors, pointOffset, color, intensity );
+
+				}
+
+				_vector3.getPositionFromMatrix( light.matrixWorld );
+
+				pointPositions[ pointOffset ]     = _vector3.x;
+				pointPositions[ pointOffset + 1 ] = _vector3.y;
+				pointPositions[ pointOffset + 2 ] = _vector3.z;
+
+				pointDistances[ pointLength ] = distance;
+
+				pointLength += 1;
+
+			} else if ( light instanceof THREE.SpotLight ) {
+
+				spotCount += 1;
+
+				if ( ! light.visible ) continue;
+
+				spotOffset = spotLength * 3;
+
+				if ( _this.gammaInput ) {
+
+					setColorGamma( spotColors, spotOffset, color, intensity * intensity );
+
+				} else {
+
+					setColorLinear( spotColors, spotOffset, color, intensity );
+
+				}
+
+				_vector3.getPositionFromMatrix( light.matrixWorld );
+
+				spotPositions[ spotOffset ]     = _vector3.x;
+				spotPositions[ spotOffset + 1 ] = _vector3.y;
+				spotPositions[ spotOffset + 2 ] = _vector3.z;
+
+				spotDistances[ spotLength ] = distance;
+
+				_direction.copy( _vector3 );
+				_vector3.getPositionFromMatrix( light.target.matrixWorld );
+				_direction.sub( _vector3 );
+				_direction.normalize();
+
+				spotDirections[ spotOffset ]     = _direction.x;
+				spotDirections[ spotOffset + 1 ] = _direction.y;
+				spotDirections[ spotOffset + 2 ] = _direction.z;
+
+				spotAnglesCos[ spotLength ] = Math.cos( light.angle );
+				spotExponents[ spotLength ] = light.exponent;
+
+				spotLength += 1;
+
+			} else if ( light instanceof THREE.HemisphereLight ) {
+
+				hemiCount += 1;
+
+				if ( ! light.visible ) continue;
+
+				_direction.getPositionFromMatrix( light.matrixWorld );
+				_direction.normalize();
+
+				// skip lights with undefined direction
+				// these create troubles in OpenGL (making pixel black)
+
+				if ( _direction.x === 0 && _direction.y === 0 && _direction.z === 0 ) continue;
+
+				hemiOffset = hemiLength * 3;
+
+				hemiPositions[ hemiOffset ]     = _direction.x;
+				hemiPositions[ hemiOffset + 1 ] = _direction.y;
+				hemiPositions[ hemiOffset + 2 ] = _direction.z;
+
+				skyColor = light.color;
+				groundColor = light.groundColor;
+
+				if ( _this.gammaInput ) {
+
+					intensitySq = intensity * intensity;
+
+					setColorGamma( hemiSkyColors, hemiOffset, skyColor, intensitySq );
+					setColorGamma( hemiGroundColors, hemiOffset, groundColor, intensitySq );
+
+				} else {
+
+					setColorLinear( hemiSkyColors, hemiOffset, skyColor, intensity );
+					setColorLinear( hemiGroundColors, hemiOffset, groundColor, intensity );
+
+				}
+
+				hemiLength += 1;
+
+			}
+
+		}
+
+		// null eventual remains from removed lights
+		// (this is to avoid if in shader)
+
+		for ( l = dirLength * 3, ll = Math.max( dirColors.length, dirCount * 3 ); l < ll; l ++ ) dirColors[ l ] = 0.0;
+		for ( l = pointLength * 3, ll = Math.max( pointColors.length, pointCount * 3 ); l < ll; l ++ ) pointColors[ l ] = 0.0;
+		for ( l = spotLength * 3, ll = Math.max( spotColors.length, spotCount * 3 ); l < ll; l ++ ) spotColors[ l ] = 0.0;
+		for ( l = hemiLength * 3, ll = Math.max( hemiSkyColors.length, hemiCount * 3 ); l < ll; l ++ ) hemiSkyColors[ l ] = 0.0;
+		for ( l = hemiLength * 3, ll = Math.max( hemiGroundColors.length, hemiCount * 3 ); l < ll; l ++ ) hemiGroundColors[ l ] = 0.0;
+
+		zlights.directional.length = dirLength;
+		zlights.point.length = pointLength;
+		zlights.spot.length = spotLength;
+		zlights.hemi.length = hemiLength;
+
+		zlights.ambient[ 0 ] = r;
+		zlights.ambient[ 1 ] = g;
+		zlights.ambient[ 2 ] = b;
+
+	};
+
+	// Allocations
+
+	function allocateBones ( object ) {
+
+		if ( renderer.supportsBoneTextures && object && object.useVertexTexture ) {
+
+			return 1024;
+
+		} else {
+
+			// default for when object is not specified
+			// ( for example when prebuilding shader
+			//   to be used with multiple objects )
+			//
+			// 	- leave some extra space for other uniforms
+			//  - limit here is ANGLE's 254 max uniform vectors
+			//    (up to 54 should be safe)
+
+			var nVertexUniforms = renderer.maxVertexUniformVectors
+			var nVertexMatrices = Math.floor( ( nVertexUniforms - 20 ) / 4 );
+
+			var maxBones = nVertexMatrices;
+
+			if ( object !== undefined && object instanceof THREE.SkinnedMesh ) {
+
+				maxBones = Math.min( object.bones.length, maxBones );
+
+				if ( maxBones < object.bones.length ) {
+
+					console.warn( "WebGLRenderer: too many bones - " + object.bones.length + ", this GPU supports just " + maxBones + " (try OpenGL instead of ANGLE)" );
+
+				}
+
+			}
+
+			return maxBones;
+
+		}
+
+	};
+
+	function allocateLights ( lights ) {
+
+		var l, ll, light, dirLights, pointLights, spotLights, hemiLights;
+
+		dirLights = pointLights = spotLights = hemiLights = 0;
+
+		for ( l = 0, ll = lights.length; l < ll; l ++ ) {
+
+			light = lights[ l ];
+
+			if ( light.onlyShadow ) continue;
+
+			if ( light instanceof THREE.DirectionalLight ) dirLights ++;
+			if ( light instanceof THREE.PointLight ) pointLights ++;
+			if ( light instanceof THREE.SpotLight ) spotLights ++;
+			if ( light instanceof THREE.HemisphereLight ) hemiLights ++;
+
+		}
+
+		return { 'directional' : dirLights, 'point' : pointLights, 'spot': spotLights, 'hemi': hemiLights };
+
+	};
+
+	function allocateShadows ( lights ) {
+
+		var l, ll, light, maxShadows = 0;
+
+		for ( l = 0, ll = lights.length; l < ll; l++ ) {
+
+			light = lights[ l ];
+
+			if ( ! light.castShadow ) continue;
+
+			if ( light instanceof THREE.SpotLight ) maxShadows ++;
+			if ( light instanceof THREE.DirectionalLight && ! light.shadowCascade ) maxShadows ++;
+
+		}
+
+		return maxShadows;
+
+	};
+
+	// default plugins (order is important)
+
+	this.shadowMapPlugin = new THREE.ShadowMapPlugin();
+	this.addPrePlugin( this.shadowMapPlugin );
+
+	this.addPostPlugin( new THREE.SpritePlugin() );
+	this.addPostPlugin( new THREE.LensFlarePlugin() );
+
+};
 
 
-				_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglSkinWeightsBuffer );
-				enableAttribute( attributes.skinWeight );
-				_gl.vertexAttribPointer( attributes.skinWeight, 4, _gl.FLOAT, false, 0, 0 );
+/*global THREE:false */
 
 
-			}
+THREE.WebGLRenderer.LowLevelRenderer = function ( parameters ) {
 
 
-			// line distances
+	parameters = parameters || {};
 
 
-			if ( attributes.lineDistance >= 0 ) {
+	var _canvas = parameters.canvas !== undefined ? parameters.canvas : document.createElement( 'canvas' ),
 
 
-				_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglLineDistanceBuffer );
-				enableAttribute( attributes.lineDistance );
-				_gl.vertexAttribPointer( attributes.lineDistance, 1, _gl.FLOAT, false, 0, 0 );
+	_precision = parameters.precision !== undefined ? parameters.precision : 'highp',
 
 
-			}
+	_alpha = parameters.alpha !== undefined ? parameters.alpha : true,
+	_premultipliedAlpha = parameters.premultipliedAlpha !== undefined ? parameters.premultipliedAlpha : true,
+	_antialias = parameters.antialias !== undefined ? parameters.antialias : false,
+	_stencil = parameters.stencil !== undefined ? parameters.stencil : true,
+	_preserveDrawingBuffer = parameters.preserveDrawingBuffer !== undefined ? parameters.preserveDrawingBuffer : false,
 
 
-		}
+	_clearColor = parameters.clearColor !== undefined ? new THREE.Color( parameters.clearColor ) : new THREE.Color( 0x000000 ),
+	_clearAlpha = parameters.clearAlpha !== undefined ? parameters.clearAlpha : 0,
+	_autoScaleCubemaps = true;
 
 
-		// render mesh
+	this.devicePixelRatio = parameters.devicePixelRatio !== undefined ? parameters.devicePixelRatio : window.devicePixelRatio !== undefined ? window.devicePixelRatio : 1;
 
 
-		if ( object instanceof THREE.Mesh ) {
+	var _currentWidth = 0, _currentHeight = 0;
 
 
-			// wireframe
+	var _gl;
 
 
-			if ( material.wireframe ) {
+	var _glExtensionTextureFloat;
+	var _glExtensionStandardDerivatives;
+	var _glExtensionTextureFilterAnisotropic;
+	var _glExtensionCompressedTextureS3TC;
 
 
-				setLineWidth( material.wireframeLinewidth );
+	initGL();
 
 
-				if ( updateBuffers ) _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, geometryGroup.__webglLineBuffer );
-				_gl.drawElements( _gl.LINES, geometryGroup.__webglLineCount, _gl.UNSIGNED_SHORT, 0 );
+	setDefaultGLState();
 
 
-			// triangles
+	var _maxTextures = _gl.getParameter( _gl.MAX_TEXTURE_IMAGE_UNITS );
+	var _maxVertexTextures = _gl.getParameter( _gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS );
+	var _maxTextureSize = _gl.getParameter( _gl.MAX_TEXTURE_SIZE );
+	var _maxCubemapSize = _gl.getParameter( _gl.MAX_CUBE_MAP_TEXTURE_SIZE );
 
 
-			} else {
+	var _maxAnisotropy = _glExtensionTextureFilterAnisotropic ? _gl.getParameter( _glExtensionTextureFilterAnisotropic.MAX_TEXTURE_MAX_ANISOTROPY_EXT ) : 0;
 
 
-				if ( updateBuffers ) _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, geometryGroup.__webglFaceBuffer );
-				_gl.drawElements( _gl.TRIANGLES, geometryGroup.__webglFaceCount, _gl.UNSIGNED_SHORT, 0 );
+	var _supportsVertexTextures = ( _maxVertexTextures > 0 );
+	var _supportsBoneTextures = _supportsVertexTextures && _glExtensionTextureFloat;
 
 
-			}
+	var _compressedTextureFormats = _glExtensionCompressedTextureS3TC ? _gl.getParameter( _gl.COMPRESSED_TEXTURE_FORMATS ) : [];
 
 
-			_this.info.render.calls ++;
-			_this.info.render.vertices += geometryGroup.__webglFaceCount;
-			_this.info.render.faces += geometryGroup.__webglFaceCount / 3;
+	var _vertexShaderPrecisionHighpFloat = _gl.getShaderPrecisionFormat( _gl.VERTEX_SHADER, _gl.HIGH_FLOAT );
+	var _vertexShaderPrecisionMediumpFloat = _gl.getShaderPrecisionFormat( _gl.VERTEX_SHADER, _gl.MEDIUM_FLOAT );
+	var _vertexShaderPrecisionLowpFloat = _gl.getShaderPrecisionFormat( _gl.VERTEX_SHADER, _gl.LOW_FLOAT );
 
 
-		// render lines
+	var _fragmentShaderPrecisionHighpFloat = _gl.getShaderPrecisionFormat( _gl.FRAGMENT_SHADER, _gl.HIGH_FLOAT );
+	var _fragmentShaderPrecisionMediumpFloat = _gl.getShaderPrecisionFormat( _gl.FRAGMENT_SHADER, _gl.MEDIUM_FLOAT );
+	var _fragmentShaderPrecisionLowpFloat = _gl.getShaderPrecisionFormat( _gl.FRAGMENT_SHADER, _gl.LOW_FLOAT );
 
 
-		} else if ( object instanceof THREE.Line ) {
+	var _vertexShaderPrecisionHighpInt = _gl.getShaderPrecisionFormat( _gl.VERTEX_SHADER, _gl.HIGH_INT );
+	var _vertexShaderPrecisionMediumpInt = _gl.getShaderPrecisionFormat( _gl.VERTEX_SHADER, _gl.MEDIUM_INT );
+	var _vertexShaderPrecisionLowpInt = _gl.getShaderPrecisionFormat( _gl.VERTEX_SHADER, _gl.LOW_INT );
 
 
-			primitives = ( object.type === THREE.LineStrip ) ? _gl.LINE_STRIP : _gl.LINES;
+	var _fragmentShaderPrecisionHighpInt = _gl.getShaderPrecisionFormat( _gl.FRAGMENT_SHADER, _gl.HIGH_INT );
+	var _fragmentShaderPrecisionMediumpInt = _gl.getShaderPrecisionFormat( _gl.FRAGMENT_SHADER, _gl.MEDIUM_INT );
+	var _fragmentShaderPrecisionLowpInt = _gl.getShaderPrecisionFormat( _gl.FRAGMENT_SHADER, _gl.LOW_INT );
 
 
-			setLineWidth( material.linewidth );
+	// clamp precision to maximum available
 
 
-			_gl.drawArrays( primitives, 0, geometryGroup.__webglLineCount );
+	var highpAvailable = _vertexShaderPrecisionHighpFloat.precision > 0 && _fragmentShaderPrecisionHighpFloat.precision > 0;
+	var mediumpAvailable = _vertexShaderPrecisionMediumpFloat.precision > 0 && _fragmentShaderPrecisionMediumpFloat.precision > 0;
 
 
-			_this.info.render.calls ++;
+	if ( _precision === "highp" && ! highpAvailable ) {
 
 
-		// render particles
+		if ( mediumpAvailable ) {
 
 
-		} else if ( object instanceof THREE.ParticleSystem ) {
+			_precision = "mediump";
+			console.warn( "WebGLRenderer: highp not supported, using mediump" );
 
 
-			_gl.drawArrays( _gl.POINTS, 0, geometryGroup.__webglParticleCount );
+		} else {
 
 
-			_this.info.render.calls ++;
-			_this.info.render.points += geometryGroup.__webglParticleCount;
+			_precision = "lowp";
+			console.warn( "WebGLRenderer: highp and mediump not supported, using lowp" );
 
 
-		// render ribbon
+		}
 
 
-		} else if ( object instanceof THREE.Ribbon ) {
+	}
 
 
-			_gl.drawArrays( _gl.TRIANGLE_STRIP, 0, geometryGroup.__webglVertexCount );
+	if ( _precision === "mediump" && ! mediumpAvailable ) {
 
 
-			_this.info.render.calls ++;
+		_precision = "lowp";
+		console.warn( "WebGLRenderer: mediump not supported, using lowp" );
 
 
-		}
+	}
 
 
-	};
+	var _enabledAttributes = {},
+		_oldBlending,
+		_oldBlendEquation,
+		_oldBlendSrc,
+		_oldBlendDst,
 
 
-	function enableAttribute( attribute ) {
+		_oldDoubleSided = -1,
+		_oldFlipSided = -1,
 
 
-		if ( ! _enabledAttributes[ attribute ] ) {
+		_oldDepthTest = -1,
+		_oldDepthWrite = -1,
 
 
-			_gl.enableVertexAttribArray( attribute );
-			_enabledAttributes[ attribute ] = true;
+		_oldLineWidth = -1,
 
 
-		}
+		_viewportX = 0,
+		_viewportY = 0,
+		_viewportWidth = 0,
+		_viewportHeight = 0,
+			// GL state cache
 
 
-	};
+		_oldPolygonOffset = null,
+		_oldPolygonOffsetFactor = null,
+		_oldPolygonOffsetUnits = null,
+		_currentFramebuffer = null;
 
 
-	function disableAttributes() {
+	function initGL () {
 
 
-		for ( var attribute in _enabledAttributes ) {
+		try {
 
 
-			if ( _enabledAttributes[ attribute ] ) {
+			if ( ! ( _gl = _canvas.getContext( 'experimental-webgl', { alpha: _alpha, premultipliedAlpha: _premultipliedAlpha, antialias: _antialias, stencil: _stencil, preserveDrawingBuffer: _preserveDrawingBuffer } ) ) ) {
 
 
-				_gl.disableVertexAttribArray( attribute );
-				_enabledAttributes[ attribute ] = false;
+				throw 'Error creating WebGL context.';
 
 
 			}
 			}
 
 
-		}
+		} catch ( error ) {
 
 
-	};
+			console.error( error );
 
 
-	function setupMorphTargets ( material, geometryGroup, object ) {
+		}
 
 
-		// set base
+		_glExtensionTextureFloat = _gl.getExtension( 'OES_texture_float' );
+		_glExtensionStandardDerivatives = _gl.getExtension( 'OES_standard_derivatives' );
 
 
-		var attributes = material.program.attributes;
+		_glExtensionTextureFilterAnisotropic = _gl.getExtension( 'EXT_texture_filter_anisotropic' ) ||
+											   _gl.getExtension( 'MOZ_EXT_texture_filter_anisotropic' ) ||
+											   _gl.getExtension( 'WEBKIT_EXT_texture_filter_anisotropic' );
 
 
-		if ( object.morphTargetBase !== -1 && attributes.position >= 0 ) {
 
 
-			_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphTargetsBuffers[ object.morphTargetBase ] );
-			enableAttribute( attributes.position );
-			_gl.vertexAttribPointer( attributes.position, 3, _gl.FLOAT, false, 0, 0 );
+		_glExtensionCompressedTextureS3TC = _gl.getExtension( 'WEBGL_compressed_texture_s3tc' ) ||
+											_gl.getExtension( 'MOZ_WEBGL_compressed_texture_s3tc' ) ||
+											_gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_s3tc' );
 
 
-		} else if ( attributes.position >= 0 ) {
+		if ( ! _glExtensionTextureFloat ) {
 
 
-			_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglVertexBuffer );
-			enableAttribute( attributes.position );
-			_gl.vertexAttribPointer( attributes.position, 3, _gl.FLOAT, false, 0, 0 );
+			console.log( 'THREE.WebGLRenderer: Float textures not supported.' );
 
 
 		}
 		}
 
 
-		if ( object.morphTargetForcedOrder.length ) {
+		if ( ! _glExtensionStandardDerivatives ) {
+
+			console.log( 'THREE.WebGLRenderer: Standard derivatives not supported.' );
 
 
-			// set forced order
+		}
 
 
-			var m = 0;
-			var order = object.morphTargetForcedOrder;
-			var influences = object.morphTargetInfluences;
+		if ( ! _glExtensionTextureFilterAnisotropic ) {
 
 
-			while ( m < material.numSupportedMorphTargets && m < order.length ) {
+			console.log( 'THREE.WebGLRenderer: Anisotropic texture filtering not supported.' );
 
 
-				if ( attributes[ "morphTarget" + m ] >= 0 ) {
+		}
 
 
-					_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphTargetsBuffers[ order[ m ] ] );
-					enableAttribute( attributes[ "morphTarget" + m ] );
-					_gl.vertexAttribPointer( attributes[ "morphTarget" + m ], 3, _gl.FLOAT, false, 0, 0 );
+		if ( ! _glExtensionCompressedTextureS3TC ) {
 
 
-				}
+			console.log( 'THREE.WebGLRenderer: S3TC compressed textures not supported.' );
 
 
-				if ( attributes[ "morphNormal" + m ] >= 0 && material.morphNormals ) {
+		}
 
 
-					_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphNormalsBuffers[ order[ m ] ] );
-					enableAttribute( attributes[ "morphNormal" + m ] );
-					_gl.vertexAttribPointer( attributes[ "morphNormal" + m ], 3, _gl.FLOAT, false, 0, 0 );
+		if ( _gl.getShaderPrecisionFormat === undefined ) {
 
 
-				}
+			_gl.getShaderPrecisionFormat = function() { 
 
 
-				object.__webglMorphTargetInfluences[ m ] = influences[ order[ m ] ];
+				return {
+					"rangeMin"  : 1,
+					"rangeMax"  : 1,
+					"precision" : 1
+				};
 
 
-				m ++;
 			}
 			}
 
 
-		} else {
-
-			// find the most influencing
+		}
 
 
-			var influence, activeInfluenceIndices = [];
-			var influences = object.morphTargetInfluences;
-			var i, il = influences.length;
+	}
 
 
-			for ( i = 0; i < il; i ++ ) {
+	function setDefaultGLState () {
 
 
-				influence = influences[ i ];
+		_gl.clearColor( 0, 0, 0, 1 );
+		_gl.clearDepth( 1 );
+		_gl.clearStencil( 0 );
 
 
-				if ( influence > 0 ) {
+		_gl.enable( _gl.DEPTH_TEST );
+		_gl.depthFunc( _gl.LEQUAL );
 
 
-					activeInfluenceIndices.push( [ influence, i ] );
+		_gl.frontFace( _gl.CCW );
+		_gl.cullFace( _gl.BACK );
+		_gl.enable( _gl.CULL_FACE );
 
 
-				}
+		_gl.enable( _gl.BLEND );
+		_gl.blendEquation( _gl.FUNC_ADD );
+		_gl.blendFunc( _gl.SRC_ALPHA, _gl.ONE_MINUS_SRC_ALPHA );
 
 
-			}
+		_gl.clearColor( _clearColor.r, _clearColor.g, _clearColor.b, _clearAlpha );
 
 
-			if ( activeInfluenceIndices.length > material.numSupportedMorphTargets ) {
+	}
 
 
-				activeInfluenceIndices.sort( numericalSort );
-				activeInfluenceIndices.length = material.numSupportedMorphTargets;
+	// Fallback filters for non-power-of-2 textures
 
 
-			} else if ( activeInfluenceIndices.length > material.numSupportedMorphNormals ) {
+	function filterFallback ( f ) {
 
 
-				activeInfluenceIndices.sort( numericalSort );
+		if ( f === THREE.NearestFilter || f === THREE.NearestMipMapNearestFilter || f === THREE.NearestMipMapLinearFilter ) {
 
 
-			} else if ( activeInfluenceIndices.length === 0 ) {
+			return _gl.NEAREST;
 
 
-				activeInfluenceIndices.push( [ 0, 0 ] );
+		}
 
 
-			};
+		return _gl.LINEAR;
 
 
-			var influenceIndex, m = 0;
+	}
 
 
-			while ( m < material.numSupportedMorphTargets ) {
+	function getContext() {
 
 
-				if ( activeInfluenceIndices[ m ] ) {
+		return _gl;
 
 
-					influenceIndex = activeInfluenceIndices[ m ][ 1 ];
+	}
 
 
-					if ( attributes[ "morphTarget" + m ] >= 0 ) {
+	function getDomElement(){
 
 
-						_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphTargetsBuffers[ influenceIndex ] );
-						enableAttribute( attributes[ "morphTarget" + m ] );
-						_gl.vertexAttribPointer( attributes[ "morphTarget" + m ], 3, _gl.FLOAT, false, 0, 0 );
+		return _canvas;
 
 
-					}
+	}
 
 
-					if ( attributes[ "morphNormal" + m ] >= 0 && material.morphNormals ) {
+	function getPrecision() {
 
 
-						_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphNormalsBuffers[ influenceIndex ] );
-						enableAttribute( attributes[ "morphNormal" + m ] );
-						_gl.vertexAttribPointer( attributes[ "morphNormal" + m ], 3, _gl.FLOAT, false, 0, 0 );
+		return _precision;
 
 
+	}
 
 
-					}
+	function getCurrentWidth(){
 
 
-					object.__webglMorphTargetInfluences[ m ] = influences[ influenceIndex ];
+		return _currentWidth;
 
 
-				} else {
+	}
 
 
-					/*
-					_gl.vertexAttribPointer( attributes[ "morphTarget" + m ], 3, _gl.FLOAT, false, 0, 0 );
+	function getCurrentHeight(){
 
 
-					if ( material.morphNormals ) {
+		return _currentHeight;
 
 
-						_gl.vertexAttribPointer( attributes[ "morphNormal" + m ], 3, _gl.FLOAT, false, 0, 0 );
+	}
 
 
-					}
-					*/
+	function supportsVertexTextures() {
 
 
-					object.__webglMorphTargetInfluences[ m ] = 0;
+		return _supportsVertexTextures;
 
 
-				}
+	}
 
 
-				m ++;
+	function supportsFloatTextures() {
 
 
-			}
+		return _glExtensionTextureFloat;
 
 
-		}
+	}
 
 
-		// load updated influences uniform
+	function supportsStandardDerivatives() {
 
 
-		if ( material.program.uniforms.morphTargetInfluences !== null ) {
+		return _glExtensionStandardDerivatives;
 
 
-			_gl.uniform1fv( material.program.uniforms.morphTargetInfluences, object.__webglMorphTargetInfluences );
+	}
 
 
-		}
+	function supportsCompressedTextureS3TC() {
 
 
-	};
+		return _glExtensionCompressedTextureS3TC;
 
 
-	// Sorting
+	}
 
 
-	function painterSortStable ( a, b ) {
+	function getMaxAnisotropy() {
 
 
-		if ( a.z !== b.z ) {
+		return _maxAnisotropy;
 
 
-			return b.z - a.z;
+	}
 
 
-		} else {
+	function setSize( width, height ) {
 
 
-			return b.id - a.id;
+		_canvas.width = width;
+		_canvas.height = height;
 
 
-		}
+		setViewport( 0, 0, _canvas.width, _canvas.height );
 
 
-	};
+	}
 
 
-	function numericalSort ( a, b ) {
+	function setViewport( x, y, width, height ) {
 
 
-		return b[ 0 ] - a[ 0 ];
+		_viewportX = x !== undefined ? x : 0;
+		_viewportY = y !== undefined ? y : 0;
 
 
-	};
+		_viewportWidth = width !== undefined ? width : _canvas.width;
+		_viewportHeight = height !== undefined ? height : _canvas.height;
 
 
+		_gl.viewport( _viewportX, _viewportY, _viewportWidth, _viewportHeight );
 
 
-	// Rendering
+	}
 
 
-	this.render = function ( scene, camera, renderTarget, forceClear ) {
+	function setScissor( x, y, width, height ) {
 
 
-		if ( camera instanceof THREE.Camera === false ) {
+		_gl.scissor( x, y, width, height );
 
 
-			console.error( 'THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.' );
-			return;
+	}
 
 
-		}
+	function enableScissorTest( enable ) {
 
 
-		var i, il,
+		enable ? _gl.enable( _gl.SCISSOR_TEST ) : _gl.disable( _gl.SCISSOR_TEST );
 
 
-		webglObject, object,
-		renderList,
+	}
 
 
-		lights = scene.__lights,
-		fog = scene.fog;
+	// Clearing
 
 
-		// reset caching for this frame
+	function setClearColorHex( hex, alpha ) {
 
 
-		_currentMaterialId = -1;
-		_lightsNeedUpdate = true;
+		_clearColor.setHex( hex );
+		_clearAlpha = alpha;
 
 
-		// update scene graph
+		_gl.clearColor( _clearColor.r, _clearColor.g, _clearColor.b, _clearAlpha );
 
 
-		if ( this.autoUpdateScene ) scene.updateMatrixWorld();
+	}
 
 
-		// update camera matrices and frustum
+	function setClearColor( color, alpha ) {
 
 
-		if ( camera.parent === undefined ) camera.updateMatrixWorld();
+		_clearColor.copy( color );
+		_clearAlpha = alpha;
 
 
-		camera.matrixWorldInverse.getInverse( camera.matrixWorld );
+		_gl.clearColor( _clearColor.r, _clearColor.g, _clearColor.b, _clearAlpha );
 
 
-		_projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
-		_frustum.setFromMatrix( _projScreenMatrix );
+	}
 
 
-		// update WebGL objects
+	function getClearColor() {
 
 
-		if ( this.autoUpdateObjects ) this.initWebGLObjects( scene );
+		return _clearColor;
 
 
-		// custom render plugins (pre pass)
+	}
 
 
-		renderPlugins( this.renderPluginsPre, scene, camera );
+	function getClearAlpha() {
 
 
-		//
+		return _clearAlpha;
 
 
-		_this.info.render.calls = 0;
-		_this.info.render.vertices = 0;
-		_this.info.render.faces = 0;
-		_this.info.render.points = 0;
+	}
 
 
-		this.setRenderTarget( renderTarget );
+	function clear( color, depth, stencil ) {
 
 
-		if ( this.autoClear || forceClear ) {
+		var bits = 0;
 
 
-			this.clear( this.autoClearColor, this.autoClearDepth, this.autoClearStencil );
+		if ( color === undefined || color ) bits |= _gl.COLOR_BUFFER_BIT;
+		if ( depth === undefined || depth ) bits |= _gl.DEPTH_BUFFER_BIT;
+		if ( stencil === undefined || stencil ) bits |= _gl.STENCIL_BUFFER_BIT;
 
 
-		}
+		_gl.clear( bits );
 
 
-		// set matrices for regular objects (frustum culled)
+	}
 
 
-		renderList = scene.__webglObjects;
+	function clearTarget( renderTarget, color, depth, stencil ) {
 
 
-		for ( i = 0, il = renderList.length; i < il; i ++ ) {
+		setRenderTarget( renderTarget );
+		clear( color, depth, stencil );
 
 
-			webglObject = renderList[ i ];
-			object = webglObject.object;
+	}
 
 
-			webglObject.render = false;
+	function deleteBuffer(buffer){
 
 
-			if ( object.visible ) {
+		_gl.deleteBuffer(buffer);
 
 
-				if ( ! ( object instanceof THREE.Mesh || object instanceof THREE.ParticleSystem ) || ! ( object.frustumCulled ) || _frustum.intersectsObject( object ) ) {
+	}
 
 
-					setupMatrices( object, camera );
+	function deleteTexture(texture){
 
 
-					unrollBufferMaterial( webglObject );
+		_gl.deleteTexture( texture );
 
 
-					webglObject.render = true;
+	}
 
 
-					if ( this.sortObjects === true ) {
+	function deleteFramebuffer(Framebuffer){
 
 
-						if ( object.renderDepth !== null ) {
+		_gl.deleteFramebuffer(Framebuffer);
 
 
-							webglObject.z = object.renderDepth;
+	}
 
 
-						} else {
+	function deleteRenderbuffer(RenderBuffer){
 
 
-							_vector3.getPositionFromMatrix( object.matrixWorld );
-							_vector3.applyProjection( _projScreenMatrix );
+		_gl.deleteRenderbuffer(RenderBuffer);
 
 
-							webglObject.z = _vector3.z;
+	}
 
 
-						}
+	function deleteProgram(RenderBuffer){
 
 
-						webglObject.id = object.id;
+		_gl.deleteProgram(RenderBuffer);
 
 
-					}
+	}
 
 
-				}
+	function createBuffer(){
 
 
-			}
+		return _gl.createBuffer();
 
 
-		}
+	}
 
 
-		if ( this.sortObjects ) {
+	function setStaticArrayBuffer(buffer,data){
 
 
-			renderList.sort( painterSortStable );
+		bindArrayBuffer( buffer );
+		_gl.bufferData( _gl.ARRAY_BUFFER, data, _gl.STATIC_DRAW );
 
 
-		}
+	}
 
 
-		// set matrices for immediate objects
+	function setStaticIndexBuffer(buffer,data){
 
 
-		renderList = scene.__webglObjectsImmediate;
+		bindElementArrayBuffer( buffer );
+		_gl.bufferData( _gl.ELEMENT_ARRAY_BUFFER, data, _gl.STATIC_DRAW );
 
 
-		for ( i = 0, il = renderList.length; i < il; i ++ ) {
+	}
 
 
-			webglObject = renderList[ i ];
-			object = webglObject.object;
+	function setDynamicArrayBuffer(buffer,data){
 
 
-			if ( object.visible ) {
+		bindArrayBuffer( buffer );
+		_gl.bufferData( _gl.ARRAY_BUFFER, data, _gl.DYNAMIC_DRAW );
 
 
-				setupMatrices( object, camera );
+	}
 
 
-				unrollImmediateBufferMaterial( webglObject );
+	function setDynamicIndexBuffer(buffer,data){
 
 
-			}
+		bindElementArrayBuffer( buffer );
+		_gl.bufferData( _gl.ELEMENT_ARRAY_BUFFER, data, _gl.DYNAMIC_DRAW );
 
 
-		}
+	}
 
 
-		if ( scene.overrideMaterial ) {
+	function drawTriangles(count){
 
 
-			var material = scene.overrideMaterial;
+		_gl.drawArrays( _gl.TRIANGLES, 0, count );
 
 
-			this.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst );
-			this.setDepthTest( material.depthTest );
-			this.setDepthWrite( material.depthWrite );
-			setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );
+	}
 
 
-			renderObjects( scene.__webglObjects, false, "", camera, lights, fog, true, material );
-			renderObjectsImmediate( scene.__webglObjectsImmediate, "", camera, lights, fog, false, material );
+	function drawTriangleStrip(count){
 
 
-		} else {
+		_gl.drawArrays( _gl.TRIANGLE_STRIP, 0, count );
 
 
-			var material = null;
+	}
 
 
-			// opaque pass (front-to-back order)
+	function drawLines(count){
 
 
-			this.setBlending( THREE.NoBlending );
+		_gl.drawArrays( _gl.LINES, 0, count );
 
 
-			renderObjects( scene.__webglObjects, true, "opaque", camera, lights, fog, false, material );
-			renderObjectsImmediate( scene.__webglObjectsImmediate, "opaque", camera, lights, fog, false, material );
+	}
 
 
-			// transparent pass (back-to-front order)
+	function drawLineStrip(count){
 
 
-			renderObjects( scene.__webglObjects, false, "transparent", camera, lights, fog, true, material );
-			renderObjectsImmediate( scene.__webglObjectsImmediate, "transparent", camera, lights, fog, true, material );
+		_gl.drawArrays( _gl.LINE_STRIP, 0, count );
 
 
-		}
+	}
 
 
-		// custom render plugins (post pass)
+	function drawPoints(count){
 
 
-		renderPlugins( this.renderPluginsPost, scene, camera );
+		_gl.drawArrays( _gl.POINTS, 0, count );
 
 
+	}
 
 
-		// Generate mipmap if we're using any kind of mipmap filtering
+	function drawTriangleElements(buffer,count,offset){
 
 
-		if ( renderTarget && renderTarget.generateMipmaps && renderTarget.minFilter !== THREE.NearestFilter && renderTarget.minFilter !== THREE.LinearFilter ) {
+		bindElementArrayBuffer( buffer );
+		_gl.drawElements( _gl.TRIANGLES, count, _gl.UNSIGNED_SHORT, offset ); // 2 bytes per Uint16
 
 
-			updateRenderTargetMipmap( renderTarget );
+	}
 
 
-		}
+	function drawLineElements(buffer,count,offset){
 
 
-		// Ensure depth buffer writing is enabled so it can be cleared on next render
+		bindElementArrayBuffer(  buffer );
+		_gl.drawElements( _gl.LINES, count, _gl.UNSIGNED_SHORT, offset ); // 2 bytes per Uint16
 
 
-		this.setDepthTest( true );
-		this.setDepthWrite( true );
+	}
 
 
-		// _gl.finish();
+	var _boundBuffer;
 
 
-	};
+	function bindArrayBuffer(buffer){
 
 
-	function renderPlugins( plugins, scene, camera ) {
+		if (_boundBuffer != buffer){
 
 
-		if ( ! plugins.length ) return;
+			_gl.bindBuffer( _gl.ARRAY_BUFFER, buffer );
+			_boundBuffer = buffer;
 
 
-		for ( var i = 0, il = plugins.length; i < il; i ++ ) {
+		}
 
 
-			// reset state for plugin (to start from clean slate)
+	}
 
 
-			_currentProgram = null;
-			_currentCamera = null;
+	function bindElementArrayBuffer(buffer){
 
 
-			_oldBlending = -1;
-			_oldDepthTest = -1;
-			_oldDepthWrite = -1;
-			_oldDoubleSided = -1;
-			_oldFlipSided = -1;
-			_currentGeometryGroupHash = -1;
-			_currentMaterialId = -1;
+		if (_boundBuffer != buffer){
 
 
-			_lightsNeedUpdate = true;
+			_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, buffer );
+			_boundBuffer = buffer;
 
 
-			plugins[ i ].render( scene, camera, _currentWidth, _currentHeight );
+		}
 
 
-			// reset state after plugin (anything could have changed)
+	}
 
 
-			_currentProgram = null;
-			_currentCamera = null;
+	function enableAttribute( attribute ) {
 
 
-			_oldBlending = -1;
-			_oldDepthTest = -1;
-			_oldDepthWrite = -1;
-			_oldDoubleSided = -1;
-			_oldFlipSided = -1;
-			_currentGeometryGroupHash = -1;
-			_currentMaterialId = -1;
+		if ( ! _enabledAttributes[ attribute ] ) {
 
 
-			_lightsNeedUpdate = true;
+			_gl.enableVertexAttribArray( attribute );
+			_enabledAttributes[ attribute ] = true;
 
 
 		}
 		}
 
 
-	};
+	}
 
 
-	function renderObjects ( renderList, reverse, materialType, camera, lights, fog, useBlending, overrideMaterial ) {
+	function disableAttributes() {
 
 
-		var webglObject, object, buffer, material, start, end, delta;
+		for ( var attribute in _enabledAttributes ) {
 
 
-		if ( reverse ) {
+			if ( _enabledAttributes[ attribute ] ) {
 
 
-			start = renderList.length - 1;
-			end = -1;
-			delta = -1;
+				_gl.disableVertexAttribArray( attribute );
+				_enabledAttributes[ attribute ] = false;
 
 
-		} else {
+			}
 
 
-			start = 0;
-			end = renderList.length;
-			delta = 1;
 		}
 		}
 
 
-		for ( var i = start; i !== end; i += delta ) {
-
-			webglObject = renderList[ i ];
-
-			if ( webglObject.render ) {
-
-				object = webglObject.object;
-				buffer = webglObject.buffer;
+	}
 
 
-				if ( overrideMaterial ) {
+	function getAttribLocation( program, id ){
 
 
-					material = overrideMaterial;
+		return _gl.getAttribLocation( program, id );
 
 
-				} else {
+	}
 
 
-					material = webglObject[ materialType ];
+	function setFloatAttribute(index,buffer,size,offset){
 
 
-					if ( ! material ) continue;
+		bindArrayBuffer( buffer );
+		enableAttribute( index );
+		_gl.vertexAttribPointer( index, size, _gl.FLOAT, false, 0, offset );
 
 
-					if ( useBlending ) _this.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst );
+	}
 
 
-					_this.setDepthTest( material.depthTest );
-					_this.setDepthWrite( material.depthWrite );
-					setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );
+	function getUniformLocation( program, id ){
 
 
-				}
+		return _gl.getUniformLocation( program, id );
 
 
-				_this.setMaterialFaces( material );
+	}
 
 
-				if ( buffer instanceof THREE.BufferGeometry ) {
+	function uniform1i(uniform,value){
 
 
-					_this.renderBufferDirect( camera, lights, fog, material, buffer, object );
+		_gl.uniform1i( uniform, value );
 
 
-				} else {
+	}
 
 
-					_this.renderBuffer( camera, lights, fog, material, buffer, object );
+	function uniform1f(uniform,value){
 
 
-				}
+		_gl.uniform1f( uniform, value );
 
 
-			}
+	}
 
 
-		}
+	function uniform2f(uniform,value1, value2){
 
 
-	};
+		_gl.uniform2f( uniform, value1, value2 );
 
 
-	function renderObjectsImmediate ( renderList, materialType, camera, lights, fog, useBlending, overrideMaterial ) {
+	}
 
 
-		var webglObject, object, material, program;
+	function uniform3f(uniform, value1, value2, value3){
 
 
-		for ( var i = 0, il = renderList.length; i < il; i ++ ) {
+		_gl.uniform3f( uniform, value1, value2, value3 );
 
 
-			webglObject = renderList[ i ];
-			object = webglObject.object;
+	}
 
 
-			if ( object.visible ) {
+	function uniform4f(uniform, value1, value2, value3, value4){
 
 
-				if ( overrideMaterial ) {
+		_gl.uniform4f( uniform, value1, value2, value3, value4);
 
 
-					material = overrideMaterial;
+	}
 
 
-				} else {
+	function uniform1iv(uniform,value){
 
 
-					material = webglObject[ materialType ];
+		_gl.uniform1iv( uniform, value );
 
 
-					if ( ! material ) continue;
+	}
 
 
-					if ( useBlending ) _this.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst );
+	function uniform2iv(uniform,value){
 
 
-					_this.setDepthTest( material.depthTest );
-					_this.setDepthWrite( material.depthWrite );
-					setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );
+		_gl.uniform2iv( uniform, value );
 
 
-				}
+	}
 
 
-				_this.renderImmediateObject( camera, lights, fog, material, object );
+	function uniform3iv(uniform,value){
 
 
-			}
+		_gl.uniform3iv( uniform, value );
 
 
-		}
+	}
 
 
-	};
+	function uniform1fv(uniform,value){
 
 
-	this.renderImmediateObject = function ( camera, lights, fog, material, object ) {
+		_gl.uniform1fv( uniform, value );
 
 
-		var program = setProgram( camera, lights, fog, material, object );
+	}
 
 
-		_currentGeometryGroupHash = -1;
+	function uniform2fv(uniform,value){
 
 
-		_this.setMaterialFaces( material );
+		_gl.uniform2fv( uniform, value );
 
 
-		if ( object.immediateRenderCallback ) {
+	}
 
 
-			object.immediateRenderCallback( program, _gl, _frustum );
+	function uniform3fv(uniform,value){
 
 
-		} else {
+		_gl.uniform3fv( uniform, value );
 
 
-			object.render( function( object ) { _this.renderBufferImmediate( object, program, material ); } );
+	}
 
 
-		}
+	function uniform4fv(uniform,value){
 
 
-	};
+		_gl.uniform3fv( uniform, value );
 
 
-	function unrollImmediateBufferMaterial ( globject ) {
+	}
 
 
-		var object = globject.object,
-			material = object.material;
+	function uniformMatrix3fv(location,value){
 
 
-		if ( material.transparent ) {
+		_gl.uniformMatrix3fv( location, false, value );
 
 
-			globject.transparent = material;
-			globject.opaque = null;
+	}
 
 
-		} else {
+	function uniformMatrix4fv(location,value){
 
 
-			globject.opaque = material;
-			globject.transparent = null;
+		_gl.uniformMatrix4fv( location, false, value );
 
 
-		}
+	}
 
 
-	};
+	function useProgram(program){
 
 
-	function unrollBufferMaterial ( globject ) {
+		_gl.useProgram( program );
 
 
-		var object = globject.object,
-			buffer = globject.buffer,
-			material, materialIndex, meshMaterial;
+	}
 
 
-		meshMaterial = object.material;
+	function setFaceCulling( cullFace, frontFaceDirection ) {
 
 
-		if ( meshMaterial instanceof THREE.MeshFaceMaterial ) {
+		if ( cullFace === THREE.CullFaceNone ) {
 
 
-			materialIndex = buffer.materialIndex;
+			_gl.disable( _gl.CULL_FACE );
 
 
-			material = meshMaterial.materials[ materialIndex ];
+		} else {
 
 
-			if ( material.transparent ) {
+			if ( frontFaceDirection === THREE.FrontFaceDirectionCW ) {
 
 
-				globject.transparent = material;
-				globject.opaque = null;
+				_gl.frontFace( _gl.CW );
 
 
 			} else {
 			} else {
 
 
-				globject.opaque = material;
-				globject.transparent = null;
+				_gl.frontFace( _gl.CCW );
 
 
 			}
 			}
 
 
-		} else {
-
-			material = meshMaterial;
-
-			if ( material ) {
+			if ( cullFace === THREE.CullFaceBack ) {
 
 
-				if ( material.transparent ) {
+				_gl.cullFace( _gl.BACK );
 
 
-					globject.transparent = material;
-					globject.opaque = null;
+			} else if ( cullFace === THREE.CullFaceFront ) {
 
 
-				} else {
+				_gl.cullFace( _gl.FRONT );
 
 
-					globject.opaque = material;
-					globject.transparent = null;
+			} else {
 
 
-				}
+				_gl.cullFace( _gl.FRONT_AND_BACK );
 
 
 			}
 			}
 
 
-		}
+			_gl.enable( _gl.CULL_FACE );
 
 
-	};
+		}
 
 
-	// Geometry splitting
+	}
 
 
-	function sortFacesByMaterial ( geometry, material ) {
+	function setMaterialFaces( material ) {
 
 
-		var f, fl, face, materialIndex, vertices,
-			groupHash, hash_map = {};
+		var doubleSided = material.side === THREE.DoubleSide;
+		var flipSided = material.side === THREE.BackSide;
 
 
-		var numMorphTargets = geometry.morphTargets.length;
-		var numMorphNormals = geometry.morphNormals.length;
+		if ( _oldDoubleSided !== doubleSided ) {
 
 
-		var usesFaceMaterial = material instanceof THREE.MeshFaceMaterial;
+			if ( doubleSided ) {
 
 
-		geometry.geometryGroups = {};
+				_gl.disable( _gl.CULL_FACE );
 
 
-		for ( f = 0, fl = geometry.faces.length; f < fl; f ++ ) {
+			} else {
 
 
-			face = geometry.faces[ f ];
-			materialIndex = usesFaceMaterial ? face.materialIndex : 0;
+				_gl.enable( _gl.CULL_FACE );
 
 
-			if ( hash_map[ materialIndex ] === undefined ) {
+			}
 
 
-				hash_map[ materialIndex ] = { 'hash': materialIndex, 'counter': 0 };
+			_oldDoubleSided = doubleSided;
 
 
-			}
+		}
 
 
-			groupHash = hash_map[ materialIndex ].hash + '_' + hash_map[ materialIndex ].counter;
+		if ( _oldFlipSided !== flipSided ) {
 
 
-			if ( geometry.geometryGroups[ groupHash ] === undefined ) {
+			if ( flipSided ) {
 
 
-				geometry.geometryGroups[ groupHash ] = { 'faces3': [], 'faces4': [], 'materialIndex': materialIndex, 'vertices': 0, 'numMorphTargets': numMorphTargets, 'numMorphNormals': numMorphNormals };
+				_gl.frontFace( _gl.CW );
 
 
-			}
+			} else {
 
 
-			vertices = face instanceof THREE.Face3 ? 3 : 4;
+				_gl.frontFace( _gl.CCW );
 
 
-			if ( geometry.geometryGroups[ groupHash ].vertices + vertices > 65535 ) {
+			}
 
 
-				hash_map[ materialIndex ].counter += 1;
-				groupHash = hash_map[ materialIndex ].hash + '_' + hash_map[ materialIndex ].counter;
+			_oldFlipSided = flipSided;
 
 
-				if ( geometry.geometryGroups[ groupHash ] === undefined ) {
+		}
 
 
-					geometry.geometryGroups[ groupHash ] = { 'faces3': [], 'faces4': [], 'materialIndex': materialIndex, 'vertices': 0, 'numMorphTargets': numMorphTargets, 'numMorphNormals': numMorphNormals };
+	}
 
 
-				}
+	function setPolygonOffset ( polygonoffset, factor, units ) {
 
 
-			}
+		if ( _oldPolygonOffset !== polygonoffset ) {
 
 
-			if ( face instanceof THREE.Face3 ) {
+			if ( polygonoffset ) {
 
 
-				geometry.geometryGroups[ groupHash ].faces3.push( f );
+				_gl.enable( _gl.POLYGON_OFFSET_FILL );
 
 
 			} else {
 			} else {
 
 
-				geometry.geometryGroups[ groupHash ].faces4.push( f );
+				_gl.disable( _gl.POLYGON_OFFSET_FILL );
 
 
 			}
 			}
 
 
-			geometry.geometryGroups[ groupHash ].vertices += vertices;
+			_oldPolygonOffset = polygonoffset;
 
 
 		}
 		}
 
 
-		geometry.geometryGroupsList = [];
-
-		for ( var g in geometry.geometryGroups ) {
+		if ( polygonoffset && ( _oldPolygonOffsetFactor !== factor || _oldPolygonOffsetUnits !== units ) ) {
 
 
-			geometry.geometryGroups[ g ].id = _geometryGroupCounter ++;
+			_gl.polygonOffset( factor, units );
 
 
-			geometry.geometryGroupsList.push( geometry.geometryGroups[ g ] );
+			_oldPolygonOffsetFactor = factor;
+			_oldPolygonOffsetUnits = units;
 
 
 		}
 		}
 
 
-	};
+	}
+
+	function setBlending( blending, blendEquation, blendSrc, blendDst ) {
+
+		if ( blending !== _oldBlending ) {
 
 
-	// Objects refresh
+			if ( blending === THREE.NoBlending ) {
 
 
-	this.initWebGLObjects = function ( scene ) {
+				_gl.disable( _gl.BLEND );
 
 
-		if ( !scene.__webglObjects ) {
+			} else if ( blending === THREE.AdditiveBlending ) {
 
 
-			scene.__webglObjects = [];
-			scene.__webglObjectsImmediate = [];
-			scene.__webglSprites = [];
-			scene.__webglFlares = [];
+				_gl.enable( _gl.BLEND );
+				_gl.blendEquation( _gl.FUNC_ADD );
+				_gl.blendFunc( _gl.SRC_ALPHA, _gl.ONE );
 
 
-		}
+			} else if ( blending === THREE.SubtractiveBlending ) {
 
 
-		while ( scene.__objectsAdded.length ) {
+				// TODO: Find blendFuncSeparate() combination
+				_gl.enable( _gl.BLEND );
+				_gl.blendEquation( _gl.FUNC_ADD );
+				_gl.blendFunc( _gl.ZERO, _gl.ONE_MINUS_SRC_COLOR );
 
 
-			addObject( scene.__objectsAdded[ 0 ], scene );
-			scene.__objectsAdded.splice( 0, 1 );
+			} else if ( blending === THREE.MultiplyBlending ) {
 
 
-		}
+				// TODO: Find blendFuncSeparate() combination
+				_gl.enable( _gl.BLEND );
+				_gl.blendEquation( _gl.FUNC_ADD );
+				_gl.blendFunc( _gl.ZERO, _gl.SRC_COLOR );
 
 
-		while ( scene.__objectsRemoved.length ) {
+			} else if ( blending === THREE.CustomBlending ) {
 
 
-			removeObject( scene.__objectsRemoved[ 0 ], scene );
-			scene.__objectsRemoved.splice( 0, 1 );
+				_gl.enable( _gl.BLEND );
 
 
-		}
+			} else {
 
 
-		// update must be called after objects adding / removal
+				_gl.enable( _gl.BLEND );
+				_gl.blendEquationSeparate( _gl.FUNC_ADD, _gl.FUNC_ADD );
+				_gl.blendFuncSeparate( _gl.SRC_ALPHA, _gl.ONE_MINUS_SRC_ALPHA, _gl.ONE, _gl.ONE_MINUS_SRC_ALPHA );
 
 
-		for ( var o = 0, ol = scene.__webglObjects.length; o < ol; o ++ ) {
+			}
 
 
-			updateObject( scene.__webglObjects[ o ].object );
+			_oldBlending = blending;
 
 
 		}
 		}
 
 
-	};
-
-	// Objects adding
+		if ( blending === THREE.CustomBlending ) {
 
 
-	function addObject ( object, scene ) {
+			if ( blendEquation !== _oldBlendEquation ) {
 
 
-		var g, geometry, material, geometryGroup;
+				_gl.blendEquation( paramThreeToGL( blendEquation ) );
 
 
-		if ( ! object.__webglInit ) {
+				_oldBlendEquation = blendEquation;
 
 
-			object.__webglInit = true;
+			}
 
 
-			object._modelViewMatrix = new THREE.Matrix4();
-			object._normalMatrix = new THREE.Matrix3();
+			if ( blendSrc !== _oldBlendSrc || blendDst !== _oldBlendDst ) {
 
 
-			if ( object.geometry !== undefined && object.geometry.__webglInit === undefined ) {
+				_gl.blendFunc( paramThreeToGL( blendSrc ), paramThreeToGL( blendDst ) );
 
 
-				object.geometry.__webglInit = true;
-				object.geometry.addEventListener( 'dispose', onGeometryDispose );
+				_oldBlendSrc = blendSrc;
+				_oldBlendDst = blendDst;
 
 
 			}
 			}
 
 
-			geometry = object.geometry;
+		} else {
 
 
-			if ( geometry === undefined ) {
+			_oldBlendEquation = null;
+			_oldBlendSrc = null;
+			_oldBlendDst = null;
 
 
-				// fail silently for now
+		}
 
 
-			} else if ( geometry instanceof THREE.BufferGeometry ) {
+	}
 
 
-				initDirectBuffers( geometry );
+	function setDepthTest( depthTest ) {
 
 
-			} else if ( object instanceof THREE.Mesh ) {
+		if ( _oldDepthTest !== depthTest ) {
 
 
-				material = object.material;
+			if ( depthTest ) {
 
 
-				if ( geometry.geometryGroups === undefined ) {
+				_gl.enable( _gl.DEPTH_TEST );
 
 
-					sortFacesByMaterial( geometry, material );
+			} else {
 
 
-				}
+				_gl.disable( _gl.DEPTH_TEST );
 
 
-				// create separate VBOs per geometry chunk
+			}
 
 
-				for ( g in geometry.geometryGroups ) {
+			_oldDepthTest = depthTest;
 
 
-					geometryGroup = geometry.geometryGroups[ g ];
+		}
 
 
-					// initialise VBO on the first access
+	}
 
 
-					if ( ! geometryGroup.__webglVertexBuffer ) {
+	function setDepthWrite( depthWrite ) {
 
 
-						createMeshBuffers( geometryGroup );
-						initMeshBuffers( geometryGroup, object );
+		if ( _oldDepthWrite !== depthWrite ) {
 
 
-						geometry.verticesNeedUpdate = true;
-						geometry.morphTargetsNeedUpdate = true;
-						geometry.elementsNeedUpdate = true;
-						geometry.uvsNeedUpdate = true;
-						geometry.normalsNeedUpdate = true;
-						geometry.tangentsNeedUpdate = true;
-						geometry.colorsNeedUpdate = true;
+			_gl.depthMask( depthWrite );
+			_oldDepthWrite = depthWrite;
 
 
-					}
+		}
 
 
-				}
+	}
 
 
-			} else if ( object instanceof THREE.Ribbon ) {
+	function setTexture( texture, slot ) {
 
 
-				if ( ! geometry.__webglVertexBuffer ) {
+		if ( texture.needsUpdate ) {
 
 
-					createRibbonBuffers( geometry );
-					initRibbonBuffers( geometry, object );
+			if ( ! texture.__webglInit ) {
 
 
-					geometry.verticesNeedUpdate = true;
-					geometry.colorsNeedUpdate = true;
-					geometry.normalsNeedUpdate = true;
+				texture.__webglInit = true;
 
 
-				}
+				//texture.addEventListener( 'dispose', onTextureDispose );
 
 
-			} else if ( object instanceof THREE.Line ) {
+				texture.__webglTexture = _gl.createTexture();
 
 
-				if ( ! geometry.__webglVertexBuffer ) {
+				//_this.info.memory.textures ++;
 
 
-					createLineBuffers( geometry );
-					initLineBuffers( geometry, object );
+			}
 
 
-					geometry.verticesNeedUpdate = true;
-					geometry.colorsNeedUpdate = true;
-					geometry.lineDistancesNeedUpdate = true;
+			_gl.activeTexture( _gl.TEXTURE0 + slot );
+			_gl.bindTexture( _gl.TEXTURE_2D, texture.__webglTexture );
 
 
-				}
+			_gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY );
+			_gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha );
+			_gl.pixelStorei( _gl.UNPACK_ALIGNMENT, texture.unpackAlignment );
 
 
-			} else if ( object instanceof THREE.ParticleSystem ) {
+			var image = texture.image,
+			isImagePowerOfTwo = isPowerOfTwo( image.width ) && isPowerOfTwo( image.height ),
+			glFormat = paramThreeToGL( texture.format ),
+			glType = paramThreeToGL( texture.type );
 
 
-				if ( ! geometry.__webglVertexBuffer ) {
+			setTextureParameters( _gl.TEXTURE_2D, texture, isImagePowerOfTwo );
 
 
-					createParticleBuffers( geometry );
-					initParticleBuffers( geometry, object );
+			var mipmap, mipmaps = texture.mipmaps;
 
 
-					geometry.verticesNeedUpdate = true;
-					geometry.colorsNeedUpdate = true;
+			if ( texture instanceof THREE.DataTexture ) {
 
 
-				}
+				// use manually created mipmaps if available
+				// if there are no manual mipmaps
+				// set 0 level mipmap and then use GL to generate other mipmap levels
 
 
-			}
+				if ( mipmaps.length > 0 && isImagePowerOfTwo ) {
 
 
-		}
+					for ( var i = 0, il = mipmaps.length; i < il; i ++ ) {
 
 
-		if ( ! object.__webglActive ) {
+						mipmap = mipmaps[ i ];
+						_gl.texImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
 
 
-			if ( object instanceof THREE.Mesh ) {
+					}
 
 
-				geometry = object.geometry;
+					texture.generateMipmaps = false;
 
 
-				if ( geometry instanceof THREE.BufferGeometry ) {
+				} else {
 
 
-					addBuffer( scene.__webglObjects, geometry, object );
+					_gl.texImage2D( _gl.TEXTURE_2D, 0, glFormat, image.width, image.height, 0, glFormat, glType, image.data );
 
 
-				} else if ( geometry instanceof THREE.Geometry ) {
+				}
 
 
-					for ( g in geometry.geometryGroups ) {
+			} else if ( texture instanceof THREE.CompressedTexture ) {
 
 
-						geometryGroup = geometry.geometryGroups[ g ];
+				// compressed textures can only use manually created mipmaps
+				// WebGL can't generate mipmaps for DDS textures
 
 
-						addBuffer( scene.__webglObjects, geometryGroup, object );
+				for( var i = 0, il = mipmaps.length; i < il; i ++ ) {
 
 
-					}
+					mipmap = mipmaps[ i ];
+					_gl.compressedTexImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, mipmap.data );
 
 
 				}
 				}
 
 
-			} else if ( object instanceof THREE.Ribbon ||
-						object instanceof THREE.Line ||
-						object instanceof THREE.ParticleSystem ) {
-
-				geometry = object.geometry;
-				addBuffer( scene.__webglObjects, geometry, object );
+			} else { // regular Texture (image, video, canvas)
 
 
-			} else if ( object instanceof THREE.ImmediateRenderObject || object.immediateRenderCallback ) {
+				// use manually created mipmaps if available
+				// if there are no manual mipmaps
+				// set 0 level mipmap and then use GL to generate other mipmap levels
 
 
-				addBufferImmediate( scene.__webglObjectsImmediate, object );
+				if ( mipmaps.length > 0 && isImagePowerOfTwo ) {
 
 
-			} else if ( object instanceof THREE.Sprite ) {
+					for ( var i = 0, il = mipmaps.length; i < il; i ++ ) {
 
 
-				scene.__webglSprites.push( object );
+						mipmap = mipmaps[ i ];
+						_gl.texImage2D( _gl.TEXTURE_2D, i, glFormat, glFormat, glType, mipmap );
 
 
-			} else if ( object instanceof THREE.LensFlare ) {
+					}
 
 
-				scene.__webglFlares.push( object );
+					texture.generateMipmaps = false;
 
 
-			}
+				} else {
 
 
-			object.__webglActive = true;
+					_gl.texImage2D( _gl.TEXTURE_2D, 0, glFormat, glFormat, glType, texture.image );
 
 
-		}
+				}
 
 
-	};
+			}
 
 
-	function addBuffer ( objlist, buffer, object ) {
+			if ( texture.generateMipmaps && isImagePowerOfTwo ) _gl.generateMipmap( _gl.TEXTURE_2D );
 
 
-		objlist.push(
-			{
-				buffer: buffer,
-				object: object,
-				opaque: null,
-				transparent: null
-			}
-		);
+			texture.needsUpdate = false;
 
 
-	};
+			if ( texture.onUpdate ) texture.onUpdate();
 
 
-	function addBufferImmediate ( objlist, object ) {
+		} else {
 
 
-		objlist.push(
-			{
-				object: object,
-				opaque: null,
-				transparent: null
-			}
-		);
+			_gl.activeTexture( _gl.TEXTURE0 + slot );
+			_gl.bindTexture( _gl.TEXTURE_2D, texture.__webglTexture );
 
 
-	};
+		}
 
 
-	// Objects updates
+	}
 
 
-	function updateObject ( object ) {
+	function setCubeTexture ( texture, slot ) {
 
 
-		var geometry = object.geometry,
-			geometryGroup, customAttributesDirty, material;
+		if ( texture.image.length === 6 ) {
 
 
-		if ( geometry instanceof THREE.BufferGeometry ) {
+			if ( texture.needsUpdate ) {
 
 
-			setDirectBuffers( geometry, _gl.DYNAMIC_DRAW, !geometry.dynamic );
+				if ( ! texture.image.__webglTextureCube ) {
 
 
-		} else if ( object instanceof THREE.Mesh ) {
+					texture.image.__webglTextureCube = _gl.createTexture();
 
 
-			// check all geometry groups
 
 
-			for( var i = 0, il = geometry.geometryGroupsList.length; i < il; i ++ ) {
+				}
 
 
-				geometryGroup = geometry.geometryGroupsList[ i ];
+				_gl.activeTexture( _gl.TEXTURE0 + slot );
+				_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, texture.image.__webglTextureCube );
 
 
-				material = getBufferMaterial( object, geometryGroup );
+				_gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY );
 
 
-				if ( geometry.buffersNeedUpdate ) {
+				var isCompressed = texture instanceof THREE.CompressedTexture;
 
 
-					initMeshBuffers( geometryGroup, object );
+				var cubeImage = [];
 
 
-				}
+				for ( var i = 0; i < 6; i ++ ) {
 
 
-				customAttributesDirty = material.attributes && areCustomAttributesDirty( material );
+					if ( _autoScaleCubemaps && ! isCompressed ) {
 
 
-				if ( geometry.verticesNeedUpdate || geometry.morphTargetsNeedUpdate || geometry.elementsNeedUpdate ||
-					 geometry.uvsNeedUpdate || geometry.normalsNeedUpdate ||
-					 geometry.colorsNeedUpdate || geometry.tangentsNeedUpdate || customAttributesDirty ) {
+						cubeImage[ i ] = clampToMaxSize( texture.image[ i ], _maxCubemapSize );
 
 
-					setMeshBuffers( geometryGroup, object, _gl.DYNAMIC_DRAW, !geometry.dynamic, material );
+					} else {
 
 
-				}
+						cubeImage[ i ] = texture.image[ i ];
 
 
-			}
+					}
 
 
-			geometry.verticesNeedUpdate = false;
-			geometry.morphTargetsNeedUpdate = false;
-			geometry.elementsNeedUpdate = false;
-			geometry.uvsNeedUpdate = false;
-			geometry.normalsNeedUpdate = false;
-			geometry.colorsNeedUpdate = false;
-			geometry.tangentsNeedUpdate = false;
+				}
 
 
-			geometry.buffersNeedUpdate = false;
+				var image = cubeImage[ 0 ],
+				isImagePowerOfTwo = isPowerOfTwo( image.width ) && isPowerOfTwo( image.height ),
+				glFormat = paramThreeToGL( texture.format ),
+				glType = paramThreeToGL( texture.type );
 
 
-			material.attributes && clearCustomAttributes( material );
+				setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture, isImagePowerOfTwo );
 
 
-		} else if ( object instanceof THREE.Ribbon ) {
+				for ( var i = 0; i < 6; i ++ ) {
 
 
-			material = getBufferMaterial( object, geometry );
+					if ( isCompressed ) {
 
 
-			customAttributesDirty = material.attributes && areCustomAttributesDirty( material );
+						var mipmap, mipmaps = cubeImage[ i ].mipmaps;
 
 
-			if ( geometry.verticesNeedUpdate || geometry.colorsNeedUpdate || geometry.normalsNeedUpdate || customAttributesDirty ) {
+						for( var j = 0, jl = mipmaps.length; j < jl; j ++ ) {
 
 
-				setRibbonBuffers( geometry, _gl.DYNAMIC_DRAW );
+							mipmap = mipmaps[ j ];
+							_gl.compressedTexImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glFormat, mipmap.width, mipmap.height, 0, mipmap.data );
 
 
-			}
+						}
 
 
-			geometry.verticesNeedUpdate = false;
-			geometry.colorsNeedUpdate = false;
-			geometry.normalsNeedUpdate = false;
+					} else {
 
 
-			material.attributes && clearCustomAttributes( material );
+						_gl.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, glFormat, glType, cubeImage[ i ] );
 
 
-		} else if ( object instanceof THREE.Line ) {
+					}
 
 
-			material = getBufferMaterial( object, geometry );
+				}
 
 
-			customAttributesDirty = material.attributes && areCustomAttributesDirty( material );
+				if ( texture.generateMipmaps && isImagePowerOfTwo ) {
 
 
-			if ( geometry.verticesNeedUpdate || geometry.colorsNeedUpdate || geometry.lineDistancesNeedUpdate || customAttributesDirty ) {
+					_gl.generateMipmap( _gl.TEXTURE_CUBE_MAP );
 
 
-				setLineBuffers( geometry, _gl.DYNAMIC_DRAW );
+				}
 
 
-			}
+				texture.needsUpdate = false;
 
 
-			geometry.verticesNeedUpdate = false;
-			geometry.colorsNeedUpdate = false;
-			geometry.lineDistancesNeedUpdate = false;
+				if ( texture.onUpdate ) texture.onUpdate();
 
 
-			material.attributes && clearCustomAttributes( material );
+			} else {
 
 
+				_gl.activeTexture( _gl.TEXTURE0 + slot );
+				_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, texture.image.__webglTextureCube );
 
 
-		} else if ( object instanceof THREE.ParticleSystem ) {
+			}
 
 
-			material = getBufferMaterial( object, geometry );
+		}
 
 
-			customAttributesDirty = material.attributes && areCustomAttributesDirty( material );
+	}
 
 
-			if ( geometry.verticesNeedUpdate || geometry.colorsNeedUpdate || object.sortParticles || customAttributesDirty ) {
+	// Textures
 
 
-				setParticleBuffers( geometry, _gl.DYNAMIC_DRAW, object );
+	function isPowerOfTwo ( value ) {
 
 
-			}
+		return ( value & ( value - 1 ) ) === 0;
 
 
-			geometry.verticesNeedUpdate = false;
-			geometry.colorsNeedUpdate = false;
+	}
 
 
-			material.attributes && clearCustomAttributes( material );
+	function setTextureParameters ( textureType, texture, isImagePowerOfTwo ) {
 
 
-		}
+		if ( isImagePowerOfTwo ) {
 
 
-	};
+			_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, paramThreeToGL( texture.wrapS ) );
+			_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, paramThreeToGL( texture.wrapT ) );
 
 
-	// Objects updates - custom attributes check
+			_gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, paramThreeToGL( texture.magFilter ) );
+			_gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, paramThreeToGL( texture.minFilter ) );
 
 
-	function areCustomAttributesDirty ( material ) {
+		} else {
 
 
-		for ( var a in material.attributes ) {
+			_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, _gl.CLAMP_TO_EDGE );
+			_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, _gl.CLAMP_TO_EDGE );
 
 
-			if ( material.attributes[ a ].needsUpdate ) return true;
+			_gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, filterFallback( texture.magFilter ) );
+			_gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, filterFallback( texture.minFilter ) );
 
 
 		}
 		}
 
 
-		return false;
-
-	};
+		if ( _glExtensionTextureFilterAnisotropic && texture.type !== THREE.FloatType ) {
 
 
-	function clearCustomAttributes ( material ) {
+			if ( texture.anisotropy > 1 || texture.__oldAnisotropy ) {
 
 
-		for ( var a in material.attributes ) {
+				_gl.texParameterf( textureType, _glExtensionTextureFilterAnisotropic.TEXTURE_MAX_ANISOTROPY_EXT, Math.min( texture.anisotropy, _maxAnisotropy ) );
+				texture.__oldAnisotropy = texture.anisotropy;
 
 
-			material.attributes[ a ].needsUpdate = false;
+			}
 
 
 		}
 		}
 
 
-	};
+	}
+
+	function setupFrameBuffer ( framebuffer, renderTarget, textureTarget ) {
+
+		_gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
+		_gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, textureTarget, renderTarget.__webglTexture, 0 );
 
 
-	// Objects removal
+	}
 
 
-	function removeObject ( object, scene ) {
+	function setupRenderBuffer ( renderbuffer, renderTarget  ) {
 
 
-		if ( object instanceof THREE.Mesh  ||
-			 object instanceof THREE.ParticleSystem ||
-			 object instanceof THREE.Ribbon ||
-			 object instanceof THREE.Line ) {
+		_gl.bindRenderbuffer( _gl.RENDERBUFFER, renderbuffer );
 
 
-			removeInstances( scene.__webglObjects, object );
+		if ( renderTarget.depthBuffer && ! renderTarget.stencilBuffer ) {
 
 
-		} else if ( object instanceof THREE.Sprite ) {
+			_gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.DEPTH_COMPONENT16, renderTarget.width, renderTarget.height );
+			_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer );
 
 
-			removeInstancesDirect( scene.__webglSprites, object );
+		/* For some reason this is not working. Defaulting to RGBA4.
+		} else if( ! renderTarget.depthBuffer && renderTarget.stencilBuffer ) {
 
 
-		} else if ( object instanceof THREE.LensFlare ) {
+			_gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.STENCIL_INDEX8, renderTarget.width, renderTarget.height );
+			_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.STENCIL_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer );
+		*/
+		} else if( renderTarget.depthBuffer && renderTarget.stencilBuffer ) {
 
 
-			removeInstancesDirect( scene.__webglFlares, object );
+			_gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.DEPTH_STENCIL, renderTarget.width, renderTarget.height );
+			_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer );
 
 
-		} else if ( object instanceof THREE.ImmediateRenderObject || object.immediateRenderCallback ) {
+		} else {
 
 
-			removeInstances( scene.__webglObjectsImmediate, object );
+			_gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.RGBA4, renderTarget.width, renderTarget.height );
 
 
 		}
 		}
 
 
-		object.__webglActive = false;
-
-	};
+	}
 
 
-	function removeInstances ( objlist, object ) {
+	function setRenderTarget( renderTarget ) {
 
 
-		for ( var o = objlist.length - 1; o >= 0; o -- ) {
+		var isCube = ( renderTarget instanceof THREE.WebGLRenderTargetCube );
 
 
-			if ( objlist[ o ].object === object ) {
+		if ( renderTarget && ! renderTarget.__webglFramebuffer ) {
 
 
-				objlist.splice( o, 1 );
+			if ( renderTarget.depthBuffer === undefined ) renderTarget.depthBuffer = true;
+			if ( renderTarget.stencilBuffer === undefined ) renderTarget.stencilBuffer = true;
 
 
-			}
+			//renderTarget.addEventListener( 'dispose', onRenderTargetDispose );
 
 
-		}
+			renderTarget.__webglTexture = _gl.createTexture();
 
 
-	};
+			//_this.info.memory.textures ++;
 
 
-	function removeInstancesDirect ( objlist, object ) {
+			// Setup texture, create render and frame buffers
 
 
-		for ( var o = objlist.length - 1; o >= 0; o -- ) {
+			var isTargetPowerOfTwo = isPowerOfTwo( renderTarget.width ) && isPowerOfTwo( renderTarget.height ),
+				glFormat = paramThreeToGL( renderTarget.format ),
+				glType = paramThreeToGL( renderTarget.type );
 
 
-			if ( objlist[ o ] === object ) {
+			if ( isCube ) {
 
 
-				objlist.splice( o, 1 );
+				renderTarget.__webglFramebuffer = [];
+				renderTarget.__webglRenderbuffer = [];
 
 
-			}
+				_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, renderTarget.__webglTexture );
+				setTextureParameters( _gl.TEXTURE_CUBE_MAP, renderTarget, isTargetPowerOfTwo );
 
 
-		}
+				for ( var i = 0; i < 6; i ++ ) {
 
 
-	};
+					renderTarget.__webglFramebuffer[ i ] = _gl.createFramebuffer();
+					renderTarget.__webglRenderbuffer[ i ] = _gl.createRenderbuffer();
 
 
-	// Materials
+					_gl.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null );
 
 
-	this.initMaterial = function ( material, lights, fog, object ) {
+					setupFrameBuffer( renderTarget.__webglFramebuffer[ i ], renderTarget, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i );
+					setupRenderBuffer( renderTarget.__webglRenderbuffer[ i ], renderTarget );
 
 
-		material.addEventListener( 'dispose', onMaterialDispose );
+				}
 
 
-		var u, a, identifiers, i, parameters, maxLightCount, maxBones, maxShadows, shaderID;
+				if ( isTargetPowerOfTwo ) _gl.generateMipmap( _gl.TEXTURE_CUBE_MAP );
 
 
-		if ( material instanceof THREE.MeshDepthMaterial ) {
+			} else {
 
 
-			shaderID = 'depth';
+				renderTarget.__webglFramebuffer = _gl.createFramebuffer();
 
 
-		} else if ( material instanceof THREE.MeshNormalMaterial ) {
+				if ( renderTarget.shareDepthFrom ) {
 
 
-			shaderID = 'normal';
+					renderTarget.__webglRenderbuffer = renderTarget.shareDepthFrom.__webglRenderbuffer;
 
 
-		} else if ( material instanceof THREE.MeshBasicMaterial ) {
+				} else {
 
 
-			shaderID = 'basic';
+					renderTarget.__webglRenderbuffer = _gl.createRenderbuffer();
 
 
-		} else if ( material instanceof THREE.MeshLambertMaterial ) {
+				}
 
 
-			shaderID = 'lambert';
+				_gl.bindTexture( _gl.TEXTURE_2D, renderTarget.__webglTexture );
+				setTextureParameters( _gl.TEXTURE_2D, renderTarget, isTargetPowerOfTwo );
 
 
-		} else if ( material instanceof THREE.MeshPhongMaterial ) {
+				_gl.texImage2D( _gl.TEXTURE_2D, 0, glFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null );
 
 
-			shaderID = 'phong';
+				setupFrameBuffer( renderTarget.__webglFramebuffer, renderTarget, _gl.TEXTURE_2D );
 
 
-		} else if ( material instanceof THREE.LineBasicMaterial ) {
+				if ( renderTarget.shareDepthFrom ) {
 
 
-			shaderID = 'basic';
+					if ( renderTarget.depthBuffer && ! renderTarget.stencilBuffer ) {
 
 
-		} else if ( material instanceof THREE.LineDashedMaterial ) {
+						_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.RENDERBUFFER, renderTarget.__webglRenderbuffer );
 
 
-			shaderID = 'dashed';
+					} else if ( renderTarget.depthBuffer && renderTarget.stencilBuffer ) {
 
 
-		} else if ( material instanceof THREE.ParticleBasicMaterial ) {
+						_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.RENDERBUFFER, renderTarget.__webglRenderbuffer );
 
 
-			shaderID = 'particle_basic';
+					}
 
 
-		}
+				} else {
 
 
-		if ( shaderID ) {
+					setupRenderBuffer( renderTarget.__webglRenderbuffer, renderTarget );
 
 
-			setMaterialShaders( material, THREE.ShaderLib[ shaderID ] );
+				}
 
 
-		}
+				if ( isTargetPowerOfTwo ) _gl.generateMipmap( _gl.TEXTURE_2D );
 
 
-		// heuristics to create shader parameters according to lights in the scene
-		// (not to blow over maxLights budget)
+			}
 
 
-		maxLightCount = allocateLights( lights );
+			// Release everything
 
 
-		maxShadows = allocateShadows( lights );
+			if ( isCube ) {
 
 
-		maxBones = allocateBones( object );
+				_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, null );
 
 
-		parameters = {
+			} else {
 
 
-			map: !!material.map,
-			envMap: !!material.envMap,
-			lightMap: !!material.lightMap,
-			bumpMap: !!material.bumpMap,
-			normalMap: !!material.normalMap,
-			specularMap: !!material.specularMap,
+				_gl.bindTexture( _gl.TEXTURE_2D, null );
 
 
-			vertexColors: material.vertexColors,
+			}
 
 
-			fog: fog,
-			useFog: material.fog,
-			fogExp: fog instanceof THREE.FogExp2,
+			_gl.bindRenderbuffer( _gl.RENDERBUFFER, null );
+			_gl.bindFramebuffer( _gl.FRAMEBUFFER, null );
 
 
-			sizeAttenuation: material.sizeAttenuation,
+		}
 
 
-			skinning: material.skinning,
-			maxBones: maxBones,
-			useVertexTexture: _supportsBoneTextures && object && object.useVertexTexture,
-			boneTextureWidth: object && object.boneTextureWidth,
-			boneTextureHeight: object && object.boneTextureHeight,
+		var framebuffer, width, height, vx, vy;
 
 
-			morphTargets: material.morphTargets,
-			morphNormals: material.morphNormals,
-			maxMorphTargets: this.maxMorphTargets,
-			maxMorphNormals: this.maxMorphNormals,
+		if ( renderTarget ) {
 
 
-			maxDirLights: maxLightCount.directional,
-			maxPointLights: maxLightCount.point,
-			maxSpotLights: maxLightCount.spot,
-			maxHemiLights: maxLightCount.hemi,
+			if ( isCube ) {
 
 
-			maxShadows: maxShadows,
-			shadowMapEnabled: this.shadowMapEnabled && object.receiveShadow,
-			shadowMapType: this.shadowMapType,
-			shadowMapDebug: this.shadowMapDebug,
-			shadowMapCascade: this.shadowMapCascade,
+				framebuffer = renderTarget.__webglFramebuffer[ renderTarget.activeCubeFace ];
 
 
-			alphaTest: material.alphaTest,
-			metal: material.metal,
-			perPixel: material.perPixel,
-			wrapAround: material.wrapAround,
-			doubleSided: material.side === THREE.DoubleSide,
-			flipSided: material.side === THREE.BackSide
+			} else {
 
 
-		};
+				framebuffer = renderTarget.__webglFramebuffer;
 
 
-		material.program = buildProgram( shaderID, material.fragmentShader, material.vertexShader, material.uniforms, material.attributes, material.defines, parameters );
+			}
 
 
-		var attributes = material.program.attributes;
+			width = renderTarget.width;
+			height = renderTarget.height;
 
 
-		if ( material.morphTargets ) {
+			vx = 0;
+			vy = 0;
 
 
-			material.numSupportedMorphTargets = 0;
+		} else {
 
 
-			var id, base = "morphTarget";
+			framebuffer = null;
 
 
-			for ( i = 0; i < this.maxMorphTargets; i ++ ) {
+			width = _viewportWidth;
+			height = _viewportHeight;
 
 
-				id = base + i;
+			vx = _viewportX;
+			vy = _viewportY;
 
 
-				if ( attributes[ id ] >= 0 ) {
+		}
 
 
-					material.numSupportedMorphTargets ++;
+		if ( framebuffer !== _currentFramebuffer ) {
 
 
-				}
+			_gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
+			_gl.viewport( vx, vy, width, height );
 
 
-			}
+			_currentFramebuffer = framebuffer;
 
 
 		}
 		}
 
 
-		if ( material.morphNormals ) {
+		_currentWidth = width;
+		_currentHeight = height;
 
 
-			material.numSupportedMorphNormals = 0;
+	}
 
 
-			var id, base = "morphNormal";
+	function clampToMaxSize ( image, maxSize ) {
 
 
-			for ( i = 0; i < this.maxMorphNormals; i ++ ) {
+		if ( image.width <= maxSize && image.height <= maxSize ) {
 
 
-				id = base + i;
+			return image;
 
 
-				if ( attributes[ id ] >= 0 ) {
+		}
 
 
-					material.numSupportedMorphNormals ++;
+		// Warning: Scaling through the canvas will only work with images that use
+		// premultiplied alpha.
 
 
-				}
+		var maxDimension = Math.max( image.width, image.height );
+		var newWidth = Math.floor( image.width * maxSize / maxDimension );
+		var newHeight = Math.floor( image.height * maxSize / maxDimension );
 
 
-			}
+		var canvas = document.createElement( 'canvas' );
+		canvas.width = newWidth;
+		canvas.height = newHeight;
 
 
-		}
+		var ctx = canvas.getContext( "2d" );
+		ctx.drawImage( image, 0, 0, image.width, image.height, 0, 0, newWidth, newHeight );
 
 
-		material.uniformsList = [];
+		return canvas;
 
 
-		for ( u in material.uniforms ) {
+	}
 
 
-			material.uniformsList.push( [ material.uniforms[ u ], u ] );
+	function updateRenderTargetMipmap ( renderTarget ) {
 
 
-		}
+		if ( renderTarget instanceof THREE.WebGLRenderTargetCube ) {
 
 
-	};
+			_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, renderTarget.__webglTexture );
+			_gl.generateMipmap( _gl.TEXTURE_CUBE_MAP );
+			_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, null );
 
 
-	function setMaterialShaders( material, shaders ) {
+		} else {
 
 
-		material.uniforms = THREE.UniformsUtils.clone( shaders.uniforms );
-		material.vertexShader = shaders.vertexShader;
-		material.fragmentShader = shaders.fragmentShader;
+			_gl.bindTexture( _gl.TEXTURE_2D, renderTarget.__webglTexture );
+			_gl.generateMipmap( _gl.TEXTURE_2D );
+			_gl.bindTexture( _gl.TEXTURE_2D, null );
 
 
-	};
+		}
 
 
-	function setProgram( camera, lights, fog, material, object ) {
+	}
 
 
-		_usedTextureUnits = 0;
+	function setCubeTextureDynamic ( texture, slot ) {
 
 
-		if ( material.needsUpdate ) {
+		_gl.activeTexture( _gl.TEXTURE0 + slot );
+		_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, texture.__webglTexture );
 
 
-			if ( material.program ) deallocateMaterial( material );
+	}
 
 
-			_this.initMaterial( material, lights, fog, object );
-			material.needsUpdate = false;
+	// Map three.js constants to WebGL constants
+	function paramThreeToGL ( p ) {
 
 
-		}
+		if ( p === THREE.RepeatWrapping ) return _gl.REPEAT;
+		if ( p === THREE.ClampToEdgeWrapping ) return _gl.CLAMP_TO_EDGE;
+		if ( p === THREE.MirroredRepeatWrapping ) return _gl.MIRRORED_REPEAT;
 
 
-		if ( material.morphTargets ) {
+		if ( p === THREE.NearestFilter ) return _gl.NEAREST;
+		if ( p === THREE.NearestMipMapNearestFilter ) return _gl.NEAREST_MIPMAP_NEAREST;
+		if ( p === THREE.NearestMipMapLinearFilter ) return _gl.NEAREST_MIPMAP_LINEAR;
 
 
-			if ( ! object.__webglMorphTargetInfluences ) {
+		if ( p === THREE.LinearFilter ) return _gl.LINEAR;
+		if ( p === THREE.LinearMipMapNearestFilter ) return _gl.LINEAR_MIPMAP_NEAREST;
+		if ( p === THREE.LinearMipMapLinearFilter ) return _gl.LINEAR_MIPMAP_LINEAR;
 
 
-				object.__webglMorphTargetInfluences = new Float32Array( _this.maxMorphTargets );
+		if ( p === THREE.UnsignedByteType ) return _gl.UNSIGNED_BYTE;
+		if ( p === THREE.UnsignedShort4444Type ) return _gl.UNSIGNED_SHORT_4_4_4_4;
+		if ( p === THREE.UnsignedShort5551Type ) return _gl.UNSIGNED_SHORT_5_5_5_1;
+		if ( p === THREE.UnsignedShort565Type ) return _gl.UNSIGNED_SHORT_5_6_5;
 
 
-			}
+		if ( p === THREE.ByteType ) return _gl.BYTE;
+		if ( p === THREE.ShortType ) return _gl.SHORT;
+		if ( p === THREE.UnsignedShortType ) return _gl.UNSIGNED_SHORT;
+		if ( p === THREE.IntType ) return _gl.INT;
+		if ( p === THREE.UnsignedIntType ) return _gl.UNSIGNED_INT;
+		if ( p === THREE.FloatType ) return _gl.FLOAT;
 
 
-		}
+		if ( p === THREE.AlphaFormat ) return _gl.ALPHA;
+		if ( p === THREE.RGBFormat ) return _gl.RGB;
+		if ( p === THREE.RGBAFormat ) return _gl.RGBA;
+		if ( p === THREE.LuminanceFormat ) return _gl.LUMINANCE;
+		if ( p === THREE.LuminanceAlphaFormat ) return _gl.LUMINANCE_ALPHA;
 
 
-		var refreshMaterial = false;
+		if ( p === THREE.AddEquation ) return _gl.FUNC_ADD;
+		if ( p === THREE.SubtractEquation ) return _gl.FUNC_SUBTRACT;
+		if ( p === THREE.ReverseSubtractEquation ) return _gl.FUNC_REVERSE_SUBTRACT;
 
 
-		var program = material.program,
-			p_uniforms = program.uniforms,
-			m_uniforms = material.uniforms;
+		if ( p === THREE.ZeroFactor ) return _gl.ZERO;
+		if ( p === THREE.OneFactor ) return _gl.ONE;
+		if ( p === THREE.SrcColorFactor ) return _gl.SRC_COLOR;
+		if ( p === THREE.OneMinusSrcColorFactor ) return _gl.ONE_MINUS_SRC_COLOR;
+		if ( p === THREE.SrcAlphaFactor ) return _gl.SRC_ALPHA;
+		if ( p === THREE.OneMinusSrcAlphaFactor ) return _gl.ONE_MINUS_SRC_ALPHA;
+		if ( p === THREE.DstAlphaFactor ) return _gl.DST_ALPHA;
+		if ( p === THREE.OneMinusDstAlphaFactor ) return _gl.ONE_MINUS_DST_ALPHA;
 
 
-		if ( program !== _currentProgram ) {
+		if ( p === THREE.DstColorFactor ) return _gl.DST_COLOR;
+		if ( p === THREE.OneMinusDstColorFactor ) return _gl.ONE_MINUS_DST_COLOR;
+		if ( p === THREE.SrcAlphaSaturateFactor ) return _gl.SRC_ALPHA_SATURATE;
 
 
-			_gl.useProgram( program );
-			_currentProgram = program;
+		if ( _glExtensionCompressedTextureS3TC !== undefined ) {
 
 
-			refreshMaterial = true;
+			if ( p === THREE.RGB_S3TC_DXT1_Format ) return _glExtensionCompressedTextureS3TC.COMPRESSED_RGB_S3TC_DXT1_EXT;
+			if ( p === THREE.RGBA_S3TC_DXT1_Format ) return _glExtensionCompressedTextureS3TC.COMPRESSED_RGBA_S3TC_DXT1_EXT;
+			if ( p === THREE.RGBA_S3TC_DXT3_Format ) return _glExtensionCompressedTextureS3TC.COMPRESSED_RGBA_S3TC_DXT3_EXT;
+			if ( p === THREE.RGBA_S3TC_DXT5_Format ) return _glExtensionCompressedTextureS3TC.COMPRESSED_RGBA_S3TC_DXT5_EXT;
 
 
 		}
 		}
 
 
-		if ( material.id !== _currentMaterialId ) {
+		return 0;
 
 
-			_currentMaterialId = material.id;
-			refreshMaterial = true;
+	}
 
 
-		}
+	function compileShader(vertexShader, fragmentShader){
 
 
-		if ( refreshMaterial || camera !== _currentCamera ) {
+		var program = _gl.createProgram();
 
 
-			_gl.uniformMatrix4fv( p_uniforms.projectionMatrix, false, camera.projectionMatrix.elements );
+		var glFragmentShader = getShader( "fragment", fragmentShader );
+		var glVertexShader = getShader( "vertex", vertexShader );
 
 
-			if ( camera !== _currentCamera ) _currentCamera = camera;
+		_gl.attachShader( program, glVertexShader );
+		_gl.attachShader( program, glFragmentShader );
 
 
-		}
+		_gl.linkProgram( program );
 
 
-		// skinning uniforms must be set even if material didn't change
-		// auto-setting of texture unit for bone texture must go before other textures
-		// not sure why, but otherwise weird things happen
+		if ( !_gl.getProgramParameter( program, _gl.LINK_STATUS ) ) {
 
 
-		if ( material.skinning ) {
+			console.error( "Could not initialise shader\n" + "VALIDATE_STATUS: " + _gl.getProgramParameter( program, _gl.VALIDATE_STATUS ) + ", gl error [" + _gl.getError() + "]" );
 
 
-			if ( _supportsBoneTextures && object.useVertexTexture ) {
+		}
 
 
-				if ( p_uniforms.boneTexture !== null ) {
+		// clean up
 
 
-					var textureUnit = getTextureUnit();
+		_gl.deleteShader( glFragmentShader );
+		_gl.deleteShader( glVertexShader );
 
 
-					_gl.uniform1i( p_uniforms.boneTexture, textureUnit );
-					_this.setTexture( object.boneTexture, textureUnit );
+		return program;
 
 
-				}
+	}
 
 
-			} else {
+	function resetState(){
 
 
-				if ( p_uniforms.boneGlobalMatrices !== null ) {
+		_oldBlending = -1;
+		_oldDepthTest = -1;
+		_oldDepthWrite = -1;
+		_oldDoubleSided = -1;
+		_oldFlipSided = -1;
 
 
-					_gl.uniformMatrix4fv( p_uniforms.boneGlobalMatrices, false, object.boneMatrices );
+	}
 
 
-				}
+	function getShader ( type, string ) {
 
 
-			}
+		var shader;
 
 
-		}
+		if ( type === "fragment" ) {
 
 
-		if ( refreshMaterial ) {
+			shader = _gl.createShader( _gl.FRAGMENT_SHADER );
 
 
-			// refresh uniforms common to several materials
+		} else if ( type === "vertex" ) {
 
 
-			if ( fog && material.fog ) {
+			shader = _gl.createShader( _gl.VERTEX_SHADER );
 
 
-				refreshUniformsFog( m_uniforms, fog );
+		}
 
 
-			}
+		_gl.shaderSource( shader, string );
+		_gl.compileShader( shader );
 
 
-			if ( material instanceof THREE.MeshPhongMaterial ||
-				 material instanceof THREE.MeshLambertMaterial ||
-				 material.lights ) {
+		if ( !_gl.getShaderParameter( shader, _gl.COMPILE_STATUS ) ) {
 
 
-				if ( _lightsNeedUpdate ) {
+			console.error( _gl.getShaderInfoLog( shader ) );
+			console.error( addLineNumbers( string ) );
+			return null;
 
 
-					setupLights( program, lights );
-					_lightsNeedUpdate = false;
+		}
 
 
-				}
+		return shader;
 
 
-				refreshUniformsLights( m_uniforms, _lights );
+	}
 
 
-			}
+	function addLineNumbers ( string ) {
 
 
-			if ( material instanceof THREE.MeshBasicMaterial ||
-				 material instanceof THREE.MeshLambertMaterial ||
-				 material instanceof THREE.MeshPhongMaterial ) {
+		var chunks = string.split( "\n" );
 
 
-				refreshUniformsCommon( m_uniforms, material );
+		for ( var i = 0, il = chunks.length; i < il; i ++ ) {
 
 
-			}
+			// Chrome reports shader errors on lines
+			// starting counting from 1
 
 
-			// refresh single material specific uniforms
+			chunks[ i ] = ( i + 1 ) + ": " + chunks[ i ];
 
 
-			if ( material instanceof THREE.LineBasicMaterial ) {
+		}
 
 
-				refreshUniformsLine( m_uniforms, material );
+		return chunks.join( "\n" );
 
 
-			} else if ( material instanceof THREE.LineDashedMaterial ) {
+	}
 
 
-				refreshUniformsLine( m_uniforms, material );
-				refreshUniformsDash( m_uniforms, material );
+	function setLineWidth ( width ) {
 
 
-			} else if ( material instanceof THREE.ParticleBasicMaterial ) {
+		if ( width !== _oldLineWidth ) {
 
 
-				refreshUniformsParticle( m_uniforms, material );
+			_gl.lineWidth( width );
 
 
-			} else if ( material instanceof THREE.MeshPhongMaterial ) {
+			_oldLineWidth = width;
 
 
-				refreshUniformsPhong( m_uniforms, material );
+		}
 
 
-			} else if ( material instanceof THREE.MeshLambertMaterial ) {
+	}
 
 
-				refreshUniformsLambert( m_uniforms, material );
+	return {
 
 
-			} else if ( material instanceof THREE.MeshDepthMaterial ) {
+		context: _gl,
+
+		autoScaleCubemaps: _autoScaleCubemaps,
+		supportsBoneTextures: _supportsBoneTextures,
+		precision: _precision,
+		maxVertexUniformVectors: _gl.getParameter( _gl.MAX_VERTEX_UNIFORM_VECTORS ),
+
+		// Methods
+
+		getContext: getContext,
+		getDomElement: getDomElement,
+		getPrecision: getPrecision,
+		getCurrentWidth: getCurrentWidth,
+		getCurrentHeight: getCurrentHeight,
+		supportsVertexTextures: supportsVertexTextures,
+		supportsFloatTextures: supportsFloatTextures,
+		supportsStandardDerivatives: supportsStandardDerivatives,
+		supportsCompressedTextureS3TC: supportsCompressedTextureS3TC,
+		getMaxAnisotropy: getMaxAnisotropy,
+
+		setRenderTarget: setRenderTarget,
+		setSize: setSize,
+		setViewport: setViewport,
+		setScissor: setScissor,
+		enableScissorTest: enableScissorTest,
+
+		setClearColorHex: setClearColorHex,
+		setClearColor: setClearColor,
+		getClearColor: getClearColor,
+		getClearAlpha: getClearAlpha,
+		clear: clear,
+		clearTarget: clearTarget,
+
+		deleteBuffer: deleteBuffer,
+		deleteTexture: deleteTexture,
+		deleteFramebuffer: deleteFramebuffer,
+		deleteRenderbuffer: deleteRenderbuffer,
+		deleteProgram: deleteProgram,
+
+		createBuffer: createBuffer,
+		setStaticArrayBuffer: setStaticArrayBuffer,
+		setStaticIndexBuffer: setStaticIndexBuffer,
+		setDynamicArrayBuffer: setDynamicArrayBuffer,
+		setDynamicIndexBuffer: setDynamicIndexBuffer,
+
+		drawTriangles: drawTriangles,
+		drawTriangleStrip: drawTriangleStrip,
+		drawLines: drawLines,
+		drawLineStrip: drawLineStrip,
+		drawPoints: drawPoints,
+		drawTriangleElements: drawTriangleElements,
+		drawLineElements: drawLineElements,
+
+		bindArrayBuffer: bindArrayBuffer,
+		bindElementArrayBuffer: bindElementArrayBuffer,
+
+		enableAttribute: enableAttribute,
+		disableAttributes: disableAttributes,
+		getAttribLocation: getAttribLocation,
+		setFloatAttribute: setFloatAttribute,
+
+		getUniformLocation: getUniformLocation,
+
+		uniform1i: uniform1i,
+		uniform1f: uniform1f,
+		uniform2f: uniform2f,
+		uniform3f: uniform3f,
+		uniform4f: uniform4f,
+		uniform1iv: uniform1iv,
+		uniform2iv: uniform2iv,
+		uniform3iv: uniform3iv,
+		uniform1fv: uniform1fv,
+		uniform2fv: uniform2fv,
+		uniform3fv: uniform3fv,
+		uniform4fv: uniform4fv,
+		uniformMatrix3fv: uniformMatrix3fv,
+		uniformMatrix4fv: uniformMatrix4fv,
+
+		useProgram: useProgram,
+		compileShader: compileShader,
+
+		setFaceCulling: setFaceCulling,
+		setMaterialFaces: setMaterialFaces,
+		setPolygonOffset: setPolygonOffset,
+		setBlending: setBlending,
+		setDepthTest: setDepthTest,
+		setDepthWrite: setDepthWrite,
+
+		setTexture: setTexture,
+		setCubeTexture: setCubeTexture,
+		updateRenderTargetMipmap: updateRenderTargetMipmap,
+		setCubeTextureDynamic: setCubeTextureDynamic,
+
+		paramThreeToGL: paramThreeToGL,
+		setLineWidth: setLineWidth,
+		resetState: resetState
 
 
-				m_uniforms.mNear.value = camera.near;
-				m_uniforms.mFar.value = camera.far;
-				m_uniforms.opacity.value = material.opacity;
+	}
 
 
-			} else if ( material instanceof THREE.MeshNormalMaterial ) {
+};
+
+THREE.WebGLRenderer.ShaderBuilder = function ( renderer, info ) {
+
+	this.renderer = renderer;
+	this.info = info;
+	this.programs = [],
+	this.programs_counter = 0;
+
+};
+
+THREE.extend( THREE.WebGLRenderer.ShaderBuilder.prototype, {
+
+	buildProgram: function ( shaderID, fragmentShader, vertexShader, uniforms, attributes, defines, parameters ) {
+
+		var renderer = this.renderer;
+		var p, pl, d, program, code;
+		var chunks = [];
+
+		// Generate code
+
+		if ( shaderID ) {
+
+			chunks.push( shaderID );
+
+		} else {
+
+			chunks.push( fragmentShader );
+			chunks.push( vertexShader );
+
+		}
+
+		for ( d in defines ) {
+
+			chunks.push( d );
+			chunks.push( defines[ d ] );
+
+		}
+
+		for ( p in parameters ) {
+
+			chunks.push( p );
+			chunks.push( parameters[ p ] );
+
+		}
+
+		code = chunks.join();
+
+		// Check if code has been already compiled
+
+		for ( p = 0, pl = this.programs.length; p < pl; p ++ ) {
+
+			var programInfo = this.programs[ p ];
+
+			if ( programInfo.code === code ) {
+
+				//console.log( "Code already compiled." /*: \n\n" + code*/ );
+
+				programInfo.usedTimes ++;
+
+				return programInfo.program;
+
+			}
+
+		}
+
+		var shadowMapTypeDefine = "SHADOWMAP_TYPE_BASIC";
+
+		if ( parameters.shadowMapType === THREE.PCFShadowMap ) {
+
+			shadowMapTypeDefine = "SHADOWMAP_TYPE_PCF";
+
+		} else if ( parameters.shadowMapType === THREE.PCFSoftShadowMap ) {
+
+			shadowMapTypeDefine = "SHADOWMAP_TYPE_PCF_SOFT";
+
+		}
+
+		//console.log( "building new program " );
+
+		//
+
+		var customDefines = this.generateDefines( defines );
+
+		//
+
+		var prefix_vertex = [
+
+			"precision " + renderer.precision + " float;",
+
+			customDefines,
+
+			renderer.supportsVertexTextures ? "#define VERTEX_TEXTURES" : "",
+
+			parameters.gammaInput ? "#define GAMMA_INPUT" : "",
+			parameters.gammaOutput ? "#define GAMMA_OUTPUT" : "",
+			parameters.physicallyBasedShading ? "#define PHYSICALLY_BASED_SHADING" : "",
+
+			"#define MAX_DIR_LIGHTS " + parameters.maxDirLights,
+			"#define MAX_POINT_LIGHTS " + parameters.maxPointLights,
+			"#define MAX_SPOT_LIGHTS " + parameters.maxSpotLights,
+			"#define MAX_HEMI_LIGHTS " + parameters.maxHemiLights,
+
+			"#define MAX_SHADOWS " + parameters.maxShadows,
+
+			"#define MAX_BONES " + parameters.maxBones,
+
+			parameters.map ? "#define USE_MAP" : "",
+			parameters.envMap ? "#define USE_ENVMAP" : "",
+			parameters.lightMap ? "#define USE_LIGHTMAP" : "",
+			parameters.bumpMap ? "#define USE_BUMPMAP" : "",
+			parameters.normalMap ? "#define USE_NORMALMAP" : "",
+			parameters.specularMap ? "#define USE_SPECULARMAP" : "",
+			parameters.vertexColors ? "#define USE_COLOR" : "",
+
+			parameters.skinning ? "#define USE_SKINNING" : "",
+			parameters.useVertexTexture ? "#define BONE_TEXTURE" : "",
+			parameters.boneTextureWidth ? "#define N_BONE_PIXEL_X " + parameters.boneTextureWidth.toFixed( 1 ) : "",
+			parameters.boneTextureHeight ? "#define N_BONE_PIXEL_Y " + parameters.boneTextureHeight.toFixed( 1 ) : "",
+
+			parameters.morphTargets ? "#define USE_MORPHTARGETS" : "",
+			parameters.morphNormals ? "#define USE_MORPHNORMALS" : "",
+			parameters.perPixel ? "#define PHONG_PER_PIXEL" : "",
+			parameters.wrapAround ? "#define WRAP_AROUND" : "",
+			parameters.doubleSided ? "#define DOUBLE_SIDED" : "",
+			parameters.flipSided ? "#define FLIP_SIDED" : "",
+
+			parameters.shadowMapEnabled ? "#define USE_SHADOWMAP" : "",
+			parameters.shadowMapEnabled ? "#define " + shadowMapTypeDefine : "",
+			parameters.shadowMapDebug ? "#define SHADOWMAP_DEBUG" : "",
+			parameters.shadowMapCascade ? "#define SHADOWMAP_CASCADE" : "",
+
+			parameters.sizeAttenuation ? "#define USE_SIZEATTENUATION" : "",
+
+			"uniform mat4 modelMatrix;",
+			"uniform mat4 modelViewMatrix;",
+			"uniform mat4 projectionMatrix;",
+			"uniform mat4 viewMatrix;",
+			"uniform mat3 normalMatrix;",
+			"uniform vec3 cameraPosition;",
+
+			"attribute vec3 position;",
+			"attribute vec3 normal;",
+			"attribute vec2 uv;",
+			"attribute vec2 uv2;",
+
+			"#ifdef USE_COLOR",
+
+				"attribute vec3 color;",
+
+			"#endif",
+
+			"#ifdef USE_MORPHTARGETS",
+
+				"attribute vec3 morphTarget0;",
+				"attribute vec3 morphTarget1;",
+				"attribute vec3 morphTarget2;",
+				"attribute vec3 morphTarget3;",
+
+				"#ifdef USE_MORPHNORMALS",
+
+					"attribute vec3 morphNormal0;",
+					"attribute vec3 morphNormal1;",
+					"attribute vec3 morphNormal2;",
+					"attribute vec3 morphNormal3;",
+
+				"#else",
+
+					"attribute vec3 morphTarget4;",
+					"attribute vec3 morphTarget5;",
+					"attribute vec3 morphTarget6;",
+					"attribute vec3 morphTarget7;",
+
+				"#endif",
+
+			"#endif",
+
+			"#ifdef USE_SKINNING",
+
+				"attribute vec4 skinIndex;",
+				"attribute vec4 skinWeight;",
+
+			"#endif",
+
+			""
+
+		].join("\n");
+
+		var prefix_fragment = [
+
+			"precision " + renderer.precision + " float;",
+
+			( parameters.bumpMap || parameters.normalMap ) ? "#extension GL_OES_standard_derivatives : enable" : "",
+
+			customDefines,
+
+			"#define MAX_DIR_LIGHTS " + parameters.maxDirLights,
+			"#define MAX_POINT_LIGHTS " + parameters.maxPointLights,
+			"#define MAX_SPOT_LIGHTS " + parameters.maxSpotLights,
+			"#define MAX_HEMI_LIGHTS " + parameters.maxHemiLights,
+
+			"#define MAX_SHADOWS " + parameters.maxShadows,
+
+			parameters.alphaTest ? "#define ALPHATEST " + parameters.alphaTest: "",
+
+			parameters.gammaInput ? "#define GAMMA_INPUT" : "",
+			parameters.gammaOutput ? "#define GAMMA_OUTPUT" : "",
+    		parameters.physicallyBasedShading ? "#define PHYSICALLY_BASED_SHADING" : "",
+
+			( parameters.useFog && parameters.fog ) ? "#define USE_FOG" : "",
+			( parameters.useFog && parameters.fogExp ) ? "#define FOG_EXP2" : "",
+
+			parameters.map ? "#define USE_MAP" : "",
+			parameters.envMap ? "#define USE_ENVMAP" : "",
+			parameters.lightMap ? "#define USE_LIGHTMAP" : "",
+			parameters.bumpMap ? "#define USE_BUMPMAP" : "",
+			parameters.normalMap ? "#define USE_NORMALMAP" : "",
+			parameters.specularMap ? "#define USE_SPECULARMAP" : "",
+			parameters.vertexColors ? "#define USE_COLOR" : "",
+
+			parameters.metal ? "#define METAL" : "",
+			parameters.perPixel ? "#define PHONG_PER_PIXEL" : "",
+			parameters.wrapAround ? "#define WRAP_AROUND" : "",
+			parameters.doubleSided ? "#define DOUBLE_SIDED" : "",
+			parameters.flipSided ? "#define FLIP_SIDED" : "",
+
+			parameters.shadowMapEnabled ? "#define USE_SHADOWMAP" : "",
+			parameters.shadowMapEnabled ? "#define " + shadowMapTypeDefine : "",
+			parameters.shadowMapDebug ? "#define SHADOWMAP_DEBUG" : "",
+			parameters.shadowMapCascade ? "#define SHADOWMAP_CASCADE" : "",
+
+			"uniform mat4 viewMatrix;",
+			"uniform vec3 cameraPosition;",
+			""
+
+		].join("\n");
+
+		program = renderer.compileShader(prefix_vertex + vertexShader, prefix_fragment + fragmentShader);
+
+		//console.log( prefix_fragment + fragmentShader );
+		//console.log( prefix_vertex + vertexShader );
+
+		program.uniforms = {};
+		program.attributes = {};
+
+		var identifiers, u, a, i;
+
+		// cache uniform locations
+
+		identifiers = [
+
+			'viewMatrix', 'modelViewMatrix', 'projectionMatrix', 'normalMatrix', 'modelMatrix', 'cameraPosition',
+			'morphTargetInfluences'
+
+		];
+
+		if ( parameters.useVertexTexture ) {
+
+			identifiers.push( 'boneTexture' );
+
+		} else {
+
+			identifiers.push( 'boneGlobalMatrices' );
+
+		}
+
+		for ( u in uniforms ) {
+
+			identifiers.push( u );
+
+		}
+
+		this.cacheUniformLocations( program, identifiers );
+
+		// cache attributes locations
+
+		identifiers = [
+
+			"position", "normal", "uv", "uv2", "tangent", "color",
+			"skinIndex", "skinWeight", "lineDistance"
+
+		];
+
+		for ( i = 0; i < parameters.maxMorphTargets; i ++ ) {
+
+			identifiers.push( "morphTarget" + i );
+
+		}
+
+		for ( i = 0; i < parameters.maxMorphNormals; i ++ ) {
+
+			identifiers.push( "morphNormal" + i );
+
+		}
+
+		for ( a in attributes ) {
+
+			identifiers.push( a );
+
+		}
+
+		this.cacheAttributeLocations( program, identifiers );
+
+		program.id = this.programs_counter ++;
+
+		this.programs.push( { program: program, code: code, usedTimes: 1 } );
+
+		this.info.memory.programs = this.programs.length;
+
+		return program;
+
+	},
+
+	generateDefines: function ( defines ) {
+
+		var value, chunk, chunks = [];
+
+		for ( var d in defines ) {
+
+			value = defines[ d ];
+			if ( value === false ) continue;
+
+			chunk = "#define " + d + " " + value;
+			chunks.push( chunk );
+
+		}
+
+		return chunks.join( "\n" );
+
+	},
+
+	// Shader parameters cache
+
+	cacheUniformLocations: function ( program, identifiers ) {
+
+		var i, l, id, renderer = this.renderer;
+
+		for ( i = 0, l = identifiers.length; i < l; i ++ ) {
+
+			id = identifiers[ i ];
+			program.uniforms[ id ] = renderer.getUniformLocation( program, id );
+
+		}
+
+	},
+
+	cacheAttributeLocations: function ( program, identifiers ) {
+
+		var i, l, id, renderer = this.renderer;
+
+		for( i = 0, l = identifiers.length; i < l; i ++ ) {
+
+			id = identifiers[ i ];
+			program.attributes[ id ] = renderer.getAttribLocation( program, id );
+
+		}
+
+	},
+
+	removeProgram: function ( program ) {
+
+		var i, il, programInfo;
+		var deleteProgram = false;
+		var programs = this.programs;
+
+		for ( i = 0, il = programs.length; i < il; i ++ ) {
+
+			programInfo = programs[ i ];
+
+			if ( programInfo.program === program ) {
+
+				programInfo.usedTimes --;
+
+				if ( programInfo.usedTimes === 0 ) {
+
+					deleteProgram = true;
+
+				}
+
+				break;
+
+			}
+
+		}
+
+		if ( deleteProgram === true ) {
+
+			// avoid using array.splice, this is costlier than creating new array from scratch
+
+			var newPrograms = [];
+
+			for ( i = 0, il = programs.length; i < il; i ++ ) {
+
+				programInfo = programs[ i ];
+
+				if ( programInfo.program !== program ) {
+
+					newPrograms.push( programInfo );
+
+				}
+
+			}
+
+			this.programs = newPrograms;
+
+			this.renderer.deleteProgram( program );
+
+			this.info.memory.programs --;
+
+		}
+
+	}
+
+} );
 
 
-				m_uniforms.opacity.value = material.opacity;
+THREE.WebGLRenderer.Object3DRenderer = function ( lowlevelrenderer, info ) {
 
 
-			}
+	this.renderer = lowlevelrenderer;
+	this.info = info;
 
 
-			if ( object.receiveShadow && ! material._shadowPass ) {
+};
 
 
-				refreshUniformsShadow( m_uniforms, lights );
+THREE.extend( THREE.WebGLRenderer.Object3DRenderer.prototype, {
 
 
-			}
+	getBufferMaterial: function ( object, geometryGroup ) {
 
 
-			// load common uniforms
+		return object.material instanceof THREE.MeshFaceMaterial
+			? object.material.materials[ geometryGroup.materialIndex ]
+			: object.material;
 
 
-			loadUniformsGeneric( program, material.uniformsList );
+	},
 
 
-			// load material specific uniforms
-			// (shader material also gets them for the sake of genericity)
+	bufferGuessUVType: function ( material ) {
 
 
-			if ( material instanceof THREE.ShaderMaterial ||
-				 material instanceof THREE.MeshPhongMaterial ||
-				 material.envMap ) {
+		// material must use some texture to require uvs
 
 
-				if ( p_uniforms.cameraPosition !== null ) {
+		if ( material.map || material.lightMap || material.bumpMap || material.normalMap || material.specularMap || material instanceof THREE.ShaderMaterial ) {
 
 
-					_vector3.getPositionFromMatrix( camera.matrixWorld );
-					_gl.uniform3f( p_uniforms.cameraPosition, _vector3.x, _vector3.y, _vector3.z );
+			return true;
 
 
-				}
+		}
 
 
-			}
+		return false;
 
 
-			if ( material instanceof THREE.MeshPhongMaterial ||
-				 material instanceof THREE.MeshLambertMaterial ||
-				 material instanceof THREE.ShaderMaterial ||
-				 material.skinning ) {
+	},
 
 
-				if ( p_uniforms.viewMatrix !== null ) {
+	bufferGuessNormalType: function ( material ) {
 
 
-					_gl.uniformMatrix4fv( p_uniforms.viewMatrix, false, camera.matrixWorldInverse.elements );
+		// only MeshBasicMaterial and MeshDepthMaterial don't need normals
 
 
-				}
+		if ( ( material instanceof THREE.MeshBasicMaterial && !material.envMap ) || material instanceof THREE.MeshDepthMaterial ) {
 
 
-			}
+			return false;
 
 
 		}
 		}
 
 
-		loadUniformsMatrices( p_uniforms, object );
+		if ( this.materialNeedsSmoothNormals( material ) ) {
 
 
-		if ( p_uniforms.modelMatrix !== null ) {
-
-			_gl.uniformMatrix4fv( p_uniforms.modelMatrix, false, object.matrixWorld.elements );
+			return THREE.SmoothShading;
 
 
-		}
+		} else {
 
 
-		return program;
+			return THREE.FlatShading;
 
 
-	};
+		}
 
 
-	// Uniforms (refresh uniforms objects)
+	},
 
 
-	function refreshUniformsCommon ( uniforms, material ) {
+	materialNeedsSmoothNormals: function ( material ) {
 
 
-		uniforms.opacity.value = material.opacity;
+		return material && material.shading !== undefined && material.shading === THREE.SmoothShading;
 
 
-		if ( _this.gammaInput ) {
+	},
 
 
-			uniforms.diffuse.value.copyGammaToLinear( material.color );
+	bufferGuessVertexColorType: function ( material ) {
 
 
-		} else {
+		if ( material.vertexColors ) {
 
 
-			uniforms.diffuse.value = material.color;
+			return material.vertexColors;
 
 
 		}
 		}
 
 
-		uniforms.map.value = material.map;
-		uniforms.lightMap.value = material.lightMap;
-		uniforms.specularMap.value = material.specularMap;
-
-		if ( material.bumpMap ) {
-
-			uniforms.bumpMap.value = material.bumpMap;
-			uniforms.bumpScale.value = material.bumpScale;
-
-		}
+		return false;
 
 
-		if ( material.normalMap ) {
+	},
 
 
-			uniforms.normalMap.value = material.normalMap;
-			uniforms.normalScale.value.copy( material.normalScale );
+	initCustomAttributes: function ( geometry, object ) {
 
 
-		}
+		var nvertices = geometry.vertices.length;
 
 
-		// uv repeat and offset setting priorities
-		//	1. color map
-		//	2. specular map
-		//	3. normal map
-		//	4. bump map
+		var material = object.material;
 
 
-		var uvScaleMap;
+		if ( material.attributes ) {
 
 
-		if ( material.map ) {
+			if ( geometry.__webglCustomAttributesList === undefined ) {
 
 
-			uvScaleMap = material.map;
+				geometry.__webglCustomAttributesList = [];
 
 
-		} else if ( material.specularMap ) {
+			}
 
 
-			uvScaleMap = material.specularMap;
+			for ( var a in material.attributes ) {
 
 
-		} else if ( material.normalMap ) {
+				var attribute = material.attributes[ a ];
 
 
-			uvScaleMap = material.normalMap;
+				if ( !attribute.__webglInitialized || attribute.createUniqueBuffers ) {
 
 
-		} else if ( material.bumpMap ) {
+					attribute.__webglInitialized = true;
 
 
-			uvScaleMap = material.bumpMap;
+					var size = 1;		// "f" and "i"
 
 
-		}
+					if ( attribute.type === "v2" ) size = 2;
+					else if ( attribute.type === "v3" ) size = 3;
+					else if ( attribute.type === "v4" ) size = 4;
+					else if ( attribute.type === "c"  ) size = 3;
 
 
-		if ( uvScaleMap !== undefined ) {
+					attribute.size = size;
 
 
-			var offset = uvScaleMap.offset;
-			var repeat = uvScaleMap.repeat;
+					attribute.array = new Float32Array( nvertices * size );
 
 
-			uniforms.offsetRepeat.value.set( offset.x, offset.y, repeat.x, repeat.y );
+					attribute.buffer = this.renderer.createBuffer();
+					attribute.buffer.belongsToAttribute = a;
 
 
-		}
+					attribute.needsUpdate = true;
 
 
-		uniforms.envMap.value = material.envMap;
-		uniforms.flipEnvMap.value = ( material.envMap instanceof THREE.WebGLRenderTargetCube ) ? 1 : -1;
+				}
 
 
-		if ( _this.gammaInput ) {
+				geometry.__webglCustomAttributesList.push( attribute );
 
 
-			//uniforms.reflectivity.value = material.reflectivity * material.reflectivity;
-			uniforms.reflectivity.value = material.reflectivity;
+			}
 
 
-		} else {
+		}
 
 
-			uniforms.reflectivity.value = material.reflectivity;
+	},
 
 
-		}
+	numericalSort: function ( a, b ) {
 
 
-		uniforms.refractionRatio.value = material.refractionRatio;
-		uniforms.combine.value = material.combine;
-		uniforms.useRefract.value = material.envMap && material.envMap.mapping instanceof THREE.CubeRefractionMapping;
+		return b[ 0 ] - a[ 0 ];
 
 
-	};
+	}
 
 
-	function refreshUniformsLine ( uniforms, material ) {
+} );
 
 
-		uniforms.diffuse.value = material.color;
-		uniforms.opacity.value = material.opacity;
+THREE.WebGLRenderer.MeshRenderer = function ( lowlevelrenderer, info ) {
 
 
-	};
+	THREE.WebGLRenderer.Object3DRenderer.call( this, lowlevelrenderer, info );
 
 
-	function refreshUniformsDash ( uniforms, material ) {
+};
 
 
-		uniforms.dashSize.value = material.dashSize;
-		uniforms.totalSize.value = material.dashSize + material.gapSize;
-		uniforms.scale.value = material.scale;
+THREE.WebGLRenderer.MeshRenderer.prototype = Object.create( THREE.WebGLRenderer.Object3DRenderer.prototype );
 
 
-	};
+THREE.extend( THREE.WebGLRenderer.MeshRenderer.prototype, {
 
 
-	function refreshUniformsParticle ( uniforms, material ) {
+	createBuffers: function ( geometryGroup ) {
 
 
-		uniforms.psColor.value = material.color;
-		uniforms.opacity.value = material.opacity;
-		uniforms.size.value = material.size;
-		uniforms.scale.value = _canvas.height / 2.0; // TODO: Cache this.
+		var renderer = this.renderer;
+		geometryGroup.__webglVertexBuffer = renderer.createBuffer();
+		geometryGroup.__webglNormalBuffer = renderer.createBuffer();
+		geometryGroup.__webglTangentBuffer = renderer.createBuffer();
+		geometryGroup.__webglColorBuffer = renderer.createBuffer();
+		geometryGroup.__webglUVBuffer = renderer.createBuffer();
+		geometryGroup.__webglUV2Buffer = renderer.createBuffer();
 
 
-		uniforms.map.value = material.map;
+		geometryGroup.__webglSkinIndicesBuffer = renderer.createBuffer();
+		geometryGroup.__webglSkinWeightsBuffer = renderer.createBuffer();
 
 
-	};
+		geometryGroup.__webglFaceBuffer = renderer.createBuffer();
+		geometryGroup.__webglLineBuffer = renderer.createBuffer();
 
 
-	function refreshUniformsFog ( uniforms, fog ) {
+		var m, ml;
 
 
-		uniforms.fogColor.value = fog.color;
+		if ( geometryGroup.numMorphTargets ) {
 
 
-		if ( fog instanceof THREE.Fog ) {
+			geometryGroup.__webglMorphTargetsBuffers = [];
 
 
-			uniforms.fogNear.value = fog.near;
-			uniforms.fogFar.value = fog.far;
+			for ( m = 0, ml = geometryGroup.numMorphTargets; m < ml; m ++ ) {
 
 
-		} else if ( fog instanceof THREE.FogExp2 ) {
+				geometryGroup.__webglMorphTargetsBuffers.push( renderer.createBuffer() );
 
 
-			uniforms.fogDensity.value = fog.density;
+			}
 
 
 		}
 		}
 
 
-	};
+		if ( geometryGroup.numMorphNormals ) {
 
 
-	function refreshUniformsPhong ( uniforms, material ) {
+			geometryGroup.__webglMorphNormalsBuffers = [];
 
 
-		uniforms.shininess.value = material.shininess;
+			for ( m = 0, ml = geometryGroup.numMorphNormals; m < ml; m ++ ) {
 
 
-		if ( _this.gammaInput ) {
+				geometryGroup.__webglMorphNormalsBuffers.push( renderer.createBuffer() );
 
 
-			uniforms.ambient.value.copyGammaToLinear( material.ambient );
-			uniforms.emissive.value.copyGammaToLinear( material.emissive );
-			uniforms.specular.value.copyGammaToLinear( material.specular );
+			}
 
 
-		} else {
+		}
 
 
-			uniforms.ambient.value = material.ambient;
-			uniforms.emissive.value = material.emissive;
-			uniforms.specular.value = material.specular;
+		this.info.memory.geometries ++;
 
 
-		}
+	},
 
 
-		if ( material.wrapAround ) {
+	initBuffers: function ( geometryGroup, object ) {
 
 
-			uniforms.wrapRGB.value.copy( material.wrapRGB );
+		var geometry = object.geometry,
+			faces3 = geometryGroup.faces3,
+			faces4 = geometryGroup.faces4,
 
 
-		}
+			nvertices = faces3.length * 3 + faces4.length * 4,
+			ntris     = faces3.length * 1 + faces4.length * 2,
+			nlines    = faces3.length * 3 + faces4.length * 4,
 
 
-	};
+			material = this.getBufferMaterial( object, geometryGroup ),
 
 
-	function refreshUniformsLambert ( uniforms, material ) {
+			uvType = this.bufferGuessUVType( material ),
+			normalType = this.bufferGuessNormalType( material ),
+			vertexColorType = this.bufferGuessVertexColorType( material );
 
 
-		if ( _this.gammaInput ) {
+		//console.log( "uvType", uvType, "normalType", normalType, "vertexColorType", vertexColorType, object, geometryGroup, material );
 
 
-			uniforms.ambient.value.copyGammaToLinear( material.ambient );
-			uniforms.emissive.value.copyGammaToLinear( material.emissive );
+		geometryGroup.__vertexArray = new Float32Array( nvertices * 3 );
 
 
-		} else {
+		if ( normalType ) {
 
 
-			uniforms.ambient.value = material.ambient;
-			uniforms.emissive.value = material.emissive;
+			geometryGroup.__normalArray = new Float32Array( nvertices * 3 );
 
 
 		}
 		}
 
 
-		if ( material.wrapAround ) {
+		if ( geometry.hasTangents ) {
 
 
-			uniforms.wrapRGB.value.copy( material.wrapRGB );
+			geometryGroup.__tangentArray = new Float32Array( nvertices * 4 );
 
 
 		}
 		}
 
 
-	};
+		if ( vertexColorType ) {
 
 
-	function refreshUniformsLights ( uniforms, lights ) {
+			geometryGroup.__colorArray = new Float32Array( nvertices * 3 );
 
 
-		uniforms.ambientLightColor.value = lights.ambient;
+		}
 
 
-		uniforms.directionalLightColor.value = lights.directional.colors;
-		uniforms.directionalLightDirection.value = lights.directional.positions;
+		if ( uvType ) {
 
 
-		uniforms.pointLightColor.value = lights.point.colors;
-		uniforms.pointLightPosition.value = lights.point.positions;
-		uniforms.pointLightDistance.value = lights.point.distances;
+			if ( geometry.faceUvs.length > 0 || geometry.faceVertexUvs.length > 0 ) {
 
 
-		uniforms.spotLightColor.value = lights.spot.colors;
-		uniforms.spotLightPosition.value = lights.spot.positions;
-		uniforms.spotLightDistance.value = lights.spot.distances;
-		uniforms.spotLightDirection.value = lights.spot.directions;
-		uniforms.spotLightAngleCos.value = lights.spot.anglesCos;
-		uniforms.spotLightExponent.value = lights.spot.exponents;
+				geometryGroup.__uvArray = new Float32Array( nvertices * 2 );
 
 
-		uniforms.hemisphereLightSkyColor.value = lights.hemi.skyColors;
-		uniforms.hemisphereLightGroundColor.value = lights.hemi.groundColors;
-		uniforms.hemisphereLightDirection.value = lights.hemi.positions;
+			}
 
 
-	};
+			if ( geometry.faceUvs.length > 1 || geometry.faceVertexUvs.length > 1 ) {
 
 
-	function refreshUniformsShadow ( uniforms, lights ) {
+				geometryGroup.__uv2Array = new Float32Array( nvertices * 2 );
 
 
-		if ( uniforms.shadowMatrix ) {
+			}
 
 
-			var j = 0;
+		}
 
 
-			for ( var i = 0, il = lights.length; i < il; i ++ ) {
+		if ( object.geometry.skinWeights.length && object.geometry.skinIndices.length ) {
 
 
-				var light = lights[ i ];
+			geometryGroup.__skinIndexArray = new Float32Array( nvertices * 4 );
+			geometryGroup.__skinWeightArray = new Float32Array( nvertices * 4 );
 
 
-				if ( ! light.castShadow ) continue;
+		}
 
 
-				if ( light instanceof THREE.SpotLight || ( light instanceof THREE.DirectionalLight && ! light.shadowCascade ) ) {
+		geometryGroup.__faceArray = new Uint16Array( ntris * 3 );
+		geometryGroup.__lineArray = new Uint16Array( nlines * 2 );
 
 
-					uniforms.shadowMap.value[ j ] = light.shadowMap;
-					uniforms.shadowMapSize.value[ j ] = light.shadowMapSize;
+		var m, ml;
 
 
-					uniforms.shadowMatrix.value[ j ] = light.shadowMatrix;
+		if ( geometryGroup.numMorphTargets ) {
 
 
-					uniforms.shadowDarkness.value[ j ] = light.shadowDarkness;
-					uniforms.shadowBias.value[ j ] = light.shadowBias;
+			geometryGroup.__morphTargetsArrays = [];
 
 
-					j ++;
+			for ( m = 0, ml = geometryGroup.numMorphTargets; m < ml; m ++ ) {
 
 
-				}
+				geometryGroup.__morphTargetsArrays.push( new Float32Array( nvertices * 3 ) );
 
 
 			}
 			}
 
 
 		}
 		}
 
 
-	};
-
-	// Uniforms (load to GPU)
-
-	function loadUniformsMatrices ( uniforms, object ) {
-
-		_gl.uniformMatrix4fv( uniforms.modelViewMatrix, false, object._modelViewMatrix.elements );
-
-		if ( uniforms.normalMatrix ) {
-
-			_gl.uniformMatrix3fv( uniforms.normalMatrix, false, object._normalMatrix.elements );
-
-		}
-
-	};
+		if ( geometryGroup.numMorphNormals ) {
 
 
-	function getTextureUnit() {
+			geometryGroup.__morphNormalsArrays = [];
 
 
-		var textureUnit = _usedTextureUnits;
+			for ( m = 0, ml = geometryGroup.numMorphNormals; m < ml; m ++ ) {
 
 
-		if ( textureUnit >= _maxTextures ) {
+				geometryGroup.__morphNormalsArrays.push( new Float32Array( nvertices * 3 ) );
 
 
-			console.warn( "WebGLRenderer: trying to use " + textureUnit + " texture units while this GPU supports only " + _maxTextures );
+			}
 
 
 		}
 		}
 
 
-		_usedTextureUnits += 1;
-
-		return textureUnit;
+		geometryGroup.__webglFaceCount = ntris * 3;
+		geometryGroup.__webglLineCount = nlines * 2;
 
 
-	};
 
 
-	function loadUniformsGeneric ( program, uniforms ) {
+		// custom attributes
 
 
-		var uniform, value, type, location, texture, textureUnit, i, il, j, jl, offset;
+		if ( material.attributes ) {
 
 
-		for ( j = 0, jl = uniforms.length; j < jl; j ++ ) {
+			if ( geometryGroup.__webglCustomAttributesList === undefined ) {
 
 
-			location = program.uniforms[ uniforms[ j ][ 1 ] ];
-			if ( !location ) continue;
+				geometryGroup.__webglCustomAttributesList = [];
 
 
-			uniform = uniforms[ j ][ 0 ];
+			}
 
 
-			type = uniform.type;
-			value = uniform.value;
+			for ( var a in material.attributes ) {
 
 
-			if ( type === "i" ) { // single integer
+				// Do a shallow copy of the attribute object so different geometryGroup chunks use different
+				// attribute buffers which are correctly indexed in the setMeshBuffers function
 
 
-				_gl.uniform1i( location, value );
+				var originalAttribute = material.attributes[ a ];
 
 
-			} else if ( type === "f" ) { // single float
+				var attribute = {};
 
 
-				_gl.uniform1f( location, value );
+				for ( var property in originalAttribute ) {
 
 
-			} else if ( type === "v2" ) { // single THREE.Vector2
+					attribute[ property ] = originalAttribute[ property ];
 
 
-				_gl.uniform2f( location, value.x, value.y );
+				}
 
 
-			} else if ( type === "v3" ) { // single THREE.Vector3
+				if ( !attribute.__webglInitialized || attribute.createUniqueBuffers ) {
 
 
-				_gl.uniform3f( location, value.x, value.y, value.z );
+					attribute.__webglInitialized = true;
 
 
-			} else if ( type === "v4" ) { // single THREE.Vector4
+					var size = 1;		// "f" and "i"
 
 
-				_gl.uniform4f( location, value.x, value.y, value.z, value.w );
+					if( attribute.type === "v2" ) size = 2;
+					else if( attribute.type === "v3" ) size = 3;
+					else if( attribute.type === "v4" ) size = 4;
+					else if( attribute.type === "c"  ) size = 3;
 
 
-			} else if ( type === "c" ) { // single THREE.Color
+					attribute.size = size;
 
 
-				_gl.uniform3f( location, value.r, value.g, value.b );
+					attribute.array = new Float32Array( nvertices * size );
 
 
-			} else if ( type === "iv1" ) { // flat array of integers (JS or typed array)
+					attribute.buffer = this.renderer.createBuffer();
+					attribute.buffer.belongsToAttribute = a;
 
 
-				_gl.uniform1iv( location, value );
+					originalAttribute.needsUpdate = true;
+					attribute.__original = originalAttribute;
 
 
-			} else if ( type === "iv" ) { // flat array of integers with 3 x N size (JS or typed array)
+				}
 
 
-				_gl.uniform3iv( location, value );
+				geometryGroup.__webglCustomAttributesList.push( attribute );
 
 
-			} else if ( type === "fv1" ) { // flat array of floats (JS or typed array)
+			}
 
 
-				_gl.uniform1fv( location, value );
+		}
 
 
-			} else if ( type === "fv" ) { // flat array of floats with 3 x N size (JS or typed array)
+		geometryGroup.__inittedArrays = true;
 
 
-				_gl.uniform3fv( location, value );
+	},
 
 
-			} else if ( type === "v2v" ) { // array of THREE.Vector2
+	setBuffers: function ( geometryGroup, object, dispose, material ) {
 
 
-				if ( uniform._array === undefined ) {
+		if ( ! geometryGroup.__inittedArrays ) {
 
 
-					uniform._array = new Float32Array( 2 * value.length );
+			return;
 
 
-				}
+		}
 
 
-				for ( i = 0, il = value.length; i < il; i ++ ) {
+		var renderer = this.renderer;
+		var normalType = this.bufferGuessNormalType( material ),
+		vertexColorType = this.bufferGuessVertexColorType( material ),
+		uvType = this.bufferGuessUVType( material ),
 
 
-					offset = i * 2;
+		needsSmoothNormals = ( normalType === THREE.SmoothShading );
 
 
-					uniform._array[ offset ] 	 = value[ i ].x;
-					uniform._array[ offset + 1 ] = value[ i ].y;
+		var f, fl, fi, face,
+		vertexNormals, faceNormal, normal,
+		vertexColors, faceColor,
+		vertexTangents,
+		uv, uv2, v1, v2, v3, v4, t1, t2, t3, t4, n1, n2, n3, n4,
+		c1, c2, c3, c4,
+		sw1, sw2, sw3, sw4,
+		si1, si2, si3, si4,
+		sa1, sa2, sa3, sa4,
+		sb1, sb2, sb3, sb4,
+		m, ml, i, il,
+		vn, uvi, uv2i,
+		vk, vkl, vka,
+		nka, chf, faceVertexNormals,
+		a,
 
 
-				}
+		vertexIndex = 0,
 
 
-				_gl.uniform2fv( location, uniform._array );
+		offset = 0,
+		offset_uv = 0,
+		offset_uv2 = 0,
+		offset_face = 0,
+		offset_normal = 0,
+		offset_tangent = 0,
+		offset_line = 0,
+		offset_color = 0,
+		offset_skin = 0,
+		offset_morphTarget = 0,
+		offset_custom = 0,
+		offset_customSrc = 0,
 
 
-			} else if ( type === "v3v" ) { // array of THREE.Vector3
+		value,
 
 
-				if ( uniform._array === undefined ) {
+		vertexArray = geometryGroup.__vertexArray,
+		uvArray = geometryGroup.__uvArray,
+		uv2Array = geometryGroup.__uv2Array,
+		normalArray = geometryGroup.__normalArray,
+		tangentArray = geometryGroup.__tangentArray,
+		colorArray = geometryGroup.__colorArray,
 
 
-					uniform._array = new Float32Array( 3 * value.length );
+		skinIndexArray = geometryGroup.__skinIndexArray,
+		skinWeightArray = geometryGroup.__skinWeightArray,
 
 
-				}
+		morphTargetsArrays = geometryGroup.__morphTargetsArrays,
+		morphNormalsArrays = geometryGroup.__morphNormalsArrays,
 
 
-				for ( i = 0, il = value.length; i < il; i ++ ) {
+		customAttributes = geometryGroup.__webglCustomAttributesList,
+		customAttribute,
 
 
-					offset = i * 3;
+		faceArray = geometryGroup.__faceArray,
+		lineArray = geometryGroup.__lineArray,
 
 
-					uniform._array[ offset ] 	 = value[ i ].x;
-					uniform._array[ offset + 1 ] = value[ i ].y;
-					uniform._array[ offset + 2 ] = value[ i ].z;
+		geometry = object.geometry, // this is shared for all chunks
 
 
-				}
+		dirtyVertices = geometry.verticesNeedUpdate,
+		dirtyElements = geometry.elementsNeedUpdate,
+		dirtyUvs = geometry.uvsNeedUpdate,
+		dirtyNormals = geometry.normalsNeedUpdate,
+		dirtyTangents = geometry.tangentsNeedUpdate,
+		dirtyColors = geometry.colorsNeedUpdate,
+		dirtyMorphTargets = geometry.morphTargetsNeedUpdate,
 
 
-				_gl.uniform3fv( location, uniform._array );
+		vertices = geometry.vertices,
+		chunk_faces3 = geometryGroup.faces3,
+		chunk_faces4 = geometryGroup.faces4,
+		obj_faces = geometry.faces,
 
 
-			} else if ( type === "v4v" ) { // array of THREE.Vector4
+		obj_uvs  = geometry.faceVertexUvs[ 0 ],
+		obj_uvs2 = geometry.faceVertexUvs[ 1 ],
 
 
-				if ( uniform._array === undefined ) {
+		obj_colors = geometry.colors,
 
 
-					uniform._array = new Float32Array( 4 * value.length );
+		obj_skinIndices = geometry.skinIndices,
+		obj_skinWeights = geometry.skinWeights,
 
 
-				}
+		morphTargets = geometry.morphTargets,
+		morphNormals = geometry.morphNormals;
 
 
-				for ( i = 0, il = value.length; i < il; i ++ ) {
+		if ( dirtyVertices ) {
 
 
-					offset = i * 4;
+			for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
 
 
-					uniform._array[ offset ] 	 = value[ i ].x;
-					uniform._array[ offset + 1 ] = value[ i ].y;
-					uniform._array[ offset + 2 ] = value[ i ].z;
-					uniform._array[ offset + 3 ] = value[ i ].w;
+				face = obj_faces[ chunk_faces3[ f ] ];
 
 
-				}
+				v1 = vertices[ face.a ];
+				v2 = vertices[ face.b ];
+				v3 = vertices[ face.c ];
 
 
-				_gl.uniform4fv( location, uniform._array );
+				vertexArray[ offset ]     = v1.x;
+				vertexArray[ offset + 1 ] = v1.y;
+				vertexArray[ offset + 2 ] = v1.z;
 
 
-			} else if ( type === "m4") { // single THREE.Matrix4
+				vertexArray[ offset + 3 ] = v2.x;
+				vertexArray[ offset + 4 ] = v2.y;
+				vertexArray[ offset + 5 ] = v2.z;
 
 
-				if ( uniform._array === undefined ) {
+				vertexArray[ offset + 6 ] = v3.x;
+				vertexArray[ offset + 7 ] = v3.y;
+				vertexArray[ offset + 8 ] = v3.z;
 
 
-					uniform._array = new Float32Array( 16 );
+				offset += 9;
 
 
-				}
+			}
 
 
-				value.flattenToArray( uniform._array );
-				_gl.uniformMatrix4fv( location, false, uniform._array );
+			for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
 
 
-			} else if ( type === "m4v" ) { // array of THREE.Matrix4
+				face = obj_faces[ chunk_faces4[ f ] ];
 
 
-				if ( uniform._array === undefined ) {
+				v1 = vertices[ face.a ];
+				v2 = vertices[ face.b ];
+				v3 = vertices[ face.c ];
+				v4 = vertices[ face.d ];
 
 
-					uniform._array = new Float32Array( 16 * value.length );
+				vertexArray[ offset ]     = v1.x;
+				vertexArray[ offset + 1 ] = v1.y;
+				vertexArray[ offset + 2 ] = v1.z;
 
 
-				}
+				vertexArray[ offset + 3 ] = v2.x;
+				vertexArray[ offset + 4 ] = v2.y;
+				vertexArray[ offset + 5 ] = v2.z;
 
 
-				for ( i = 0, il = value.length; i < il; i ++ ) {
+				vertexArray[ offset + 6 ] = v3.x;
+				vertexArray[ offset + 7 ] = v3.y;
+				vertexArray[ offset + 8 ] = v3.z;
 
 
-					value[ i ].flattenToArrayOffset( uniform._array, i * 16 );
+				vertexArray[ offset + 9 ]  = v4.x;
+				vertexArray[ offset + 10 ] = v4.y;
+				vertexArray[ offset + 11 ] = v4.z;
 
 
-				}
+				offset += 12;
 
 
-				_gl.uniformMatrix4fv( location, false, uniform._array );
+			}
 
 
-			} else if ( type === "t" ) { // single THREE.Texture (2d or cube)
+			renderer.setDynamicArrayBuffer( geometryGroup.__webglVertexBuffer, vertexArray);
 
 
-				texture = value;
-				textureUnit = getTextureUnit();
+		}
 
 
-				_gl.uniform1i( location, textureUnit );
+		if ( dirtyMorphTargets ) {
 
 
-				if ( !texture ) continue;
+			for ( vk = 0, vkl = morphTargets.length; vk < vkl; vk ++ ) {
 
 
-				if ( texture.image instanceof Array && texture.image.length === 6 ) {
+				offset_morphTarget = 0;
 
 
-					setCubeTexture( texture, textureUnit );
+				for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
 
 
-				} else if ( texture instanceof THREE.WebGLRenderTargetCube ) {
+					chf = chunk_faces3[ f ];
+					face = obj_faces[ chf ];
 
 
-					setCubeTextureDynamic( texture, textureUnit );
+					// morph positions
 
 
-				} else {
+					v1 = morphTargets[ vk ].vertices[ face.a ];
+					v2 = morphTargets[ vk ].vertices[ face.b ];
+					v3 = morphTargets[ vk ].vertices[ face.c ];
 
 
-					_this.setTexture( texture, textureUnit );
+					vka = morphTargetsArrays[ vk ];
 
 
-				}
+					vka[ offset_morphTarget ] 	  = v1.x;
+					vka[ offset_morphTarget + 1 ] = v1.y;
+					vka[ offset_morphTarget + 2 ] = v1.z;
 
 
-			} else if ( type === "tv" ) { // array of THREE.Texture (2d)
+					vka[ offset_morphTarget + 3 ] = v2.x;
+					vka[ offset_morphTarget + 4 ] = v2.y;
+					vka[ offset_morphTarget + 5 ] = v2.z;
 
 
-				if ( uniform._array === undefined ) {
+					vka[ offset_morphTarget + 6 ] = v3.x;
+					vka[ offset_morphTarget + 7 ] = v3.y;
+					vka[ offset_morphTarget + 8 ] = v3.z;
 
 
-					uniform._array = [];
+					// morph normals
 
 
-				}
+					if ( material.morphNormals ) {
 
 
-				for( i = 0, il = uniform.value.length; i < il; i ++ ) {
+						if ( needsSmoothNormals ) {
 
 
-					uniform._array[ i ] = getTextureUnit();
+							faceVertexNormals = morphNormals[ vk ].vertexNormals[ chf ];
 
 
-				}
+							n1 = faceVertexNormals.a;
+							n2 = faceVertexNormals.b;
+							n3 = faceVertexNormals.c;
 
 
-				_gl.uniform1iv( location, uniform._array );
+						} else {
 
 
-				for( i = 0, il = uniform.value.length; i < il; i ++ ) {
+							n1 = morphNormals[ vk ].faceNormals[ chf ];
+							n2 = n1;
+							n3 = n1;
 
 
-					texture = uniform.value[ i ];
-					textureUnit = uniform._array[ i ];
+						}
 
 
-					if ( !texture ) continue;
+						nka = morphNormalsArrays[ vk ];
 
 
-					_this.setTexture( texture, textureUnit );
+						nka[ offset_morphTarget ] 	  = n1.x;
+						nka[ offset_morphTarget + 1 ] = n1.y;
+						nka[ offset_morphTarget + 2 ] = n1.z;
 
 
-				}
+						nka[ offset_morphTarget + 3 ] = n2.x;
+						nka[ offset_morphTarget + 4 ] = n2.y;
+						nka[ offset_morphTarget + 5 ] = n2.z;
 
 
-			}
+						nka[ offset_morphTarget + 6 ] = n3.x;
+						nka[ offset_morphTarget + 7 ] = n3.y;
+						nka[ offset_morphTarget + 8 ] = n3.z;
 
 
-		}
+					}
 
 
-	};
+					//
 
 
-	function setupMatrices ( object, camera ) {
+					offset_morphTarget += 9;
 
 
-		object._modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld );
+				}
 
 
-		object._normalMatrix.getInverse( object._modelViewMatrix );
-		object._normalMatrix.transpose();
+				for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
 
 
-	};
+					chf = chunk_faces4[ f ];
+					face = obj_faces[ chf ];
 
 
-	//
+					// morph positions
 
 
-	function setColorGamma( array, offset, color, intensitySq ) {
+					v1 = morphTargets[ vk ].vertices[ face.a ];
+					v2 = morphTargets[ vk ].vertices[ face.b ];
+					v3 = morphTargets[ vk ].vertices[ face.c ];
+					v4 = morphTargets[ vk ].vertices[ face.d ];
 
 
-		array[ offset ]     = color.r * color.r * intensitySq;
-		array[ offset + 1 ] = color.g * color.g * intensitySq;
-		array[ offset + 2 ] = color.b * color.b * intensitySq;
+					vka = morphTargetsArrays[ vk ];
 
 
-	};
+					vka[ offset_morphTarget ] 	  = v1.x;
+					vka[ offset_morphTarget + 1 ] = v1.y;
+					vka[ offset_morphTarget + 2 ] = v1.z;
 
 
-	function setColorLinear( array, offset, color, intensity ) {
+					vka[ offset_morphTarget + 3 ] = v2.x;
+					vka[ offset_morphTarget + 4 ] = v2.y;
+					vka[ offset_morphTarget + 5 ] = v2.z;
 
 
-		array[ offset ]     = color.r * intensity;
-		array[ offset + 1 ] = color.g * intensity;
-		array[ offset + 2 ] = color.b * intensity;
+					vka[ offset_morphTarget + 6 ] = v3.x;
+					vka[ offset_morphTarget + 7 ] = v3.y;
+					vka[ offset_morphTarget + 8 ] = v3.z;
 
 
-	};
+					vka[ offset_morphTarget + 9 ]  = v4.x;
+					vka[ offset_morphTarget + 10 ] = v4.y;
+					vka[ offset_morphTarget + 11 ] = v4.z;
 
 
-	function setupLights ( program, lights ) {
+					// morph normals
 
 
-		var l, ll, light, n,
-		r = 0, g = 0, b = 0,
-		color, skyColor, groundColor,
-		intensity,  intensitySq,
-		position,
-		distance,
+					if ( material.morphNormals ) {
 
 
-		zlights = _lights,
+						if ( needsSmoothNormals ) {
 
 
-		dirColors = zlights.directional.colors,
-		dirPositions = zlights.directional.positions,
+							faceVertexNormals = morphNormals[ vk ].vertexNormals[ chf ];
 
 
-		pointColors = zlights.point.colors,
-		pointPositions = zlights.point.positions,
-		pointDistances = zlights.point.distances,
+							n1 = faceVertexNormals.a;
+							n2 = faceVertexNormals.b;
+							n3 = faceVertexNormals.c;
+							n4 = faceVertexNormals.d;
 
 
-		spotColors = zlights.spot.colors,
-		spotPositions = zlights.spot.positions,
-		spotDistances = zlights.spot.distances,
-		spotDirections = zlights.spot.directions,
-		spotAnglesCos = zlights.spot.anglesCos,
-		spotExponents = zlights.spot.exponents,
+						} else {
 
 
-		hemiSkyColors = zlights.hemi.skyColors,
-		hemiGroundColors = zlights.hemi.groundColors,
-		hemiPositions = zlights.hemi.positions,
+							n1 = morphNormals[ vk ].faceNormals[ chf ];
+							n2 = n1;
+							n3 = n1;
+							n4 = n1;
 
 
-		dirLength = 0,
-		pointLength = 0,
-		spotLength = 0,
-		hemiLength = 0,
+						}
 
 
-		dirCount = 0,
-		pointCount = 0,
-		spotCount = 0,
-		hemiCount = 0,
+						nka = morphNormalsArrays[ vk ];
 
 
-		dirOffset = 0,
-		pointOffset = 0,
-		spotOffset = 0,
-		hemiOffset = 0;
+						nka[ offset_morphTarget ] 	  = n1.x;
+						nka[ offset_morphTarget + 1 ] = n1.y;
+						nka[ offset_morphTarget + 2 ] = n1.z;
 
 
-		for ( l = 0, ll = lights.length; l < ll; l ++ ) {
+						nka[ offset_morphTarget + 3 ] = n2.x;
+						nka[ offset_morphTarget + 4 ] = n2.y;
+						nka[ offset_morphTarget + 5 ] = n2.z;
 
 
-			light = lights[ l ];
+						nka[ offset_morphTarget + 6 ] = n3.x;
+						nka[ offset_morphTarget + 7 ] = n3.y;
+						nka[ offset_morphTarget + 8 ] = n3.z;
 
 
-			if ( light.onlyShadow ) continue;
+						nka[ offset_morphTarget + 9 ]  = n4.x;
+						nka[ offset_morphTarget + 10 ] = n4.y;
+						nka[ offset_morphTarget + 11 ] = n4.z;
 
 
-			color = light.color;
-			intensity = light.intensity;
-			distance = light.distance;
+					}
 
 
-			if ( light instanceof THREE.AmbientLight ) {
+					//
 
 
-				if ( ! light.visible ) continue;
+					offset_morphTarget += 12;
 
 
-				if ( _this.gammaInput ) {
+				}
 
 
-					r += color.r * color.r;
-					g += color.g * color.g;
-					b += color.b * color.b;
+				this.renderer.setDynamicArrayBuffer( geometryGroup.__webglMorphTargetsBuffers[ vk ], morphTargetsArrays[ vk ]);
 
 
-				} else {
+				if ( material.morphNormals ) {
 
 
-					r += color.r;
-					g += color.g;
-					b += color.b;
+					this.renderer.setDynamicArrayBuffer( geometryGroup.__webglMorphNormalsBuffers[ vk ], morphNormalsArrays[ vk ]);
 
 
 				}
 				}
 
 
-			} else if ( light instanceof THREE.DirectionalLight ) {
+			}
+
+		}
 
 
-				dirCount += 1;
+		if ( obj_skinWeights.length ) {
 
 
-				if ( ! light.visible ) continue;
+			for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
 
 
-				_direction.getPositionFromMatrix( light.matrixWorld );
-				_vector3.getPositionFromMatrix( light.target.matrixWorld );
-				_direction.sub( _vector3 );
-				_direction.normalize();
+				face = obj_faces[ chunk_faces3[ f ]	];
 
 
-				// skip lights with undefined direction
-				// these create troubles in OpenGL (making pixel black)
+				// weights
 
 
-				if ( _direction.x === 0 && _direction.y === 0 && _direction.z === 0 ) continue;
+				sw1 = obj_skinWeights[ face.a ];
+				sw2 = obj_skinWeights[ face.b ];
+				sw3 = obj_skinWeights[ face.c ];
 
 
-				dirOffset = dirLength * 3;
+				skinWeightArray[ offset_skin ]     = sw1.x;
+				skinWeightArray[ offset_skin + 1 ] = sw1.y;
+				skinWeightArray[ offset_skin + 2 ] = sw1.z;
+				skinWeightArray[ offset_skin + 3 ] = sw1.w;
 
 
-				dirPositions[ dirOffset ]     = _direction.x;
-				dirPositions[ dirOffset + 1 ] = _direction.y;
-				dirPositions[ dirOffset + 2 ] = _direction.z;
+				skinWeightArray[ offset_skin + 4 ] = sw2.x;
+				skinWeightArray[ offset_skin + 5 ] = sw2.y;
+				skinWeightArray[ offset_skin + 6 ] = sw2.z;
+				skinWeightArray[ offset_skin + 7 ] = sw2.w;
 
 
-				if ( _this.gammaInput ) {
+				skinWeightArray[ offset_skin + 8 ]  = sw3.x;
+				skinWeightArray[ offset_skin + 9 ]  = sw3.y;
+				skinWeightArray[ offset_skin + 10 ] = sw3.z;
+				skinWeightArray[ offset_skin + 11 ] = sw3.w;
 
 
-					setColorGamma( dirColors, dirOffset, color, intensity * intensity );
+				// indices
 
 
-				} else {
+				si1 = obj_skinIndices[ face.a ];
+				si2 = obj_skinIndices[ face.b ];
+				si3 = obj_skinIndices[ face.c ];
 
 
-					setColorLinear( dirColors, dirOffset, color, intensity );
+				skinIndexArray[ offset_skin ]     = si1.x;
+				skinIndexArray[ offset_skin + 1 ] = si1.y;
+				skinIndexArray[ offset_skin + 2 ] = si1.z;
+				skinIndexArray[ offset_skin + 3 ] = si1.w;
 
 
-				}
+				skinIndexArray[ offset_skin + 4 ] = si2.x;
+				skinIndexArray[ offset_skin + 5 ] = si2.y;
+				skinIndexArray[ offset_skin + 6 ] = si2.z;
+				skinIndexArray[ offset_skin + 7 ] = si2.w;
 
 
-				dirLength += 1;
+				skinIndexArray[ offset_skin + 8 ]  = si3.x;
+				skinIndexArray[ offset_skin + 9 ]  = si3.y;
+				skinIndexArray[ offset_skin + 10 ] = si3.z;
+				skinIndexArray[ offset_skin + 11 ] = si3.w;
 
 
-			} else if ( light instanceof THREE.PointLight ) {
+				offset_skin += 12;
 
 
-				pointCount += 1;
+			}
 
 
-				if ( ! light.visible ) continue;
+			for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
 
 
-				pointOffset = pointLength * 3;
+				face = obj_faces[ chunk_faces4[ f ] ];
 
 
-				if ( _this.gammaInput ) {
+				// weights
 
 
-					setColorGamma( pointColors, pointOffset, color, intensity * intensity );
+				sw1 = obj_skinWeights[ face.a ];
+				sw2 = obj_skinWeights[ face.b ];
+				sw3 = obj_skinWeights[ face.c ];
+				sw4 = obj_skinWeights[ face.d ];
 
 
-				} else {
+				skinWeightArray[ offset_skin ]     = sw1.x;
+				skinWeightArray[ offset_skin + 1 ] = sw1.y;
+				skinWeightArray[ offset_skin + 2 ] = sw1.z;
+				skinWeightArray[ offset_skin + 3 ] = sw1.w;
 
 
-					setColorLinear( pointColors, pointOffset, color, intensity );
+				skinWeightArray[ offset_skin + 4 ] = sw2.x;
+				skinWeightArray[ offset_skin + 5 ] = sw2.y;
+				skinWeightArray[ offset_skin + 6 ] = sw2.z;
+				skinWeightArray[ offset_skin + 7 ] = sw2.w;
 
 
-				}
+				skinWeightArray[ offset_skin + 8 ]  = sw3.x;
+				skinWeightArray[ offset_skin + 9 ]  = sw3.y;
+				skinWeightArray[ offset_skin + 10 ] = sw3.z;
+				skinWeightArray[ offset_skin + 11 ] = sw3.w;
 
 
-				_vector3.getPositionFromMatrix( light.matrixWorld );
+				skinWeightArray[ offset_skin + 12 ] = sw4.x;
+				skinWeightArray[ offset_skin + 13 ] = sw4.y;
+				skinWeightArray[ offset_skin + 14 ] = sw4.z;
+				skinWeightArray[ offset_skin + 15 ] = sw4.w;
 
 
-				pointPositions[ pointOffset ]     = _vector3.x;
-				pointPositions[ pointOffset + 1 ] = _vector3.y;
-				pointPositions[ pointOffset + 2 ] = _vector3.z;
+				// indices
 
 
-				pointDistances[ pointLength ] = distance;
+				si1 = obj_skinIndices[ face.a ];
+				si2 = obj_skinIndices[ face.b ];
+				si3 = obj_skinIndices[ face.c ];
+				si4 = obj_skinIndices[ face.d ];
 
 
-				pointLength += 1;
+				skinIndexArray[ offset_skin ]     = si1.x;
+				skinIndexArray[ offset_skin + 1 ] = si1.y;
+				skinIndexArray[ offset_skin + 2 ] = si1.z;
+				skinIndexArray[ offset_skin + 3 ] = si1.w;
 
 
-			} else if ( light instanceof THREE.SpotLight ) {
+				skinIndexArray[ offset_skin + 4 ] = si2.x;
+				skinIndexArray[ offset_skin + 5 ] = si2.y;
+				skinIndexArray[ offset_skin + 6 ] = si2.z;
+				skinIndexArray[ offset_skin + 7 ] = si2.w;
 
 
-				spotCount += 1;
+				skinIndexArray[ offset_skin + 8 ]  = si3.x;
+				skinIndexArray[ offset_skin + 9 ]  = si3.y;
+				skinIndexArray[ offset_skin + 10 ] = si3.z;
+				skinIndexArray[ offset_skin + 11 ] = si3.w;
 
 
-				if ( ! light.visible ) continue;
+				skinIndexArray[ offset_skin + 12 ] = si4.x;
+				skinIndexArray[ offset_skin + 13 ] = si4.y;
+				skinIndexArray[ offset_skin + 14 ] = si4.z;
+				skinIndexArray[ offset_skin + 15 ] = si4.w;
 
 
-				spotOffset = spotLength * 3;
+				offset_skin += 16;
 
 
-				if ( _this.gammaInput ) {
+			}
 
 
-					setColorGamma( spotColors, spotOffset, color, intensity * intensity );
+			if ( offset_skin > 0 ) {
 
 
-				} else {
+			renderer.setDynamicArrayBuffer( geometryGroup.__webglSkinIndicesBuffer, skinIndexArray);
+			renderer.setDynamicArrayBuffer( geometryGroup.__webglSkinWeightsBuffer, skinWeightArray);
 
 
-					setColorLinear( spotColors, spotOffset, color, intensity );
+			}
 
 
-				}
+		}
 
 
-				_vector3.getPositionFromMatrix( light.matrixWorld );
+		if ( dirtyColors && vertexColorType ) {
 
 
-				spotPositions[ spotOffset ]     = _vector3.x;
-				spotPositions[ spotOffset + 1 ] = _vector3.y;
-				spotPositions[ spotOffset + 2 ] = _vector3.z;
+			for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
 
 
-				spotDistances[ spotLength ] = distance;
+				face = obj_faces[ chunk_faces3[ f ]	];
 
 
-				_direction.copy( _vector3 );
-				_vector3.getPositionFromMatrix( light.target.matrixWorld );
-				_direction.sub( _vector3 );
-				_direction.normalize();
+				vertexColors = face.vertexColors;
+				faceColor = face.color;
 
 
-				spotDirections[ spotOffset ]     = _direction.x;
-				spotDirections[ spotOffset + 1 ] = _direction.y;
-				spotDirections[ spotOffset + 2 ] = _direction.z;
+				if ( vertexColors.length === 3 && vertexColorType === THREE.VertexColors ) {
 
 
-				spotAnglesCos[ spotLength ] = Math.cos( light.angle );
-				spotExponents[ spotLength ] = light.exponent;
+					c1 = vertexColors[ 0 ];
+					c2 = vertexColors[ 1 ];
+					c3 = vertexColors[ 2 ];
 
 
-				spotLength += 1;
+				} else {
 
 
-			} else if ( light instanceof THREE.HemisphereLight ) {
+					c1 = faceColor;
+					c2 = faceColor;
+					c3 = faceColor;
 
 
-				hemiCount += 1;
+				}
 
 
-				if ( ! light.visible ) continue;
+				colorArray[ offset_color ]     = c1.r;
+				colorArray[ offset_color + 1 ] = c1.g;
+				colorArray[ offset_color + 2 ] = c1.b;
 
 
-				_direction.getPositionFromMatrix( light.matrixWorld );
-				_direction.normalize();
+				colorArray[ offset_color + 3 ] = c2.r;
+				colorArray[ offset_color + 4 ] = c2.g;
+				colorArray[ offset_color + 5 ] = c2.b;
 
 
-				// skip lights with undefined direction
-				// these create troubles in OpenGL (making pixel black)
+				colorArray[ offset_color + 6 ] = c3.r;
+				colorArray[ offset_color + 7 ] = c3.g;
+				colorArray[ offset_color + 8 ] = c3.b;
 
 
-				if ( _direction.x === 0 && _direction.y === 0 && _direction.z === 0 ) continue;
+				offset_color += 9;
 
 
-				hemiOffset = hemiLength * 3;
+			}
 
 
-				hemiPositions[ hemiOffset ]     = _direction.x;
-				hemiPositions[ hemiOffset + 1 ] = _direction.y;
-				hemiPositions[ hemiOffset + 2 ] = _direction.z;
+			for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
 
 
-				skyColor = light.color;
-				groundColor = light.groundColor;
+				face = obj_faces[ chunk_faces4[ f ] ];
 
 
-				if ( _this.gammaInput ) {
+				vertexColors = face.vertexColors;
+				faceColor = face.color;
 
 
-					intensitySq = intensity * intensity;
+				if ( vertexColors.length === 4 && vertexColorType === THREE.VertexColors ) {
 
 
-					setColorGamma( hemiSkyColors, hemiOffset, skyColor, intensitySq );
-					setColorGamma( hemiGroundColors, hemiOffset, groundColor, intensitySq );
+					c1 = vertexColors[ 0 ];
+					c2 = vertexColors[ 1 ];
+					c3 = vertexColors[ 2 ];
+					c4 = vertexColors[ 3 ];
 
 
 				} else {
 				} else {
 
 
-					setColorLinear( hemiSkyColors, hemiOffset, skyColor, intensity );
-					setColorLinear( hemiGroundColors, hemiOffset, groundColor, intensity );
+					c1 = faceColor;
+					c2 = faceColor;
+					c3 = faceColor;
+					c4 = faceColor;
 
 
 				}
 				}
 
 
-				hemiLength += 1;
-
-			}
-
-		}
-
-		// null eventual remains from removed lights
-		// (this is to avoid if in shader)
-
-		for ( l = dirLength * 3, ll = Math.max( dirColors.length, dirCount * 3 ); l < ll; l ++ ) dirColors[ l ] = 0.0;
-		for ( l = pointLength * 3, ll = Math.max( pointColors.length, pointCount * 3 ); l < ll; l ++ ) pointColors[ l ] = 0.0;
-		for ( l = spotLength * 3, ll = Math.max( spotColors.length, spotCount * 3 ); l < ll; l ++ ) spotColors[ l ] = 0.0;
-		for ( l = hemiLength * 3, ll = Math.max( hemiSkyColors.length, hemiCount * 3 ); l < ll; l ++ ) hemiSkyColors[ l ] = 0.0;
-		for ( l = hemiLength * 3, ll = Math.max( hemiGroundColors.length, hemiCount * 3 ); l < ll; l ++ ) hemiGroundColors[ l ] = 0.0;
-
-		zlights.directional.length = dirLength;
-		zlights.point.length = pointLength;
-		zlights.spot.length = spotLength;
-		zlights.hemi.length = hemiLength;
+				colorArray[ offset_color ]     = c1.r;
+				colorArray[ offset_color + 1 ] = c1.g;
+				colorArray[ offset_color + 2 ] = c1.b;
 
 
-		zlights.ambient[ 0 ] = r;
-		zlights.ambient[ 1 ] = g;
-		zlights.ambient[ 2 ] = b;
+				colorArray[ offset_color + 3 ] = c2.r;
+				colorArray[ offset_color + 4 ] = c2.g;
+				colorArray[ offset_color + 5 ] = c2.b;
 
 
-	};
+				colorArray[ offset_color + 6 ] = c3.r;
+				colorArray[ offset_color + 7 ] = c3.g;
+				colorArray[ offset_color + 8 ] = c3.b;
 
 
-	// GL state setting
+				colorArray[ offset_color + 9 ]  = c4.r;
+				colorArray[ offset_color + 10 ] = c4.g;
+				colorArray[ offset_color + 11 ] = c4.b;
 
 
-	this.setFaceCulling = function ( cullFace, frontFaceDirection ) {
+				offset_color += 12;
 
 
-		if ( cullFace === THREE.CullFaceNone ) {
+			}
 
 
-			_gl.disable( _gl.CULL_FACE );
+			if ( offset_color > 0 ) {
 
 
-		} else {
+				renderer.setDynamicArrayBuffer( geometryGroup.__webglColorBuffer, colorArray);
 
 
-			if ( frontFaceDirection === THREE.FrontFaceDirectionCW ) {
+			}
 
 
-				_gl.frontFace( _gl.CW );
+		}
 
 
-			} else {
+		if ( dirtyTangents && geometry.hasTangents ) {
 
 
-				_gl.frontFace( _gl.CCW );
+			for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
 
 
-			}
+				face = obj_faces[ chunk_faces3[ f ]	];
 
 
-			if ( cullFace === THREE.CullFaceBack ) {
+				vertexTangents = face.vertexTangents;
 
 
-				_gl.cullFace( _gl.BACK );
+				t1 = vertexTangents[ 0 ];
+				t2 = vertexTangents[ 1 ];
+				t3 = vertexTangents[ 2 ];
 
 
-			} else if ( cullFace === THREE.CullFaceFront ) {
+				tangentArray[ offset_tangent ]     = t1.x;
+				tangentArray[ offset_tangent + 1 ] = t1.y;
+				tangentArray[ offset_tangent + 2 ] = t1.z;
+				tangentArray[ offset_tangent + 3 ] = t1.w;
 
 
-				_gl.cullFace( _gl.FRONT );
+				tangentArray[ offset_tangent + 4 ] = t2.x;
+				tangentArray[ offset_tangent + 5 ] = t2.y;
+				tangentArray[ offset_tangent + 6 ] = t2.z;
+				tangentArray[ offset_tangent + 7 ] = t2.w;
 
 
-			} else {
+				tangentArray[ offset_tangent + 8 ]  = t3.x;
+				tangentArray[ offset_tangent + 9 ]  = t3.y;
+				tangentArray[ offset_tangent + 10 ] = t3.z;
+				tangentArray[ offset_tangent + 11 ] = t3.w;
 
 
-				_gl.cullFace( _gl.FRONT_AND_BACK );
+				offset_tangent += 12;
 
 
 			}
 			}
 
 
-			_gl.enable( _gl.CULL_FACE );
-
-		}
+			for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
 
 
-	};
+				face = obj_faces[ chunk_faces4[ f ] ];
 
 
-	this.setMaterialFaces = function ( material ) {
+				vertexTangents = face.vertexTangents;
 
 
-		var doubleSided = material.side === THREE.DoubleSide;
-		var flipSided = material.side === THREE.BackSide;
+				t1 = vertexTangents[ 0 ];
+				t2 = vertexTangents[ 1 ];
+				t3 = vertexTangents[ 2 ];
+				t4 = vertexTangents[ 3 ];
 
 
-		if ( _oldDoubleSided !== doubleSided ) {
+				tangentArray[ offset_tangent ]     = t1.x;
+				tangentArray[ offset_tangent + 1 ] = t1.y;
+				tangentArray[ offset_tangent + 2 ] = t1.z;
+				tangentArray[ offset_tangent + 3 ] = t1.w;
 
 
-			if ( doubleSided ) {
+				tangentArray[ offset_tangent + 4 ] = t2.x;
+				tangentArray[ offset_tangent + 5 ] = t2.y;
+				tangentArray[ offset_tangent + 6 ] = t2.z;
+				tangentArray[ offset_tangent + 7 ] = t2.w;
 
 
-				_gl.disable( _gl.CULL_FACE );
+				tangentArray[ offset_tangent + 8 ]  = t3.x;
+				tangentArray[ offset_tangent + 9 ]  = t3.y;
+				tangentArray[ offset_tangent + 10 ] = t3.z;
+				tangentArray[ offset_tangent + 11 ] = t3.w;
 
 
-			} else {
+				tangentArray[ offset_tangent + 12 ] = t4.x;
+				tangentArray[ offset_tangent + 13 ] = t4.y;
+				tangentArray[ offset_tangent + 14 ] = t4.z;
+				tangentArray[ offset_tangent + 15 ] = t4.w;
 
 
-				_gl.enable( _gl.CULL_FACE );
+				offset_tangent += 16;
 
 
 			}
 			}
 
 
-			_oldDoubleSided = doubleSided;
+			renderer.setDynamicArrayBuffer( geometryGroup.__webglTangentBuffer, tangentArray);
 
 
 		}
 		}
 
 
-		if ( _oldFlipSided !== flipSided ) {
-
-			if ( flipSided ) {
-
-				_gl.frontFace( _gl.CW );
-
-			} else {
-
-				_gl.frontFace( _gl.CCW );
+		if ( dirtyNormals && normalType ) {
 
 
-			}
+			for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
 
 
-			_oldFlipSided = flipSided;
+				face = obj_faces[ chunk_faces3[ f ]	];
 
 
-		}
+				vertexNormals = face.vertexNormals;
+				faceNormal = face.normal;
 
 
-	};
+				if ( vertexNormals.length === 3 && needsSmoothNormals ) {
 
 
-	this.setDepthTest = function ( depthTest ) {
+					for ( i = 0; i < 3; i ++ ) {
 
 
-		if ( _oldDepthTest !== depthTest ) {
+						vn = vertexNormals[ i ];
 
 
-			if ( depthTest ) {
+						normalArray[ offset_normal ]     = vn.x;
+						normalArray[ offset_normal + 1 ] = vn.y;
+						normalArray[ offset_normal + 2 ] = vn.z;
 
 
-				_gl.enable( _gl.DEPTH_TEST );
+						offset_normal += 3;
 
 
-			} else {
+					}
 
 
-				_gl.disable( _gl.DEPTH_TEST );
+				} else {
 
 
-			}
+					for ( i = 0; i < 3; i ++ ) {
 
 
-			_oldDepthTest = depthTest;
+						normalArray[ offset_normal ]     = faceNormal.x;
+						normalArray[ offset_normal + 1 ] = faceNormal.y;
+						normalArray[ offset_normal + 2 ] = faceNormal.z;
 
 
-		}
+						offset_normal += 3;
 
 
-	};
+					}
 
 
-	this.setDepthWrite = function ( depthWrite ) {
+				}
 
 
-		if ( _oldDepthWrite !== depthWrite ) {
+			}
 
 
-			_gl.depthMask( depthWrite );
-			_oldDepthWrite = depthWrite;
+			for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
 
 
-		}
+				face = obj_faces[ chunk_faces4[ f ] ];
 
 
-	};
+				vertexNormals = face.vertexNormals;
+				faceNormal = face.normal;
 
 
-	function setLineWidth ( width ) {
+				if ( vertexNormals.length === 4 && needsSmoothNormals ) {
 
 
-		if ( width !== _oldLineWidth ) {
+					for ( i = 0; i < 4; i ++ ) {
 
 
-			_gl.lineWidth( width );
+						vn = vertexNormals[ i ];
 
 
-			_oldLineWidth = width;
+						normalArray[ offset_normal ]     = vn.x;
+						normalArray[ offset_normal + 1 ] = vn.y;
+						normalArray[ offset_normal + 2 ] = vn.z;
 
 
-		}
+						offset_normal += 3;
 
 
-	};
+					}
 
 
-	function setPolygonOffset ( polygonoffset, factor, units ) {
+				} else {
 
 
-		if ( _oldPolygonOffset !== polygonoffset ) {
+					for ( i = 0; i < 4; i ++ ) {
 
 
-			if ( polygonoffset ) {
+						normalArray[ offset_normal ]     = faceNormal.x;
+						normalArray[ offset_normal + 1 ] = faceNormal.y;
+						normalArray[ offset_normal + 2 ] = faceNormal.z;
 
 
-				_gl.enable( _gl.POLYGON_OFFSET_FILL );
+						offset_normal += 3;
 
 
-			} else {
+					}
 
 
-				_gl.disable( _gl.POLYGON_OFFSET_FILL );
+				}
 
 
 			}
 			}
 
 
-			_oldPolygonOffset = polygonoffset;
+			renderer.setDynamicArrayBuffer( geometryGroup.__webglNormalBuffer, normalArray);
 
 
 		}
 		}
 
 
-		if ( polygonoffset && ( _oldPolygonOffsetFactor !== factor || _oldPolygonOffsetUnits !== units ) ) {
+		if ( dirtyUvs && obj_uvs && uvType ) {
 
 
-			_gl.polygonOffset( factor, units );
+			for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
 
 
-			_oldPolygonOffsetFactor = factor;
-			_oldPolygonOffsetUnits = units;
+				fi = chunk_faces3[ f ];
 
 
-		}
+				uv = obj_uvs[ fi ];
 
 
-	};
+				if ( uv === undefined ) continue;
 
 
-	this.setBlending = function ( blending, blendEquation, blendSrc, blendDst ) {
+				for ( i = 0; i < 3; i ++ ) {
 
 
-		if ( blending !== _oldBlending ) {
+					uvi = uv[ i ];
 
 
-			if ( blending === THREE.NoBlending ) {
+					uvArray[ offset_uv ]     = uvi.x;
+					uvArray[ offset_uv + 1 ] = uvi.y;
 
 
-				_gl.disable( _gl.BLEND );
+					offset_uv += 2;
 
 
-			} else if ( blending === THREE.AdditiveBlending ) {
+				}
 
 
-				_gl.enable( _gl.BLEND );
-				_gl.blendEquation( _gl.FUNC_ADD );
-				_gl.blendFunc( _gl.SRC_ALPHA, _gl.ONE );
+			}
 
 
-			} else if ( blending === THREE.SubtractiveBlending ) {
+			for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
 
 
-				// TODO: Find blendFuncSeparate() combination
-				_gl.enable( _gl.BLEND );
-				_gl.blendEquation( _gl.FUNC_ADD );
-				_gl.blendFunc( _gl.ZERO, _gl.ONE_MINUS_SRC_COLOR );
+				fi = chunk_faces4[ f ];
 
 
-			} else if ( blending === THREE.MultiplyBlending ) {
+				uv = obj_uvs[ fi ];
 
 
-				// TODO: Find blendFuncSeparate() combination
-				_gl.enable( _gl.BLEND );
-				_gl.blendEquation( _gl.FUNC_ADD );
-				_gl.blendFunc( _gl.ZERO, _gl.SRC_COLOR );
+				if ( uv === undefined ) continue;
 
 
-			} else if ( blending === THREE.CustomBlending ) {
+				for ( i = 0; i < 4; i ++ ) {
+
+					uvi = uv[ i ];
 
 
-				_gl.enable( _gl.BLEND );
+					uvArray[ offset_uv ]     = uvi.x;
+					uvArray[ offset_uv + 1 ] = uvi.y;
 
 
-			} else {
+					offset_uv += 2;
 
 
-				_gl.enable( _gl.BLEND );
-				_gl.blendEquationSeparate( _gl.FUNC_ADD, _gl.FUNC_ADD );
-				_gl.blendFuncSeparate( _gl.SRC_ALPHA, _gl.ONE_MINUS_SRC_ALPHA, _gl.ONE, _gl.ONE_MINUS_SRC_ALPHA );
+				}
 
 
 			}
 			}
 
 
-			_oldBlending = blending;
+			if ( offset_uv > 0 ) {
+
+				renderer.setDynamicArrayBuffer( geometryGroup.__webglUVBuffer, uvArray);
+
+			}
 
 
 		}
 		}
 
 
-		if ( blending === THREE.CustomBlending ) {
+		if ( dirtyUvs && obj_uvs2 && uvType ) {
 
 
-			if ( blendEquation !== _oldBlendEquation ) {
+			for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
 
 
-				_gl.blendEquation( paramThreeToGL( blendEquation ) );
+				fi = chunk_faces3[ f ];
 
 
-				_oldBlendEquation = blendEquation;
+				uv2 = obj_uvs2[ fi ];
 
 
-			}
+				if ( uv2 === undefined ) continue;
 
 
-			if ( blendSrc !== _oldBlendSrc || blendDst !== _oldBlendDst ) {
+				for ( i = 0; i < 3; i ++ ) {
 
 
-				_gl.blendFunc( paramThreeToGL( blendSrc ), paramThreeToGL( blendDst ) );
+					uv2i = uv2[ i ];
 
 
-				_oldBlendSrc = blendSrc;
-				_oldBlendDst = blendDst;
+					uv2Array[ offset_uv2 ]     = uv2i.x;
+					uv2Array[ offset_uv2 + 1 ] = uv2i.y;
 
 
-			}
+					offset_uv2 += 2;
 
 
-		} else {
+				}
 
 
-			_oldBlendEquation = null;
-			_oldBlendSrc = null;
-			_oldBlendDst = null;
+			}
 
 
-		}
+			for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
 
 
-	};
+				fi = chunk_faces4[ f ];
 
 
-	// Defines
+				uv2 = obj_uvs2[ fi ];
 
 
-	function generateDefines ( defines ) {
+				if ( uv2 === undefined ) continue;
 
 
-		var value, chunk, chunks = [];
+				for ( i = 0; i < 4; i ++ ) {
 
 
-		for ( var d in defines ) {
+					uv2i = uv2[ i ];
 
 
-			value = defines[ d ];
-			if ( value === false ) continue;
+					uv2Array[ offset_uv2 ]     = uv2i.x;
+					uv2Array[ offset_uv2 + 1 ] = uv2i.y;
 
 
-			chunk = "#define " + d + " " + value;
-			chunks.push( chunk );
+					offset_uv2 += 2;
 
 
-		}
+				}
 
 
-		return chunks.join( "\n" );
+			}
 
 
-	};
+			if ( offset_uv2 > 0 ) {
 
 
-	// Shaders
+				renderer.setDynamicArrayBuffer( geometryGroup.__webglUV2Buffer, uv2Array);
 
 
-	function buildProgram ( shaderID, fragmentShader, vertexShader, uniforms, attributes, defines, parameters ) {
+			}
 
 
-		var p, pl, d, program, code;
-		var chunks = [];
+		}
 
 
-		// Generate code
+		if ( dirtyElements ) {
 
 
-		if ( shaderID ) {
+			for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
 
 
-			chunks.push( shaderID );
+				faceArray[ offset_face ] 	 = vertexIndex;
+				faceArray[ offset_face + 1 ] = vertexIndex + 1;
+				faceArray[ offset_face + 2 ] = vertexIndex + 2;
 
 
-		} else {
+				offset_face += 3;
 
 
-			chunks.push( fragmentShader );
-			chunks.push( vertexShader );
+				lineArray[ offset_line ]     = vertexIndex;
+				lineArray[ offset_line + 1 ] = vertexIndex + 1;
 
 
-		}
+				lineArray[ offset_line + 2 ] = vertexIndex;
+				lineArray[ offset_line + 3 ] = vertexIndex + 2;
 
 
-		for ( d in defines ) {
+				lineArray[ offset_line + 4 ] = vertexIndex + 1;
+				lineArray[ offset_line + 5 ] = vertexIndex + 2;
 
 
-			chunks.push( d );
-			chunks.push( defines[ d ] );
+				offset_line += 6;
 
 
-		}
+				vertexIndex += 3;
 
 
-		for ( p in parameters ) {
+			}
 
 
-			chunks.push( p );
-			chunks.push( parameters[ p ] );
+			for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
 
 
-		}
+				faceArray[ offset_face ]     = vertexIndex;
+				faceArray[ offset_face + 1 ] = vertexIndex + 1;
+				faceArray[ offset_face + 2 ] = vertexIndex + 3;
 
 
-		code = chunks.join();
+				faceArray[ offset_face + 3 ] = vertexIndex + 1;
+				faceArray[ offset_face + 4 ] = vertexIndex + 2;
+				faceArray[ offset_face + 5 ] = vertexIndex + 3;
 
 
-		// Check if code has been already compiled
+				offset_face += 6;
 
 
-		for ( p = 0, pl = _programs.length; p < pl; p ++ ) {
+				lineArray[ offset_line ]     = vertexIndex;
+				lineArray[ offset_line + 1 ] = vertexIndex + 1;
 
 
-			var programInfo = _programs[ p ];
+				lineArray[ offset_line + 2 ] = vertexIndex;
+				lineArray[ offset_line + 3 ] = vertexIndex + 3;
 
 
-			if ( programInfo.code === code ) {
+				lineArray[ offset_line + 4 ] = vertexIndex + 1;
+				lineArray[ offset_line + 5 ] = vertexIndex + 2;
 
 
-				//console.log( "Code already compiled." /*: \n\n" + code*/ );
+				lineArray[ offset_line + 6 ] = vertexIndex + 2;
+				lineArray[ offset_line + 7 ] = vertexIndex + 3;
 
 
-				programInfo.usedTimes ++;
+				offset_line += 8;
 
 
-				return programInfo.program;
+				vertexIndex += 4;
 
 
 			}
 			}
 
 
+			renderer.setDynamicIndexBuffer( geometryGroup.__webglFaceBuffer, faceArray);
+			renderer.setDynamicIndexBuffer( geometryGroup.__webglLineBuffer, lineArray);
+
 		}
 		}
 
 
-		var shadowMapTypeDefine = "SHADOWMAP_TYPE_BASIC";
+		if ( customAttributes ) {
 
 
-		if ( parameters.shadowMapType === THREE.PCFShadowMap ) {
+			for ( i = 0, il = customAttributes.length; i < il; i ++ ) {
 
 
-			shadowMapTypeDefine = "SHADOWMAP_TYPE_PCF";
+				customAttribute = customAttributes[ i ];
 
 
-		} else if ( parameters.shadowMapType === THREE.PCFSoftShadowMap ) {
+				if ( ! customAttribute.__original.needsUpdate ) continue;
 
 
-			shadowMapTypeDefine = "SHADOWMAP_TYPE_PCF_SOFT";
+				offset_custom = 0;
+				offset_customSrc = 0;
 
 
-		}
+				if ( customAttribute.size === 1 ) {
 
 
-		//console.log( "building new program " );
+					if ( customAttribute.boundTo === undefined || customAttribute.boundTo === "vertices" ) {
 
 
-		//
+						for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
 
 
-		var customDefines = generateDefines( defines );
+							face = obj_faces[ chunk_faces3[ f ]	];
 
 
-		//
+							customAttribute.array[ offset_custom ] 	   = customAttribute.value[ face.a ];
+							customAttribute.array[ offset_custom + 1 ] = customAttribute.value[ face.b ];
+							customAttribute.array[ offset_custom + 2 ] = customAttribute.value[ face.c ];
+
+							offset_custom += 3;
+
+						}
+
+						for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
 
 
-		program = _gl.createProgram();
+							face = obj_faces[ chunk_faces4[ f ] ];
 
 
-		var prefix_vertex = [
+							customAttribute.array[ offset_custom ] 	   = customAttribute.value[ face.a ];
+							customAttribute.array[ offset_custom + 1 ] = customAttribute.value[ face.b ];
+							customAttribute.array[ offset_custom + 2 ] = customAttribute.value[ face.c ];
+							customAttribute.array[ offset_custom + 3 ] = customAttribute.value[ face.d ];
 
 
-			"precision " + _precision + " float;",
+							offset_custom += 4;
 
 
-			customDefines,
+						}
 
 
-			_supportsVertexTextures ? "#define VERTEX_TEXTURES" : "",
+					} else if ( customAttribute.boundTo === "faces" ) {
 
 
-			_this.gammaInput ? "#define GAMMA_INPUT" : "",
-			_this.gammaOutput ? "#define GAMMA_OUTPUT" : "",
-			_this.physicallyBasedShading ? "#define PHYSICALLY_BASED_SHADING" : "",
+						for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
 
 
-			"#define MAX_DIR_LIGHTS " + parameters.maxDirLights,
-			"#define MAX_POINT_LIGHTS " + parameters.maxPointLights,
-			"#define MAX_SPOT_LIGHTS " + parameters.maxSpotLights,
-			"#define MAX_HEMI_LIGHTS " + parameters.maxHemiLights,
+							value = customAttribute.value[ chunk_faces3[ f ] ];
 
 
-			"#define MAX_SHADOWS " + parameters.maxShadows,
+							customAttribute.array[ offset_custom ] 	   = value;
+							customAttribute.array[ offset_custom + 1 ] = value;
+							customAttribute.array[ offset_custom + 2 ] = value;
 
 
-			"#define MAX_BONES " + parameters.maxBones,
+							offset_custom += 3;
 
 
-			parameters.map ? "#define USE_MAP" : "",
-			parameters.envMap ? "#define USE_ENVMAP" : "",
-			parameters.lightMap ? "#define USE_LIGHTMAP" : "",
-			parameters.bumpMap ? "#define USE_BUMPMAP" : "",
-			parameters.normalMap ? "#define USE_NORMALMAP" : "",
-			parameters.specularMap ? "#define USE_SPECULARMAP" : "",
-			parameters.vertexColors ? "#define USE_COLOR" : "",
+						}
 
 
-			parameters.skinning ? "#define USE_SKINNING" : "",
-			parameters.useVertexTexture ? "#define BONE_TEXTURE" : "",
-			parameters.boneTextureWidth ? "#define N_BONE_PIXEL_X " + parameters.boneTextureWidth.toFixed( 1 ) : "",
-			parameters.boneTextureHeight ? "#define N_BONE_PIXEL_Y " + parameters.boneTextureHeight.toFixed( 1 ) : "",
+						for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
 
 
-			parameters.morphTargets ? "#define USE_MORPHTARGETS" : "",
-			parameters.morphNormals ? "#define USE_MORPHNORMALS" : "",
-			parameters.perPixel ? "#define PHONG_PER_PIXEL" : "",
-			parameters.wrapAround ? "#define WRAP_AROUND" : "",
-			parameters.doubleSided ? "#define DOUBLE_SIDED" : "",
-			parameters.flipSided ? "#define FLIP_SIDED" : "",
+							value = customAttribute.value[ chunk_faces4[ f ] ];
 
 
-			parameters.shadowMapEnabled ? "#define USE_SHADOWMAP" : "",
-			parameters.shadowMapEnabled ? "#define " + shadowMapTypeDefine : "",
-			parameters.shadowMapDebug ? "#define SHADOWMAP_DEBUG" : "",
-			parameters.shadowMapCascade ? "#define SHADOWMAP_CASCADE" : "",
+							customAttribute.array[ offset_custom ] 	   = value;
+							customAttribute.array[ offset_custom + 1 ] = value;
+							customAttribute.array[ offset_custom + 2 ] = value;
+							customAttribute.array[ offset_custom + 3 ] = value;
 
 
-			parameters.sizeAttenuation ? "#define USE_SIZEATTENUATION" : "",
+							offset_custom += 4;
 
 
-			"uniform mat4 modelMatrix;",
-			"uniform mat4 modelViewMatrix;",
-			"uniform mat4 projectionMatrix;",
-			"uniform mat4 viewMatrix;",
-			"uniform mat3 normalMatrix;",
-			"uniform vec3 cameraPosition;",
+						}
 
 
-			"attribute vec3 position;",
-			"attribute vec3 normal;",
-			"attribute vec2 uv;",
-			"attribute vec2 uv2;",
+					}
 
 
-			"#ifdef USE_COLOR",
+				} else if ( customAttribute.size === 2 ) {
 
 
-				"attribute vec3 color;",
+					if ( customAttribute.boundTo === undefined || customAttribute.boundTo === "vertices" ) {
 
 
-			"#endif",
+						for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
 
 
-			"#ifdef USE_MORPHTARGETS",
+							face = obj_faces[ chunk_faces3[ f ]	];
 
 
-				"attribute vec3 morphTarget0;",
-				"attribute vec3 morphTarget1;",
-				"attribute vec3 morphTarget2;",
-				"attribute vec3 morphTarget3;",
+							v1 = customAttribute.value[ face.a ];
+							v2 = customAttribute.value[ face.b ];
+							v3 = customAttribute.value[ face.c ];
 
 
-				"#ifdef USE_MORPHNORMALS",
+							customAttribute.array[ offset_custom ] 	   = v1.x;
+							customAttribute.array[ offset_custom + 1 ] = v1.y;
 
 
-					"attribute vec3 morphNormal0;",
-					"attribute vec3 morphNormal1;",
-					"attribute vec3 morphNormal2;",
-					"attribute vec3 morphNormal3;",
+							customAttribute.array[ offset_custom + 2 ] = v2.x;
+							customAttribute.array[ offset_custom + 3 ] = v2.y;
 
 
-				"#else",
+							customAttribute.array[ offset_custom + 4 ] = v3.x;
+							customAttribute.array[ offset_custom + 5 ] = v3.y;
 
 
-					"attribute vec3 morphTarget4;",
-					"attribute vec3 morphTarget5;",
-					"attribute vec3 morphTarget6;",
-					"attribute vec3 morphTarget7;",
+							offset_custom += 6;
 
 
-				"#endif",
+						}
 
 
-			"#endif",
+						for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
 
 
-			"#ifdef USE_SKINNING",
+							face = obj_faces[ chunk_faces4[ f ] ];
 
 
-				"attribute vec4 skinIndex;",
-				"attribute vec4 skinWeight;",
+							v1 = customAttribute.value[ face.a ];
+							v2 = customAttribute.value[ face.b ];
+							v3 = customAttribute.value[ face.c ];
+							v4 = customAttribute.value[ face.d ];
 
 
-			"#endif",
+							customAttribute.array[ offset_custom ] 	   = v1.x;
+							customAttribute.array[ offset_custom + 1 ] = v1.y;
 
 
-			""
+							customAttribute.array[ offset_custom + 2 ] = v2.x;
+							customAttribute.array[ offset_custom + 3 ] = v2.y;
 
 
-		].join("\n");
+							customAttribute.array[ offset_custom + 4 ] = v3.x;
+							customAttribute.array[ offset_custom + 5 ] = v3.y;
 
 
-		var prefix_fragment = [
+							customAttribute.array[ offset_custom + 6 ] = v4.x;
+							customAttribute.array[ offset_custom + 7 ] = v4.y;
 
 
-			"precision " + _precision + " float;",
+							offset_custom += 8;
 
 
-			( parameters.bumpMap || parameters.normalMap ) ? "#extension GL_OES_standard_derivatives : enable" : "",
+						}
 
 
-			customDefines,
+					} else if ( customAttribute.boundTo === "faces" ) {
 
 
-			"#define MAX_DIR_LIGHTS " + parameters.maxDirLights,
-			"#define MAX_POINT_LIGHTS " + parameters.maxPointLights,
-			"#define MAX_SPOT_LIGHTS " + parameters.maxSpotLights,
-			"#define MAX_HEMI_LIGHTS " + parameters.maxHemiLights,
+						for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
 
 
-			"#define MAX_SHADOWS " + parameters.maxShadows,
+							value = customAttribute.value[ chunk_faces3[ f ] ];
 
 
-			parameters.alphaTest ? "#define ALPHATEST " + parameters.alphaTest: "",
+							v1 = value;
+							v2 = value;
+							v3 = value;
 
 
-			_this.gammaInput ? "#define GAMMA_INPUT" : "",
-			_this.gammaOutput ? "#define GAMMA_OUTPUT" : "",
-			_this.physicallyBasedShading ? "#define PHYSICALLY_BASED_SHADING" : "",
+							customAttribute.array[ offset_custom ] 	   = v1.x;
+							customAttribute.array[ offset_custom + 1 ] = v1.y;
 
 
-			( parameters.useFog && parameters.fog ) ? "#define USE_FOG" : "",
-			( parameters.useFog && parameters.fogExp ) ? "#define FOG_EXP2" : "",
+							customAttribute.array[ offset_custom + 2 ] = v2.x;
+							customAttribute.array[ offset_custom + 3 ] = v2.y;
 
 
-			parameters.map ? "#define USE_MAP" : "",
-			parameters.envMap ? "#define USE_ENVMAP" : "",
-			parameters.lightMap ? "#define USE_LIGHTMAP" : "",
-			parameters.bumpMap ? "#define USE_BUMPMAP" : "",
-			parameters.normalMap ? "#define USE_NORMALMAP" : "",
-			parameters.specularMap ? "#define USE_SPECULARMAP" : "",
-			parameters.vertexColors ? "#define USE_COLOR" : "",
+							customAttribute.array[ offset_custom + 4 ] = v3.x;
+							customAttribute.array[ offset_custom + 5 ] = v3.y;
 
 
-			parameters.metal ? "#define METAL" : "",
-			parameters.perPixel ? "#define PHONG_PER_PIXEL" : "",
-			parameters.wrapAround ? "#define WRAP_AROUND" : "",
-			parameters.doubleSided ? "#define DOUBLE_SIDED" : "",
-			parameters.flipSided ? "#define FLIP_SIDED" : "",
+							offset_custom += 6;
 
 
-			parameters.shadowMapEnabled ? "#define USE_SHADOWMAP" : "",
-			parameters.shadowMapEnabled ? "#define " + shadowMapTypeDefine : "",
-			parameters.shadowMapDebug ? "#define SHADOWMAP_DEBUG" : "",
-			parameters.shadowMapCascade ? "#define SHADOWMAP_CASCADE" : "",
+						}
 
 
-			"uniform mat4 viewMatrix;",
-			"uniform vec3 cameraPosition;",
-			""
+						for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
 
 
-		].join("\n");
+							value = customAttribute.value[ chunk_faces4[ f ] ];
 
 
-		var glFragmentShader = getShader( "fragment", prefix_fragment + fragmentShader );
-		var glVertexShader = getShader( "vertex", prefix_vertex + vertexShader );
+							v1 = value;
+							v2 = value;
+							v3 = value;
+							v4 = value;
 
 
-		_gl.attachShader( program, glVertexShader );
-		_gl.attachShader( program, glFragmentShader );
+							customAttribute.array[ offset_custom ] 	   = v1.x;
+							customAttribute.array[ offset_custom + 1 ] = v1.y;
 
 
-		_gl.linkProgram( program );
+							customAttribute.array[ offset_custom + 2 ] = v2.x;
+							customAttribute.array[ offset_custom + 3 ] = v2.y;
 
 
-		if ( !_gl.getProgramParameter( program, _gl.LINK_STATUS ) ) {
+							customAttribute.array[ offset_custom + 4 ] = v3.x;
+							customAttribute.array[ offset_custom + 5 ] = v3.y;
 
 
-			console.error( "Could not initialise shader\n" + "VALIDATE_STATUS: " + _gl.getProgramParameter( program, _gl.VALIDATE_STATUS ) + ", gl error [" + _gl.getError() + "]" );
+							customAttribute.array[ offset_custom + 6 ] = v4.x;
+							customAttribute.array[ offset_custom + 7 ] = v4.y;
 
 
-		}
+							offset_custom += 8;
 
 
-		// clean up
+						}
 
 
-		_gl.deleteShader( glFragmentShader );
-		_gl.deleteShader( glVertexShader );
+					}
 
 
-		//console.log( prefix_fragment + fragmentShader );
-		//console.log( prefix_vertex + vertexShader );
+				} else if ( customAttribute.size === 3 ) {
 
 
-		program.uniforms = {};
-		program.attributes = {};
+					var pp;
 
 
-		var identifiers, u, a, i;
+					if ( customAttribute.type === "c" ) {
 
 
-		// cache uniform locations
+						pp = [ "r", "g", "b" ];
 
 
-		identifiers = [
+					} else {
 
 
-			'viewMatrix', 'modelViewMatrix', 'projectionMatrix', 'normalMatrix', 'modelMatrix', 'cameraPosition',
-			'morphTargetInfluences'
+						pp = [ "x", "y", "z" ];
 
 
-		];
+					}
 
 
-		if ( parameters.useVertexTexture ) {
+					if ( customAttribute.boundTo === undefined || customAttribute.boundTo === "vertices" ) {
 
 
-			identifiers.push( 'boneTexture' );
+						for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
 
 
-		} else {
+							face = obj_faces[ chunk_faces3[ f ]	];
 
 
-			identifiers.push( 'boneGlobalMatrices' );
+							v1 = customAttribute.value[ face.a ];
+							v2 = customAttribute.value[ face.b ];
+							v3 = customAttribute.value[ face.c ];
 
 
-		}
+							customAttribute.array[ offset_custom ] 	   = v1[ pp[ 0 ] ];
+							customAttribute.array[ offset_custom + 1 ] = v1[ pp[ 1 ] ];
+							customAttribute.array[ offset_custom + 2 ] = v1[ pp[ 2 ] ];
 
 
-		for ( u in uniforms ) {
+							customAttribute.array[ offset_custom + 3 ] = v2[ pp[ 0 ] ];
+							customAttribute.array[ offset_custom + 4 ] = v2[ pp[ 1 ] ];
+							customAttribute.array[ offset_custom + 5 ] = v2[ pp[ 2 ] ];
 
 
-			identifiers.push( u );
+							customAttribute.array[ offset_custom + 6 ] = v3[ pp[ 0 ] ];
+							customAttribute.array[ offset_custom + 7 ] = v3[ pp[ 1 ] ];
+							customAttribute.array[ offset_custom + 8 ] = v3[ pp[ 2 ] ];
 
 
-		}
+							offset_custom += 9;
 
 
-		cacheUniformLocations( program, identifiers );
+						}
 
 
-		// cache attributes locations
+						for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
 
 
-		identifiers = [
+							face = obj_faces[ chunk_faces4[ f ] ];
 
 
-			"position", "normal", "uv", "uv2", "tangent", "color",
-			"skinIndex", "skinWeight", "lineDistance"
+							v1 = customAttribute.value[ face.a ];
+							v2 = customAttribute.value[ face.b ];
+							v3 = customAttribute.value[ face.c ];
+							v4 = customAttribute.value[ face.d ];
 
 
-		];
+							customAttribute.array[ offset_custom  ] 	= v1[ pp[ 0 ] ];
+							customAttribute.array[ offset_custom + 1  ] = v1[ pp[ 1 ] ];
+							customAttribute.array[ offset_custom + 2  ] = v1[ pp[ 2 ] ];
 
 
-		for ( i = 0; i < parameters.maxMorphTargets; i ++ ) {
+							customAttribute.array[ offset_custom + 3  ] = v2[ pp[ 0 ] ];
+							customAttribute.array[ offset_custom + 4  ] = v2[ pp[ 1 ] ];
+							customAttribute.array[ offset_custom + 5  ] = v2[ pp[ 2 ] ];
 
 
-			identifiers.push( "morphTarget" + i );
+							customAttribute.array[ offset_custom + 6  ] = v3[ pp[ 0 ] ];
+							customAttribute.array[ offset_custom + 7  ] = v3[ pp[ 1 ] ];
+							customAttribute.array[ offset_custom + 8  ] = v3[ pp[ 2 ] ];
 
 
-		}
+							customAttribute.array[ offset_custom + 9  ] = v4[ pp[ 0 ] ];
+							customAttribute.array[ offset_custom + 10 ] = v4[ pp[ 1 ] ];
+							customAttribute.array[ offset_custom + 11 ] = v4[ pp[ 2 ] ];
 
 
-		for ( i = 0; i < parameters.maxMorphNormals; i ++ ) {
+							offset_custom += 12;
 
 
-			identifiers.push( "morphNormal" + i );
+						}
 
 
-		}
+					} else if ( customAttribute.boundTo === "faces" ) {
 
 
-		for ( a in attributes ) {
+						for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
 
 
-			identifiers.push( a );
+							value = customAttribute.value[ chunk_faces3[ f ] ];
 
 
-		}
+							v1 = value;
+							v2 = value;
+							v3 = value;
 
 
-		cacheAttributeLocations( program, identifiers );
+							customAttribute.array[ offset_custom ] 	   = v1[ pp[ 0 ] ];
+							customAttribute.array[ offset_custom + 1 ] = v1[ pp[ 1 ] ];
+							customAttribute.array[ offset_custom + 2 ] = v1[ pp[ 2 ] ];
 
 
-		program.id = _programs_counter ++;
+							customAttribute.array[ offset_custom + 3 ] = v2[ pp[ 0 ] ];
+							customAttribute.array[ offset_custom + 4 ] = v2[ pp[ 1 ] ];
+							customAttribute.array[ offset_custom + 5 ] = v2[ pp[ 2 ] ];
 
 
-		_programs.push( { program: program, code: code, usedTimes: 1 } );
+							customAttribute.array[ offset_custom + 6 ] = v3[ pp[ 0 ] ];
+							customAttribute.array[ offset_custom + 7 ] = v3[ pp[ 1 ] ];
+							customAttribute.array[ offset_custom + 8 ] = v3[ pp[ 2 ] ];
 
 
-		_this.info.memory.programs = _programs.length;
+							offset_custom += 9;
 
 
-		return program;
+						}
 
 
-	};
+						for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
 
 
-	// Shader parameters cache
+							value = customAttribute.value[ chunk_faces4[ f ] ];
 
 
-	function cacheUniformLocations ( program, identifiers ) {
+							v1 = value;
+							v2 = value;
+							v3 = value;
+							v4 = value;
 
 
-		var i, l, id;
+							customAttribute.array[ offset_custom  ] 	= v1[ pp[ 0 ] ];
+							customAttribute.array[ offset_custom + 1  ] = v1[ pp[ 1 ] ];
+							customAttribute.array[ offset_custom + 2  ] = v1[ pp[ 2 ] ];
 
 
-		for( i = 0, l = identifiers.length; i < l; i ++ ) {
+							customAttribute.array[ offset_custom + 3  ] = v2[ pp[ 0 ] ];
+							customAttribute.array[ offset_custom + 4  ] = v2[ pp[ 1 ] ];
+							customAttribute.array[ offset_custom + 5  ] = v2[ pp[ 2 ] ];
 
 
-			id = identifiers[ i ];
-			program.uniforms[ id ] = _gl.getUniformLocation( program, id );
+							customAttribute.array[ offset_custom + 6  ] = v3[ pp[ 0 ] ];
+							customAttribute.array[ offset_custom + 7  ] = v3[ pp[ 1 ] ];
+							customAttribute.array[ offset_custom + 8  ] = v3[ pp[ 2 ] ];
 
 
-		}
+							customAttribute.array[ offset_custom + 9  ] = v4[ pp[ 0 ] ];
+							customAttribute.array[ offset_custom + 10 ] = v4[ pp[ 1 ] ];
+							customAttribute.array[ offset_custom + 11 ] = v4[ pp[ 2 ] ];
 
 
-	};
+							offset_custom += 12;
 
 
-	function cacheAttributeLocations ( program, identifiers ) {
+						}
 
 
-		var i, l, id;
+					} else if ( customAttribute.boundTo === "faceVertices" ) {
 
 
-		for( i = 0, l = identifiers.length; i < l; i ++ ) {
+						for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
 
 
-			id = identifiers[ i ];
-			program.attributes[ id ] = _gl.getAttribLocation( program, id );
+							value = customAttribute.value[ chunk_faces3[ f ] ];
 
 
-		}
+							v1 = value[ 0 ];
+							v2 = value[ 1 ];
+							v3 = value[ 2 ];
 
 
-	};
+							customAttribute.array[ offset_custom ] 	   = v1[ pp[ 0 ] ];
+							customAttribute.array[ offset_custom + 1 ] = v1[ pp[ 1 ] ];
+							customAttribute.array[ offset_custom + 2 ] = v1[ pp[ 2 ] ];
 
 
-	function addLineNumbers ( string ) {
+							customAttribute.array[ offset_custom + 3 ] = v2[ pp[ 0 ] ];
+							customAttribute.array[ offset_custom + 4 ] = v2[ pp[ 1 ] ];
+							customAttribute.array[ offset_custom + 5 ] = v2[ pp[ 2 ] ];
 
 
-		var chunks = string.split( "\n" );
+							customAttribute.array[ offset_custom + 6 ] = v3[ pp[ 0 ] ];
+							customAttribute.array[ offset_custom + 7 ] = v3[ pp[ 1 ] ];
+							customAttribute.array[ offset_custom + 8 ] = v3[ pp[ 2 ] ];
 
 
-		for ( var i = 0, il = chunks.length; i < il; i ++ ) {
+							offset_custom += 9;
 
 
-			// Chrome reports shader errors on lines
-			// starting counting from 1
+						}
 
 
-			chunks[ i ] = ( i + 1 ) + ": " + chunks[ i ];
+						for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
 
 
-		}
+							value = customAttribute.value[ chunk_faces4[ f ] ];
 
 
-		return chunks.join( "\n" );
+							v1 = value[ 0 ];
+							v2 = value[ 1 ];
+							v3 = value[ 2 ];
+							v4 = value[ 3 ];
 
 
-	};
+							customAttribute.array[ offset_custom  ] 	= v1[ pp[ 0 ] ];
+							customAttribute.array[ offset_custom + 1  ] = v1[ pp[ 1 ] ];
+							customAttribute.array[ offset_custom + 2  ] = v1[ pp[ 2 ] ];
 
 
-	function getShader ( type, string ) {
+							customAttribute.array[ offset_custom + 3  ] = v2[ pp[ 0 ] ];
+							customAttribute.array[ offset_custom + 4  ] = v2[ pp[ 1 ] ];
+							customAttribute.array[ offset_custom + 5  ] = v2[ pp[ 2 ] ];
 
 
-		var shader;
+							customAttribute.array[ offset_custom + 6  ] = v3[ pp[ 0 ] ];
+							customAttribute.array[ offset_custom + 7  ] = v3[ pp[ 1 ] ];
+							customAttribute.array[ offset_custom + 8  ] = v3[ pp[ 2 ] ];
 
 
-		if ( type === "fragment" ) {
+							customAttribute.array[ offset_custom + 9  ] = v4[ pp[ 0 ] ];
+							customAttribute.array[ offset_custom + 10 ] = v4[ pp[ 1 ] ];
+							customAttribute.array[ offset_custom + 11 ] = v4[ pp[ 2 ] ];
 
 
-			shader = _gl.createShader( _gl.FRAGMENT_SHADER );
+							offset_custom += 12;
 
 
-		} else if ( type === "vertex" ) {
+						}
 
 
-			shader = _gl.createShader( _gl.VERTEX_SHADER );
+					}
 
 
-		}
+				} else if ( customAttribute.size === 4 ) {
 
 
-		_gl.shaderSource( shader, string );
-		_gl.compileShader( shader );
+					if ( customAttribute.boundTo === undefined || customAttribute.boundTo === "vertices" ) {
 
 
-		if ( !_gl.getShaderParameter( shader, _gl.COMPILE_STATUS ) ) {
+						for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
 
 
-			console.error( _gl.getShaderInfoLog( shader ) );
-			console.error( addLineNumbers( string ) );
-			return null;
+							face = obj_faces[ chunk_faces3[ f ]	];
 
 
-		}
+							v1 = customAttribute.value[ face.a ];
+							v2 = customAttribute.value[ face.b ];
+							v3 = customAttribute.value[ face.c ];
 
 
-		return shader;
+							customAttribute.array[ offset_custom  ] 	= v1.x;
+							customAttribute.array[ offset_custom + 1  ] = v1.y;
+							customAttribute.array[ offset_custom + 2  ] = v1.z;
+							customAttribute.array[ offset_custom + 3  ] = v1.w;
 
 
-	};
+							customAttribute.array[ offset_custom + 4  ] = v2.x;
+							customAttribute.array[ offset_custom + 5  ] = v2.y;
+							customAttribute.array[ offset_custom + 6  ] = v2.z;
+							customAttribute.array[ offset_custom + 7  ] = v2.w;
 
 
-	// Textures
+							customAttribute.array[ offset_custom + 8  ] = v3.x;
+							customAttribute.array[ offset_custom + 9  ] = v3.y;
+							customAttribute.array[ offset_custom + 10 ] = v3.z;
+							customAttribute.array[ offset_custom + 11 ] = v3.w;
 
 
+							offset_custom += 12;
 
 
-	function isPowerOfTwo ( value ) {
+						}
 
 
-		return ( value & ( value - 1 ) ) === 0;
+						for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
 
 
-	};
+							face = obj_faces[ chunk_faces4[ f ] ];
 
 
-	function setTextureParameters ( textureType, texture, isImagePowerOfTwo ) {
+							v1 = customAttribute.value[ face.a ];
+							v2 = customAttribute.value[ face.b ];
+							v3 = customAttribute.value[ face.c ];
+							v4 = customAttribute.value[ face.d ];
 
 
-		if ( isImagePowerOfTwo ) {
+							customAttribute.array[ offset_custom  ] 	= v1.x;
+							customAttribute.array[ offset_custom + 1  ] = v1.y;
+							customAttribute.array[ offset_custom + 2  ] = v1.z;
+							customAttribute.array[ offset_custom + 3  ] = v1.w;
 
 
-			_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, paramThreeToGL( texture.wrapS ) );
-			_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, paramThreeToGL( texture.wrapT ) );
+							customAttribute.array[ offset_custom + 4  ] = v2.x;
+							customAttribute.array[ offset_custom + 5  ] = v2.y;
+							customAttribute.array[ offset_custom + 6  ] = v2.z;
+							customAttribute.array[ offset_custom + 7  ] = v2.w;
 
 
-			_gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, paramThreeToGL( texture.magFilter ) );
-			_gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, paramThreeToGL( texture.minFilter ) );
+							customAttribute.array[ offset_custom + 8  ] = v3.x;
+							customAttribute.array[ offset_custom + 9  ] = v3.y;
+							customAttribute.array[ offset_custom + 10 ] = v3.z;
+							customAttribute.array[ offset_custom + 11 ] = v3.w;
 
 
-		} else {
+							customAttribute.array[ offset_custom + 12 ] = v4.x;
+							customAttribute.array[ offset_custom + 13 ] = v4.y;
+							customAttribute.array[ offset_custom + 14 ] = v4.z;
+							customAttribute.array[ offset_custom + 15 ] = v4.w;
 
 
-			_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, _gl.CLAMP_TO_EDGE );
-			_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, _gl.CLAMP_TO_EDGE );
+							offset_custom += 16;
 
 
-			_gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, filterFallback( texture.magFilter ) );
-			_gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, filterFallback( texture.minFilter ) );
+						}
 
 
-		}
+					} else if ( customAttribute.boundTo === "faces" ) {
 
 
-		if ( _glExtensionTextureFilterAnisotropic && texture.type !== THREE.FloatType ) {
+						for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
 
 
-			if ( texture.anisotropy > 1 || texture.__oldAnisotropy ) {
+							value = customAttribute.value[ chunk_faces3[ f ] ];
 
 
-				_gl.texParameterf( textureType, _glExtensionTextureFilterAnisotropic.TEXTURE_MAX_ANISOTROPY_EXT, Math.min( texture.anisotropy, _maxAnisotropy ) );
-				texture.__oldAnisotropy = texture.anisotropy;
+							v1 = value;
+							v2 = value;
+							v3 = value;
 
 
-			}
+							customAttribute.array[ offset_custom  ] 	= v1.x;
+							customAttribute.array[ offset_custom + 1  ] = v1.y;
+							customAttribute.array[ offset_custom + 2  ] = v1.z;
+							customAttribute.array[ offset_custom + 3  ] = v1.w;
 
 
-		}
+							customAttribute.array[ offset_custom + 4  ] = v2.x;
+							customAttribute.array[ offset_custom + 5  ] = v2.y;
+							customAttribute.array[ offset_custom + 6  ] = v2.z;
+							customAttribute.array[ offset_custom + 7  ] = v2.w;
 
 
-	};
+							customAttribute.array[ offset_custom + 8  ] = v3.x;
+							customAttribute.array[ offset_custom + 9  ] = v3.y;
+							customAttribute.array[ offset_custom + 10 ] = v3.z;
+							customAttribute.array[ offset_custom + 11 ] = v3.w;
 
 
-	this.setTexture = function ( texture, slot ) {
+							offset_custom += 12;
 
 
-		if ( texture.needsUpdate ) {
+						}
 
 
-			if ( ! texture.__webglInit ) {
+						for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
 
 
-				texture.__webglInit = true;
+							value = customAttribute.value[ chunk_faces4[ f ] ];
 
 
-				texture.addEventListener( 'dispose', onTextureDispose );
+							v1 = value;
+							v2 = value;
+							v3 = value;
+							v4 = value;
 
 
-				texture.__webglTexture = _gl.createTexture();
+							customAttribute.array[ offset_custom  ] 	= v1.x;
+							customAttribute.array[ offset_custom + 1  ] = v1.y;
+							customAttribute.array[ offset_custom + 2  ] = v1.z;
+							customAttribute.array[ offset_custom + 3  ] = v1.w;
 
 
-				_this.info.memory.textures ++;
+							customAttribute.array[ offset_custom + 4  ] = v2.x;
+							customAttribute.array[ offset_custom + 5  ] = v2.y;
+							customAttribute.array[ offset_custom + 6  ] = v2.z;
+							customAttribute.array[ offset_custom + 7  ] = v2.w;
 
 
-			}
+							customAttribute.array[ offset_custom + 8  ] = v3.x;
+							customAttribute.array[ offset_custom + 9  ] = v3.y;
+							customAttribute.array[ offset_custom + 10 ] = v3.z;
+							customAttribute.array[ offset_custom + 11 ] = v3.w;
 
 
-			_gl.activeTexture( _gl.TEXTURE0 + slot );
-			_gl.bindTexture( _gl.TEXTURE_2D, texture.__webglTexture );
+							customAttribute.array[ offset_custom + 12 ] = v4.x;
+							customAttribute.array[ offset_custom + 13 ] = v4.y;
+							customAttribute.array[ offset_custom + 14 ] = v4.z;
+							customAttribute.array[ offset_custom + 15 ] = v4.w;
 
 
-			_gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY );
-			_gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha );
-			_gl.pixelStorei( _gl.UNPACK_ALIGNMENT, texture.unpackAlignment );
+							offset_custom += 16;
 
 
-			var image = texture.image,
-			isImagePowerOfTwo = isPowerOfTwo( image.width ) && isPowerOfTwo( image.height ),
-			glFormat = paramThreeToGL( texture.format ),
-			glType = paramThreeToGL( texture.type );
+						}
 
 
-			setTextureParameters( _gl.TEXTURE_2D, texture, isImagePowerOfTwo );
+					} else if ( customAttribute.boundTo === "faceVertices" ) {
 
 
-			var mipmap, mipmaps = texture.mipmaps;
+						for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
 
 
-			if ( texture instanceof THREE.DataTexture ) {
+							value = customAttribute.value[ chunk_faces3[ f ] ];
 
 
-				// use manually created mipmaps if available
-				// if there are no manual mipmaps
-				// set 0 level mipmap and then use GL to generate other mipmap levels
+							v1 = value[ 0 ];
+							v2 = value[ 1 ];
+							v3 = value[ 2 ];
 
 
-				if ( mipmaps.length > 0 && isImagePowerOfTwo ) {
+							customAttribute.array[ offset_custom  ] 	= v1.x;
+							customAttribute.array[ offset_custom + 1  ] = v1.y;
+							customAttribute.array[ offset_custom + 2  ] = v1.z;
+							customAttribute.array[ offset_custom + 3  ] = v1.w;
 
 
-					for ( var i = 0, il = mipmaps.length; i < il; i ++ ) {
+							customAttribute.array[ offset_custom + 4  ] = v2.x;
+							customAttribute.array[ offset_custom + 5  ] = v2.y;
+							customAttribute.array[ offset_custom + 6  ] = v2.z;
+							customAttribute.array[ offset_custom + 7  ] = v2.w;
 
 
-						mipmap = mipmaps[ i ];
-						_gl.texImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
+							customAttribute.array[ offset_custom + 8  ] = v3.x;
+							customAttribute.array[ offset_custom + 9  ] = v3.y;
+							customAttribute.array[ offset_custom + 10 ] = v3.z;
+							customAttribute.array[ offset_custom + 11 ] = v3.w;
 
 
-					}
+							offset_custom += 12;
 
 
-					texture.generateMipmaps = false;
+						}
 
 
-				} else {
+						for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
 
 
-					_gl.texImage2D( _gl.TEXTURE_2D, 0, glFormat, image.width, image.height, 0, glFormat, glType, image.data );
+							value = customAttribute.value[ chunk_faces4[ f ] ];
 
 
-				}
+							v1 = value[ 0 ];
+							v2 = value[ 1 ];
+							v3 = value[ 2 ];
+							v4 = value[ 3 ];
 
 
-			} else if ( texture instanceof THREE.CompressedTexture ) {
+							customAttribute.array[ offset_custom  ] 	= v1.x;
+							customAttribute.array[ offset_custom + 1  ] = v1.y;
+							customAttribute.array[ offset_custom + 2  ] = v1.z;
+							customAttribute.array[ offset_custom + 3  ] = v1.w;
 
 
-				// compressed textures can only use manually created mipmaps
-				// WebGL can't generate mipmaps for DDS textures
+							customAttribute.array[ offset_custom + 4  ] = v2.x;
+							customAttribute.array[ offset_custom + 5  ] = v2.y;
+							customAttribute.array[ offset_custom + 6  ] = v2.z;
+							customAttribute.array[ offset_custom + 7  ] = v2.w;
 
 
-				for( var i = 0, il = mipmaps.length; i < il; i ++ ) {
+							customAttribute.array[ offset_custom + 8  ] = v3.x;
+							customAttribute.array[ offset_custom + 9  ] = v3.y;
+							customAttribute.array[ offset_custom + 10 ] = v3.z;
+							customAttribute.array[ offset_custom + 11 ] = v3.w;
 
 
-					mipmap = mipmaps[ i ];
-					_gl.compressedTexImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, mipmap.data );
+							customAttribute.array[ offset_custom + 12 ] = v4.x;
+							customAttribute.array[ offset_custom + 13 ] = v4.y;
+							customAttribute.array[ offset_custom + 14 ] = v4.z;
+							customAttribute.array[ offset_custom + 15 ] = v4.w;
 
 
-				}
+							offset_custom += 16;
 
 
-			} else { // regular Texture (image, video, canvas)
+						}
 
 
-				// use manually created mipmaps if available
-				// if there are no manual mipmaps
-				// set 0 level mipmap and then use GL to generate other mipmap levels
+					}
 
 
-				if ( mipmaps.length > 0 && isImagePowerOfTwo ) {
+				}
 
 
-					for ( var i = 0, il = mipmaps.length; i < il; i ++ ) {
+				renderer.setDynamicArrayBuffer( customAttribute.buffer, customAttribute.array);
 
 
-						mipmap = mipmaps[ i ];
-						_gl.texImage2D( _gl.TEXTURE_2D, i, glFormat, glFormat, glType, mipmap );
+			}
 
 
-					}
+		}
 
 
-					texture.generateMipmaps = false;
+		if ( dispose ) {
 
 
-				} else {
+			delete geometryGroup.__inittedArrays;
+			delete geometryGroup.__colorArray;
+			delete geometryGroup.__normalArray;
+			delete geometryGroup.__tangentArray;
+			delete geometryGroup.__uvArray;
+			delete geometryGroup.__uv2Array;
+			delete geometryGroup.__faceArray;
+			delete geometryGroup.__vertexArray;
+			delete geometryGroup.__lineArray;
+			delete geometryGroup.__skinIndexArray;
+			delete geometryGroup.__skinWeightArray;
 
 
-					_gl.texImage2D( _gl.TEXTURE_2D, 0, glFormat, glFormat, glType, texture.image );
+		}
 
 
-				}
+	}
 
 
-			}
+} );
 
 
-			if ( texture.generateMipmaps && isImagePowerOfTwo ) _gl.generateMipmap( _gl.TEXTURE_2D );
+THREE.WebGLRenderer.ParticleRenderer = function ( lowlevelrenderer, info ) {
 
 
-			texture.needsUpdate = false;
+	THREE.WebGLRenderer.Object3DRenderer.call( this, lowlevelrenderer, info );
 
 
-			if ( texture.onUpdate ) texture.onUpdate();
+};
 
 
-		} else {
+THREE.WebGLRenderer.ParticleRenderer.prototype = Object.create( THREE.WebGLRenderer.Object3DRenderer.prototype );
 
 
-			_gl.activeTexture( _gl.TEXTURE0 + slot );
-			_gl.bindTexture( _gl.TEXTURE_2D, texture.__webglTexture );
+THREE.extend( THREE.WebGLRenderer.ParticleRenderer.prototype, {
 
 
-		}
+	createBuffers: function ( geometry ) {
 
 
-	};
+		var renderer = this.renderer;
+		geometry.__webglVertexBuffer = renderer.createBuffer();
+		geometry.__webglColorBuffer = renderer.createBuffer();
 
 
-	function clampToMaxSize ( image, maxSize ) {
+		this.info.memory.geometries ++;
+	},
 
 
-		if ( image.width <= maxSize && image.height <= maxSize ) {
+	initBuffers: function ( geometry, object ) {
 
 
-			return image;
+		var nvertices = geometry.vertices.length;
 
 
-		}
+		geometry.__vertexArray = new Float32Array( nvertices * 3 );
+		geometry.__colorArray = new Float32Array( nvertices * 3 );
 
 
-		// Warning: Scaling through the canvas will only work with images that use
-		// premultiplied alpha.
+		geometry.__sortArray = [];
 
 
-		var maxDimension = Math.max( image.width, image.height );
-		var newWidth = Math.floor( image.width * maxSize / maxDimension );
-		var newHeight = Math.floor( image.height * maxSize / maxDimension );
+		geometry.__webglParticleCount = nvertices;
 
 
-		var canvas = document.createElement( 'canvas' );
-		canvas.width = newWidth;
-		canvas.height = newHeight;
+		this.initCustomAttributes ( geometry, object );
 
 
-		var ctx = canvas.getContext( "2d" );
-		ctx.drawImage( image, 0, 0, image.width, image.height, 0, 0, newWidth, newHeight );
+	},
 
 
-		return canvas;
+	setBuffers: function ( geometry, object , projectionScreenMatrix ) {
 
 
-	}
+		var renderer = this.renderer;
+		var v, c, vertex, offset, index, color,
 
 
-	function setCubeTexture ( texture, slot ) {
+		vertices = geometry.vertices,
+		vl = vertices.length,
 
 
-		if ( texture.image.length === 6 ) {
+		colors = geometry.colors,
+		cl = colors.length,
 
 
-			if ( texture.needsUpdate ) {
+		vertexArray = geometry.__vertexArray,
+		colorArray = geometry.__colorArray,
 
 
-				if ( ! texture.image.__webglTextureCube ) {
+		sortArray = geometry.__sortArray,
 
 
-					texture.image.__webglTextureCube = _gl.createTexture();
+		dirtyVertices = geometry.verticesNeedUpdate,
+		dirtyElements = geometry.elementsNeedUpdate,
+		dirtyColors = geometry.colorsNeedUpdate,
 
 
-					_this.info.memory.textures ++;
+		customAttributes = geometry.__webglCustomAttributesList,
+		i, il,
+		a, ca, cal, value,
+		customAttribute;
 
 
-				}
+		var _projScreenMatrixPS = THREE.WebGLRenderer.ParticleRenderer._m1,
+			_vector3 = THREE.WebGLRenderer.ParticleRenderer._v1;
 
 
-				_gl.activeTexture( _gl.TEXTURE0 + slot );
-				_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, texture.image.__webglTextureCube );
+		if ( object.sortParticles ) {
 
 
-				_gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY );
+			_projScreenMatrixPS.multiplyMatrices( projectionScreenMatrix, object.matrixWorld );
 
 
-				var isCompressed = texture instanceof THREE.CompressedTexture;
+			for ( v = 0; v < vl; v ++ ) {
 
 
-				var cubeImage = [];
+				vertex = vertices[ v ];
 
 
-				for ( var i = 0; i < 6; i ++ ) {
+				_vector3.copy( vertex );
+				_vector3.applyProjection(_projScreenMatrixPS);
 
 
-					if ( _this.autoScaleCubemaps && ! isCompressed ) {
+				sortArray[ v ] = [ _vector3.z, v ];
 
 
-						cubeImage[ i ] = clampToMaxSize( texture.image[ i ], _maxCubemapSize );
+			}
 
 
-					} else {
+			sortArray.sort( this.numericalSort );
 
 
-						cubeImage[ i ] = texture.image[ i ];
+			for ( v = 0; v < vl; v ++ ) {
 
 
-					}
+				vertex = vertices[ sortArray[v][1] ];
 
 
-				}
+				offset = v * 3;
 
 
-				var image = cubeImage[ 0 ],
-				isImagePowerOfTwo = isPowerOfTwo( image.width ) && isPowerOfTwo( image.height ),
-				glFormat = paramThreeToGL( texture.format ),
-				glType = paramThreeToGL( texture.type );
+				vertexArray[ offset ]     = vertex.x;
+				vertexArray[ offset + 1 ] = vertex.y;
+				vertexArray[ offset + 2 ] = vertex.z;
 
 
-				setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture, isImagePowerOfTwo );
+			}
 
 
-				for ( var i = 0; i < 6; i ++ ) {
+			for ( c = 0; c < cl; c ++ ) {
 
 
-					if ( isCompressed ) {
+				offset = c * 3;
 
 
-						var mipmap, mipmaps = cubeImage[ i ].mipmaps;
+				color = colors[ sortArray[c][1] ];
 
 
-						for( var j = 0, jl = mipmaps.length; j < jl; j ++ ) {
+				colorArray[ offset ]     = color.r;
+				colorArray[ offset + 1 ] = color.g;
+				colorArray[ offset + 2 ] = color.b;
 
 
-							mipmap = mipmaps[ j ];
-							_gl.compressedTexImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glFormat, mipmap.width, mipmap.height, 0, mipmap.data );
+			}
 
 
-						}
+			if ( customAttributes ) {
 
 
-					} else {
+				for ( i = 0, il = customAttributes.length; i < il; i ++ ) {
 
 
-						_gl.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, glFormat, glType, cubeImage[ i ] );
+					customAttribute = customAttributes[ i ];
 
 
-					}
+					if ( ! ( customAttribute.boundTo === undefined || customAttribute.boundTo === "vertices" ) ) continue;
 
 
-				}
+					offset = 0;
 
 
-				if ( texture.generateMipmaps && isImagePowerOfTwo ) {
+					cal = customAttribute.value.length;
 
 
-					_gl.generateMipmap( _gl.TEXTURE_CUBE_MAP );
+					if ( customAttribute.size === 1 ) {
 
 
-				}
+						for ( ca = 0; ca < cal; ca ++ ) {
 
 
-				texture.needsUpdate = false;
+							index = sortArray[ ca ][ 1 ];
 
 
-				if ( texture.onUpdate ) texture.onUpdate();
+							customAttribute.array[ ca ] = customAttribute.value[ index ];
 
 
-			} else {
+						}
 
 
-				_gl.activeTexture( _gl.TEXTURE0 + slot );
-				_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, texture.image.__webglTextureCube );
+					} else if ( customAttribute.size === 2 ) {
 
 
-			}
+						for ( ca = 0; ca < cal; ca ++ ) {
 
 
-		}
+							index = sortArray[ ca ][ 1 ];
 
 
-	};
+							value = customAttribute.value[ index ];
 
 
-	function setCubeTextureDynamic ( texture, slot ) {
+							customAttribute.array[ offset ] 	= value.x;
+							customAttribute.array[ offset + 1 ] = value.y;
 
 
-		_gl.activeTexture( _gl.TEXTURE0 + slot );
-		_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, texture.__webglTexture );
+							offset += 2;
 
 
-	};
+						}
 
 
-	// Render targets
+					} else if ( customAttribute.size === 3 ) {
 
 
-	function setupFrameBuffer ( framebuffer, renderTarget, textureTarget ) {
+						if ( customAttribute.type === "c" ) {
 
 
-		_gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
-		_gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, textureTarget, renderTarget.__webglTexture, 0 );
+							for ( ca = 0; ca < cal; ca ++ ) {
 
 
-	};
+								index = sortArray[ ca ][ 1 ];
 
 
-	function setupRenderBuffer ( renderbuffer, renderTarget  ) {
+								value = customAttribute.value[ index ];
 
 
-		_gl.bindRenderbuffer( _gl.RENDERBUFFER, renderbuffer );
+								customAttribute.array[ offset ]     = value.r;
+								customAttribute.array[ offset + 1 ] = value.g;
+								customAttribute.array[ offset + 2 ] = value.b;
 
 
-		if ( renderTarget.depthBuffer && ! renderTarget.stencilBuffer ) {
+								offset += 3;
 
 
-			_gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.DEPTH_COMPONENT16, renderTarget.width, renderTarget.height );
-			_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer );
+							}
 
 
-		/* For some reason this is not working. Defaulting to RGBA4.
-		} else if( ! renderTarget.depthBuffer && renderTarget.stencilBuffer ) {
+						} else {
 
 
-			_gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.STENCIL_INDEX8, renderTarget.width, renderTarget.height );
-			_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.STENCIL_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer );
-		*/
-		} else if ( renderTarget.depthBuffer && renderTarget.stencilBuffer ) {
+							for ( ca = 0; ca < cal; ca ++ ) {
 
 
-			_gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.DEPTH_STENCIL, renderTarget.width, renderTarget.height );
-			_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer );
+								index = sortArray[ ca ][ 1 ];
 
 
-		} else {
+								value = customAttribute.value[ index ];
 
 
-			_gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.RGBA4, renderTarget.width, renderTarget.height );
+								customAttribute.array[ offset ] 	= value.x;
+								customAttribute.array[ offset + 1 ] = value.y;
+								customAttribute.array[ offset + 2 ] = value.z;
 
 
-		}
+								offset += 3;
 
 
-	};
+							}
 
 
-	this.setRenderTarget = function ( renderTarget ) {
+						}
 
 
-		var isCube = ( renderTarget instanceof THREE.WebGLRenderTargetCube );
+					} else if ( customAttribute.size === 4 ) {
 
 
-		if ( renderTarget && ! renderTarget.__webglFramebuffer ) {
+						for ( ca = 0; ca < cal; ca ++ ) {
 
 
-			if ( renderTarget.depthBuffer === undefined ) renderTarget.depthBuffer = true;
-			if ( renderTarget.stencilBuffer === undefined ) renderTarget.stencilBuffer = true;
+							index = sortArray[ ca ][ 1 ];
 
 
-			renderTarget.addEventListener( 'dispose', onRenderTargetDispose );
+							value = customAttribute.value[ index ];
 
 
-			renderTarget.__webglTexture = _gl.createTexture();
+							customAttribute.array[ offset ]      = value.x;
+							customAttribute.array[ offset + 1  ] = value.y;
+							customAttribute.array[ offset + 2  ] = value.z;
+							customAttribute.array[ offset + 3  ] = value.w;
 
 
-			_this.info.memory.textures ++;
+							offset += 4;
 
 
-			// Setup texture, create render and frame buffers
+						}
 
 
-			var isTargetPowerOfTwo = isPowerOfTwo( renderTarget.width ) && isPowerOfTwo( renderTarget.height ),
-				glFormat = paramThreeToGL( renderTarget.format ),
-				glType = paramThreeToGL( renderTarget.type );
+					}
 
 
-			if ( isCube ) {
+				}
 
 
-				renderTarget.__webglFramebuffer = [];
-				renderTarget.__webglRenderbuffer = [];
+			}
 
 
-				_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, renderTarget.__webglTexture );
-				setTextureParameters( _gl.TEXTURE_CUBE_MAP, renderTarget, isTargetPowerOfTwo );
+		} else {
 
 
-				for ( var i = 0; i < 6; i ++ ) {
+			if ( dirtyVertices ) {
 
 
-					renderTarget.__webglFramebuffer[ i ] = _gl.createFramebuffer();
-					renderTarget.__webglRenderbuffer[ i ] = _gl.createRenderbuffer();
+				for ( v = 0; v < vl; v ++ ) {
 
 
-					_gl.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null );
+					vertex = vertices[ v ];
 
 
-					setupFrameBuffer( renderTarget.__webglFramebuffer[ i ], renderTarget, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i );
-					setupRenderBuffer( renderTarget.__webglRenderbuffer[ i ], renderTarget );
+					offset = v * 3;
 
 
-				}
+					vertexArray[ offset ]     = vertex.x;
+					vertexArray[ offset + 1 ] = vertex.y;
+					vertexArray[ offset + 2 ] = vertex.z;
 
 
-				if ( isTargetPowerOfTwo ) _gl.generateMipmap( _gl.TEXTURE_CUBE_MAP );
+				}
 
 
-			} else {
+			}
 
 
-				renderTarget.__webglFramebuffer = _gl.createFramebuffer();
+			if ( dirtyColors ) {
 
 
-				if ( renderTarget.shareDepthFrom ) {
+				for ( c = 0; c < cl; c ++ ) {
 
 
-					renderTarget.__webglRenderbuffer = renderTarget.shareDepthFrom.__webglRenderbuffer;
+					color = colors[ c ];
 
 
-				} else {
+					offset = c * 3;
 
 
-					renderTarget.__webglRenderbuffer = _gl.createRenderbuffer();
+					colorArray[ offset ]     = color.r;
+					colorArray[ offset + 1 ] = color.g;
+					colorArray[ offset + 2 ] = color.b;
 
 
 				}
 				}
 
 
-				_gl.bindTexture( _gl.TEXTURE_2D, renderTarget.__webglTexture );
-				setTextureParameters( _gl.TEXTURE_2D, renderTarget, isTargetPowerOfTwo );
+			}
 
 
-				_gl.texImage2D( _gl.TEXTURE_2D, 0, glFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null );
+			if ( customAttributes ) {
 
 
-				setupFrameBuffer( renderTarget.__webglFramebuffer, renderTarget, _gl.TEXTURE_2D );
+				for ( i = 0, il = customAttributes.length; i < il; i ++ ) {
 
 
-				if ( renderTarget.shareDepthFrom ) {
+					customAttribute = customAttributes[ i ];
 
 
-					if ( renderTarget.depthBuffer && ! renderTarget.stencilBuffer ) {
+					if ( customAttribute.needsUpdate &&
+						 ( customAttribute.boundTo === undefined ||
+						   customAttribute.boundTo === "vertices") ) {
 
 
-						_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.RENDERBUFFER, renderTarget.__webglRenderbuffer );
+						cal = customAttribute.value.length;
 
 
-					} else if ( renderTarget.depthBuffer && renderTarget.stencilBuffer ) {
+						offset = 0;
 
 
-						_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.RENDERBUFFER, renderTarget.__webglRenderbuffer );
+						if ( customAttribute.size === 1 ) {
 
 
-					}
+							for ( ca = 0; ca < cal; ca ++ ) {
 
 
-				} else {
+								customAttribute.array[ ca ] = customAttribute.value[ ca ];
 
 
-					setupRenderBuffer( renderTarget.__webglRenderbuffer, renderTarget );
+							}
 
 
-				}
+						} else if ( customAttribute.size === 2 ) {
 
 
-				if ( isTargetPowerOfTwo ) _gl.generateMipmap( _gl.TEXTURE_2D );
+							for ( ca = 0; ca < cal; ca ++ ) {
 
 
-			}
+								value = customAttribute.value[ ca ];
 
 
-			// Release everything
+								customAttribute.array[ offset ] 	= value.x;
+								customAttribute.array[ offset + 1 ] = value.y;
 
 
-			if ( isCube ) {
+								offset += 2;
 
 
-				_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, null );
+							}
 
 
-			} else {
+						} else if ( customAttribute.size === 3 ) {
 
 
-				_gl.bindTexture( _gl.TEXTURE_2D, null );
+							if ( customAttribute.type === "c" ) {
 
 
-			}
+								for ( ca = 0; ca < cal; ca ++ ) {
 
 
-			_gl.bindRenderbuffer( _gl.RENDERBUFFER, null );
-			_gl.bindFramebuffer( _gl.FRAMEBUFFER, null );
+									value = customAttribute.value[ ca ];
 
 
-		}
+									customAttribute.array[ offset ] 	= value.r;
+									customAttribute.array[ offset + 1 ] = value.g;
+									customAttribute.array[ offset + 2 ] = value.b;
 
 
-		var framebuffer, width, height, vx, vy;
+									offset += 3;
 
 
-		if ( renderTarget ) {
+								}
 
 
-			if ( isCube ) {
+							} else {
 
 
-				framebuffer = renderTarget.__webglFramebuffer[ renderTarget.activeCubeFace ];
+								for ( ca = 0; ca < cal; ca ++ ) {
 
 
-			} else {
+									value = customAttribute.value[ ca ];
 
 
-				framebuffer = renderTarget.__webglFramebuffer;
+									customAttribute.array[ offset ] 	= value.x;
+									customAttribute.array[ offset + 1 ] = value.y;
+									customAttribute.array[ offset + 2 ] = value.z;
 
 
-			}
+									offset += 3;
 
 
-			width = renderTarget.width;
-			height = renderTarget.height;
+								}
 
 
-			vx = 0;
-			vy = 0;
+							}
 
 
-		} else {
+						} else if ( customAttribute.size === 4 ) {
 
 
-			framebuffer = null;
+							for ( ca = 0; ca < cal; ca ++ ) {
 
 
-			width = _viewportWidth;
-			height = _viewportHeight;
+								value = customAttribute.value[ ca ];
 
 
-			vx = _viewportX;
-			vy = _viewportY;
+								customAttribute.array[ offset ]      = value.x;
+								customAttribute.array[ offset + 1  ] = value.y;
+								customAttribute.array[ offset + 2  ] = value.z;
+								customAttribute.array[ offset + 3  ] = value.w;
 
 
-		}
+								offset += 4;
 
 
-		if ( framebuffer !== _currentFramebuffer ) {
+							}
 
 
-			_gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
-			_gl.viewport( vx, vy, width, height );
+						}
 
 
-			_currentFramebuffer = framebuffer;
+					}
 
 
-		}
+				}
 
 
-		_currentWidth = width;
-		_currentHeight = height;
+			}
 
 
-	};
+		}
 
 
-	function updateRenderTargetMipmap ( renderTarget ) {
+		if ( dirtyVertices || object.sortParticles ) {
 
 
-		if ( renderTarget instanceof THREE.WebGLRenderTargetCube ) {
+			renderer.setDynamicArrayBuffer(geometry.__webglVertexBuffer,vertexArray);
 
 
-			_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, renderTarget.__webglTexture );
-			_gl.generateMipmap( _gl.TEXTURE_CUBE_MAP );
-			_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, null );
+		}
 
 
-		} else {
+		if ( dirtyColors || object.sortParticles ) {
 
 
-			_gl.bindTexture( _gl.TEXTURE_2D, renderTarget.__webglTexture );
-			_gl.generateMipmap( _gl.TEXTURE_2D );
-			_gl.bindTexture( _gl.TEXTURE_2D, null );
+			renderer.setDynamicArrayBuffer(geometry.__webglColorBuffer,colorArray);
 
 
 		}
 		}
 
 
-	};
+		if ( customAttributes ) {
 
 
-	// Fallback filters for non-power-of-2 textures
+			for ( i = 0, il = customAttributes.length; i < il; i ++ ) {
 
 
-	function filterFallback ( f ) {
+				customAttribute = customAttributes[ i ];
 
 
-		if ( f === THREE.NearestFilter || f === THREE.NearestMipMapNearestFilter || f === THREE.NearestMipMapLinearFilter ) {
+				if ( customAttribute.needsUpdate || object.sortParticles ) {
 
 
-			return _gl.NEAREST;
+					renderer.setDynamicArrayBuffer(customAttribute.buffer,customAttribute.array);
+
+				}
+
+			}
 
 
 		}
 		}
 
 
-		return _gl.LINEAR;
+	}
 
 
-	};
+} );
 
 
-	// Map three.js constants to WebGL constants
+THREE.WebGLRenderer.ParticleRenderer._m1 = new THREE.Matrix4();
+THREE.WebGLRenderer.ParticleRenderer._v1 = new THREE.Vector3();
 
 
-	function paramThreeToGL ( p ) {
+THREE.WebGLRenderer.LineRenderer = function ( lowlevelrenderer, info ) {
 
 
-		if ( p === THREE.RepeatWrapping ) return _gl.REPEAT;
-		if ( p === THREE.ClampToEdgeWrapping ) return _gl.CLAMP_TO_EDGE;
-		if ( p === THREE.MirroredRepeatWrapping ) return _gl.MIRRORED_REPEAT;
+	THREE.WebGLRenderer.Object3DRenderer.call( this, lowlevelrenderer, info );
 
 
-		if ( p === THREE.NearestFilter ) return _gl.NEAREST;
-		if ( p === THREE.NearestMipMapNearestFilter ) return _gl.NEAREST_MIPMAP_NEAREST;
-		if ( p === THREE.NearestMipMapLinearFilter ) return _gl.NEAREST_MIPMAP_LINEAR;
+};
 
 
-		if ( p === THREE.LinearFilter ) return _gl.LINEAR;
-		if ( p === THREE.LinearMipMapNearestFilter ) return _gl.LINEAR_MIPMAP_NEAREST;
-		if ( p === THREE.LinearMipMapLinearFilter ) return _gl.LINEAR_MIPMAP_LINEAR;
+THREE.WebGLRenderer.LineRenderer.prototype = Object.create( THREE.WebGLRenderer.Object3DRenderer.prototype );
 
 
-		if ( p === THREE.UnsignedByteType ) return _gl.UNSIGNED_BYTE;
-		if ( p === THREE.UnsignedShort4444Type ) return _gl.UNSIGNED_SHORT_4_4_4_4;
-		if ( p === THREE.UnsignedShort5551Type ) return _gl.UNSIGNED_SHORT_5_5_5_1;
-		if ( p === THREE.UnsignedShort565Type ) return _gl.UNSIGNED_SHORT_5_6_5;
+THREE.extend( THREE.WebGLRenderer.LineRenderer.prototype, {
 
 
-		if ( p === THREE.ByteType ) return _gl.BYTE;
-		if ( p === THREE.ShortType ) return _gl.SHORT;
-		if ( p === THREE.UnsignedShortType ) return _gl.UNSIGNED_SHORT;
-		if ( p === THREE.IntType ) return _gl.INT;
-		if ( p === THREE.UnsignedIntType ) return _gl.UNSIGNED_INT;
-		if ( p === THREE.FloatType ) return _gl.FLOAT;
+	createBuffers: function ( geometry ) {
 
 
-		if ( p === THREE.AlphaFormat ) return _gl.ALPHA;
-		if ( p === THREE.RGBFormat ) return _gl.RGB;
-		if ( p === THREE.RGBAFormat ) return _gl.RGBA;
-		if ( p === THREE.LuminanceFormat ) return _gl.LUMINANCE;
-		if ( p === THREE.LuminanceAlphaFormat ) return _gl.LUMINANCE_ALPHA;
+		var renderer = this.renderer;
+		geometry.__webglVertexBuffer = renderer.createBuffer();
+		geometry.__webglColorBuffer = renderer.createBuffer();
+		geometry.__webglLineDistanceBuffer = renderer.createBuffer();
 
 
-		if ( p === THREE.AddEquation ) return _gl.FUNC_ADD;
-		if ( p === THREE.SubtractEquation ) return _gl.FUNC_SUBTRACT;
-		if ( p === THREE.ReverseSubtractEquation ) return _gl.FUNC_REVERSE_SUBTRACT;
+		this.info.memory.geometries ++;
 
 
-		if ( p === THREE.ZeroFactor ) return _gl.ZERO;
-		if ( p === THREE.OneFactor ) return _gl.ONE;
-		if ( p === THREE.SrcColorFactor ) return _gl.SRC_COLOR;
-		if ( p === THREE.OneMinusSrcColorFactor ) return _gl.ONE_MINUS_SRC_COLOR;
-		if ( p === THREE.SrcAlphaFactor ) return _gl.SRC_ALPHA;
-		if ( p === THREE.OneMinusSrcAlphaFactor ) return _gl.ONE_MINUS_SRC_ALPHA;
-		if ( p === THREE.DstAlphaFactor ) return _gl.DST_ALPHA;
-		if ( p === THREE.OneMinusDstAlphaFactor ) return _gl.ONE_MINUS_DST_ALPHA;
+	},
 
 
-		if ( p === THREE.DstColorFactor ) return _gl.DST_COLOR;
-		if ( p === THREE.OneMinusDstColorFactor ) return _gl.ONE_MINUS_DST_COLOR;
-		if ( p === THREE.SrcAlphaSaturateFactor ) return _gl.SRC_ALPHA_SATURATE;
+	initBuffers: function ( geometry, object ) {
 
 
-		if ( _glExtensionCompressedTextureS3TC !== undefined ) {
+		var nvertices = geometry.vertices.length;
 
 
-			if ( p === THREE.RGB_S3TC_DXT1_Format ) return _glExtensionCompressedTextureS3TC.COMPRESSED_RGB_S3TC_DXT1_EXT;
-			if ( p === THREE.RGBA_S3TC_DXT1_Format ) return _glExtensionCompressedTextureS3TC.COMPRESSED_RGBA_S3TC_DXT1_EXT;
-			if ( p === THREE.RGBA_S3TC_DXT3_Format ) return _glExtensionCompressedTextureS3TC.COMPRESSED_RGBA_S3TC_DXT3_EXT;
-			if ( p === THREE.RGBA_S3TC_DXT5_Format ) return _glExtensionCompressedTextureS3TC.COMPRESSED_RGBA_S3TC_DXT5_EXT;
+		geometry.__vertexArray = new Float32Array( nvertices * 3 );
+		geometry.__colorArray = new Float32Array( nvertices * 3 );
+		geometry.__lineDistanceArray = new Float32Array( nvertices * 1 );
 
 
-		}
+		geometry.__webglLineCount = nvertices;
 
 
-		return 0;
+		this.initCustomAttributes ( geometry, object );
 
 
-	};
+	},
 
 
-	// Allocations
+	setBuffers: function ( geometry, object ) {
 
 
-	function allocateBones ( object ) {
+		var renderer = this.renderer;
+		var v, c, d, vertex, offset, color,
 
 
-		if ( _supportsBoneTextures && object && object.useVertexTexture ) {
+		vertices = geometry.vertices,
+		colors = geometry.colors,
+		lineDistances = geometry.lineDistances,
 
 
-			return 1024;
+		vl = vertices.length,
+		cl = colors.length,
+		dl = lineDistances.length,
 
 
-		} else {
+		vertexArray = geometry.__vertexArray,
+		colorArray = geometry.__colorArray,
+		lineDistanceArray = geometry.__lineDistanceArray,
 
 
-			// default for when object is not specified
-			// ( for example when prebuilding shader
-			//   to be used with multiple objects )
-			//
-			// 	- leave some extra space for other uniforms
-			//  - limit here is ANGLE's 254 max uniform vectors
-			//    (up to 54 should be safe)
+		dirtyVertices = geometry.verticesNeedUpdate,
+		dirtyColors = geometry.colorsNeedUpdate,
+		dirtyLineDistances = geometry.lineDistancesNeedUpdate,
 
 
-			var nVertexUniforms = _gl.getParameter( _gl.MAX_VERTEX_UNIFORM_VECTORS );
-			var nVertexMatrices = Math.floor( ( nVertexUniforms - 20 ) / 4 );
+		customAttributes = geometry.__webglCustomAttributesList,
 
 
-			var maxBones = nVertexMatrices;
+		i, il,
+		a, ca, cal, value,
+		customAttribute;
 
 
-			if ( object !== undefined && object instanceof THREE.SkinnedMesh ) {
+		if ( dirtyVertices ) {
 
 
-				maxBones = Math.min( object.bones.length, maxBones );
+			for ( v = 0; v < vl; v ++ ) {
 
 
-				if ( maxBones < object.bones.length ) {
+				vertex = vertices[ v ];
 
 
-					console.warn( "WebGLRenderer: too many bones - " + object.bones.length + ", this GPU supports just " + maxBones + " (try OpenGL instead of ANGLE)" );
+				offset = v * 3;
 
 
-				}
+				vertexArray[ offset ]     = vertex.x;
+				vertexArray[ offset + 1 ] = vertex.y;
+				vertexArray[ offset + 2 ] = vertex.z;
 
 
 			}
 			}
 
 
-			return maxBones;
+			renderer.setDynamicArrayBuffer(geometry.__webglVertexBuffer,vertexArray);
 
 
 		}
 		}
 
 
-	};
-
-	function allocateLights ( lights ) {
+		if ( dirtyColors ) {
 
 
-		var l, ll, light, dirLights, pointLights, spotLights, hemiLights;
+			for ( c = 0; c < cl; c ++ ) {
 
 
-		dirLights = pointLights = spotLights = hemiLights = 0;
+				color = colors[ c ];
 
 
-		for ( l = 0, ll = lights.length; l < ll; l ++ ) {
+				offset = c * 3;
 
 
-			light = lights[ l ];
+				colorArray[ offset ]     = color.r;
+				colorArray[ offset + 1 ] = color.g;
+				colorArray[ offset + 2 ] = color.b;
 
 
-			if ( light.onlyShadow ) continue;
+			}
 
 
-			if ( light instanceof THREE.DirectionalLight ) dirLights ++;
-			if ( light instanceof THREE.PointLight ) pointLights ++;
-			if ( light instanceof THREE.SpotLight ) spotLights ++;
-			if ( light instanceof THREE.HemisphereLight ) hemiLights ++;
+			renderer.setDynamicArrayBuffer(geometry.__webglColorBuffer,colorArray);
 
 
 		}
 		}
 
 
-		return { 'directional' : dirLights, 'point' : pointLights, 'spot': spotLights, 'hemi': hemiLights };
-
-	};
-
-	function allocateShadows ( lights ) {
-
-		var l, ll, light, maxShadows = 0;
+		if ( dirtyLineDistances ) {
 
 
-		for ( l = 0, ll = lights.length; l < ll; l++ ) {
+			for ( d = 0; d < dl; d ++ ) {
 
 
-			light = lights[ l ];
+				lineDistanceArray[ d ] = lineDistances[ d ];
 
 
-			if ( ! light.castShadow ) continue;
+			}
 
 
-			if ( light instanceof THREE.SpotLight ) maxShadows ++;
-			if ( light instanceof THREE.DirectionalLight && ! light.shadowCascade ) maxShadows ++;
+			renderer.setDynamicArrayBuffer( geometry.__webglLineDistanceBuffer,lineDistanceArray);
 
 
 		}
 		}
 
 
-		return maxShadows;
+		if ( customAttributes ) {
 
 
-	};
+			for ( i = 0, il = customAttributes.length; i < il; i ++ ) {
 
 
-	// Initialization
+				customAttribute = customAttributes[ i ];
 
 
-	function initGL () {
+				if ( customAttribute.needsUpdate &&
+					 ( customAttribute.boundTo === undefined ||
+					   customAttribute.boundTo === "vertices" ) ) {
 
 
-		try {
+					offset = 0;
 
 
-			if ( ! ( _gl = _canvas.getContext( 'experimental-webgl', { alpha: _alpha, premultipliedAlpha: _premultipliedAlpha, antialias: _antialias, stencil: _stencil, preserveDrawingBuffer: _preserveDrawingBuffer } ) ) ) {
+					cal = customAttribute.value.length;
 
 
-				throw 'Error creating WebGL context.';
+					if ( customAttribute.size === 1 ) {
 
 
-			}
+						for ( ca = 0; ca < cal; ca ++ ) {
 
 
-		} catch ( error ) {
+							customAttribute.array[ ca ] = customAttribute.value[ ca ];
 
 
-			console.error( error );
+						}
 
 
-		}
+					} else if ( customAttribute.size === 2 ) {
 
 
-		_glExtensionTextureFloat = _gl.getExtension( 'OES_texture_float' );
-		_glExtensionStandardDerivatives = _gl.getExtension( 'OES_standard_derivatives' );
+						for ( ca = 0; ca < cal; ca ++ ) {
 
 
-		_glExtensionTextureFilterAnisotropic = _gl.getExtension( 'EXT_texture_filter_anisotropic' ) ||
-											   _gl.getExtension( 'MOZ_EXT_texture_filter_anisotropic' ) ||
-											   _gl.getExtension( 'WEBKIT_EXT_texture_filter_anisotropic' );
+							value = customAttribute.value[ ca ];
 
 
+							customAttribute.array[ offset ] 	= value.x;
+							customAttribute.array[ offset + 1 ] = value.y;
 
 
-		_glExtensionCompressedTextureS3TC = _gl.getExtension( 'WEBGL_compressed_texture_s3tc' ) ||
-											_gl.getExtension( 'MOZ_WEBGL_compressed_texture_s3tc' ) ||
-											_gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_s3tc' );
+							offset += 2;
 
 
-		if ( ! _glExtensionTextureFloat ) {
+						}
 
 
-			console.log( 'THREE.WebGLRenderer: Float textures not supported.' );
+					} else if ( customAttribute.size === 3 ) {
 
 
-		}
+						if ( customAttribute.type === "c" ) {
 
 
-		if ( ! _glExtensionStandardDerivatives ) {
+							for ( ca = 0; ca < cal; ca ++ ) {
 
 
-			console.log( 'THREE.WebGLRenderer: Standard derivatives not supported.' );
+								value = customAttribute.value[ ca ];
 
 
-		}
+								customAttribute.array[ offset ] 	= value.r;
+								customAttribute.array[ offset + 1 ] = value.g;
+								customAttribute.array[ offset + 2 ] = value.b;
 
 
-		if ( ! _glExtensionTextureFilterAnisotropic ) {
+								offset += 3;
 
 
-			console.log( 'THREE.WebGLRenderer: Anisotropic texture filtering not supported.' );
+							}
 
 
-		}
+						} else {
 
 
-		if ( ! _glExtensionCompressedTextureS3TC ) {
+							for ( ca = 0; ca < cal; ca ++ ) {
 
 
-			console.log( 'THREE.WebGLRenderer: S3TC compressed textures not supported.' );
+								value = customAttribute.value[ ca ];
 
 
-		}
+								customAttribute.array[ offset ] 	= value.x;
+								customAttribute.array[ offset + 1 ] = value.y;
+								customAttribute.array[ offset + 2 ] = value.z;
 
 
-		if ( _gl.getShaderPrecisionFormat === undefined ) {
+								offset += 3;
 
 
-			_gl.getShaderPrecisionFormat = function() {
+							}
 
 
-				return {
-					"rangeMin"  : 1,
-					"rangeMax"  : 1,
-					"precision" : 1
-				};
+						}
 
 
-			}
-		}
+					} else if ( customAttribute.size === 4 ) {
 
 
-	};
+						for ( ca = 0; ca < cal; ca ++ ) {
 
 
-	function setDefaultGLState () {
+							value = customAttribute.value[ ca ];
 
 
-		_gl.clearColor( 0, 0, 0, 1 );
-		_gl.clearDepth( 1 );
-		_gl.clearStencil( 0 );
+							customAttribute.array[ offset ] 	 = value.x;
+							customAttribute.array[ offset + 1  ] = value.y;
+							customAttribute.array[ offset + 2  ] = value.z;
+							customAttribute.array[ offset + 3  ] = value.w;
 
 
-		_gl.enable( _gl.DEPTH_TEST );
-		_gl.depthFunc( _gl.LEQUAL );
+							offset += 4;
 
 
-		_gl.frontFace( _gl.CCW );
-		_gl.cullFace( _gl.BACK );
-		_gl.enable( _gl.CULL_FACE );
+						}
 
 
-		_gl.enable( _gl.BLEND );
-		_gl.blendEquation( _gl.FUNC_ADD );
-		_gl.blendFunc( _gl.SRC_ALPHA, _gl.ONE_MINUS_SRC_ALPHA );
+					}
 
 
-		_gl.clearColor( _clearColor.r, _clearColor.g, _clearColor.b, _clearAlpha );
+					renderer.setDynamicArrayBuffer( customAttribute.buffer,customAttribute.array);
 
 
-	};
+				}
 
 
-	// default plugins (order is important)
+			}
 
 
-	this.shadowMapPlugin = new THREE.ShadowMapPlugin();
-	this.addPrePlugin( this.shadowMapPlugin );
+		}
 
 
-	this.addPostPlugin( new THREE.SpritePlugin() );
-	this.addPostPlugin( new THREE.LensFlarePlugin() );
+	}
 
 
-};
+} );
+
+THREE.WebGLRenderer.RibbonRenderer = function ( lowlevelrenderer, info ) {
+
+	THREE.WebGLRenderer.Object3DRenderer.call( this, lowlevelrenderer, info );
+
+};
+
+THREE.WebGLRenderer.RibbonRenderer.prototype = Object.create( THREE.WebGLRenderer.Object3DRenderer.prototype );
+
+THREE.extend( THREE.WebGLRenderer.RibbonRenderer.prototype, {
+
+	createBuffers: function ( geometry ) {
+
+		var renderer = this.renderer;
+		geometry.__webglVertexBuffer = renderer.createBuffer();
+		geometry.__webglColorBuffer = renderer.createBuffer();
+		geometry.__webglNormalBuffer = renderer.createBuffer();
+
+		this.info.memory.geometries ++;
+	},
+
+	initBuffers: function ( geometry, object ) {
+
+		var nvertices = geometry.vertices.length;
+
+		geometry.__vertexArray = new Float32Array( nvertices * 3 );
+		geometry.__colorArray = new Float32Array( nvertices * 3 );
+		geometry.__normalArray = new Float32Array( nvertices * 3 );
+
+		geometry.__webglVertexCount = nvertices;
+
+		this.initCustomAttributes ( geometry, object );
+
+	},
+
+	setBuffers: function ( geometry, object , projectionScreenMatrix ) {
+
+		var renderer = this.renderer;
+		var v, c, n, vertex, offset, color, normal,
+
+		i, il, ca, cal, customAttribute, value,
+
+		vertices = geometry.vertices,
+		colors = geometry.colors,
+		normals = geometry.normals,
+
+		vl = vertices.length,
+		cl = colors.length,
+		nl = normals.length,
+
+		vertexArray = geometry.__vertexArray,
+		colorArray = geometry.__colorArray,
+		normalArray = geometry.__normalArray,
+
+		dirtyVertices = geometry.verticesNeedUpdate,
+		dirtyColors = geometry.colorsNeedUpdate,
+		dirtyNormals = geometry.normalsNeedUpdate,
+
+		customAttributes = geometry.__webglCustomAttributesList;
+
+		if ( dirtyVertices ) {
+
+			for ( v = 0; v < vl; v ++ ) {
+
+				vertex = vertices[ v ];
+
+				offset = v * 3;
+
+				vertexArray[ offset ]     = vertex.x;
+				vertexArray[ offset + 1 ] = vertex.y;
+				vertexArray[ offset + 2 ] = vertex.z;
+
+			}
+
+			renderer.setDynamicArrayBuffer( geometry.__webglVertexBuffer,vertexArray);
+
+		}
+
+		if ( dirtyColors ) {
+
+			for ( c = 0; c < cl; c ++ ) {
+
+				color = colors[ c ];
+
+				offset = c * 3;
+
+				colorArray[ offset ]     = color.r;
+				colorArray[ offset + 1 ] = color.g;
+				colorArray[ offset + 2 ] = color.b;
+
+			}
+
+			renderer.setDynamicArrayBuffer( geometry.__webglColorBuffer, colorArray);
+
+		}
+
+		if ( dirtyNormals ) {
+
+			for ( n = 0; n < nl; n ++ ) {
+
+				normal = normals[ n ];
+
+				offset = n * 3;
+
+				normalArray[ offset ]     = normal.x;
+				normalArray[ offset + 1 ] = normal.y;
+				normalArray[ offset + 2 ] = normal.z;
+
+			}
+
+			renderer.setDynamicArrayBuffer( geometry.__webglNormalBuffer, normalArray);
+
+		}
+
+		if ( customAttributes ) {
+
+			for ( i = 0, il = customAttributes.length; i < il; i ++ ) {
+
+				customAttribute = customAttributes[ i ];
+
+				if ( customAttribute.needsUpdate &&
+					 ( customAttribute.boundTo === undefined ||
+					   customAttribute.boundTo === "vertices" ) ) {
+
+					offset = 0;
+
+					cal = customAttribute.value.length;
+
+					if ( customAttribute.size === 1 ) {
+
+						for ( ca = 0; ca < cal; ca ++ ) {
+
+							customAttribute.array[ ca ] = customAttribute.value[ ca ];
+
+						}
+
+					} else if ( customAttribute.size === 2 ) {
+
+						for ( ca = 0; ca < cal; ca ++ ) {
+
+							value = customAttribute.value[ ca ];
+
+							customAttribute.array[ offset ] 	= value.x;
+							customAttribute.array[ offset + 1 ] = value.y;
+
+							offset += 2;
+
+						}
+
+					} else if ( customAttribute.size === 3 ) {
+
+						if ( customAttribute.type === "c" ) {
+
+							for ( ca = 0; ca < cal; ca ++ ) {
+
+								value = customAttribute.value[ ca ];
+
+								customAttribute.array[ offset ] 	= value.r;
+								customAttribute.array[ offset + 1 ] = value.g;
+								customAttribute.array[ offset + 2 ] = value.b;
+
+								offset += 3;
+
+							}
+
+						} else {
+
+							for ( ca = 0; ca < cal; ca ++ ) {
+
+								value = customAttribute.value[ ca ];
+
+								customAttribute.array[ offset ] 	= value.x;
+								customAttribute.array[ offset + 1 ] = value.y;
+								customAttribute.array[ offset + 2 ] = value.z;
+
+								offset += 3;
+
+							}
+
+						}
+
+					} else if ( customAttribute.size === 4 ) {
+
+						for ( ca = 0; ca < cal; ca ++ ) {
+
+							value = customAttribute.value[ ca ];
+
+							customAttribute.array[ offset ] 	 = value.x;
+							customAttribute.array[ offset + 1  ] = value.y;
+							customAttribute.array[ offset + 2  ] = value.z;
+							customAttribute.array[ offset + 3  ] = value.w;
+
+							offset += 4;
+
+						}
+
+					}
+
+					renderer.setDynamicArrayBuffer( customAttribute.buffer, customAttribute.array);
+
+				}
+
+			}
+
+		}
+
+	}
+
+} );
 /**
 /**
  * @author szimek / https://github.com/szimek/
  * @author szimek / https://github.com/szimek/
  * @author alteredq / http://alteredqualia.com/
  * @author alteredq / http://alteredqualia.com/

+ 383 - 383
build/three.min.js

@@ -22,9 +22,9 @@ palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:1677
 tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074};THREE.Quaternion=function(a,b,c,d){this.x=a||0;this.y=b||0;this.z=c||0;this.w=void 0!==d?d:1};
 tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074};THREE.Quaternion=function(a,b,c,d){this.x=a||0;this.y=b||0;this.z=c||0;this.w=void 0!==d?d:1};
 THREE.extend(THREE.Quaternion.prototype,{set:function(a,b,c,d){this.x=a;this.y=b;this.z=c;this.w=d;return this},copy:function(a){this.x=a.x;this.y=a.y;this.z=a.z;this.w=a.w;return this},setFromEuler:function(a,b){var c=Math.cos(a.x/2),d=Math.cos(a.y/2),e=Math.cos(a.z/2),f=Math.sin(a.x/2),g=Math.sin(a.y/2),h=Math.sin(a.z/2);void 0===b||"XYZ"===b?(this.x=f*d*e+c*g*h,this.y=c*g*e-f*d*h,this.z=c*d*h+f*g*e,this.w=c*d*e-f*g*h):"YXZ"===b?(this.x=f*d*e+c*g*h,this.y=c*g*e-f*d*h,this.z=c*d*h-f*g*e,this.w=c*
 THREE.extend(THREE.Quaternion.prototype,{set:function(a,b,c,d){this.x=a;this.y=b;this.z=c;this.w=d;return this},copy:function(a){this.x=a.x;this.y=a.y;this.z=a.z;this.w=a.w;return this},setFromEuler:function(a,b){var c=Math.cos(a.x/2),d=Math.cos(a.y/2),e=Math.cos(a.z/2),f=Math.sin(a.x/2),g=Math.sin(a.y/2),h=Math.sin(a.z/2);void 0===b||"XYZ"===b?(this.x=f*d*e+c*g*h,this.y=c*g*e-f*d*h,this.z=c*d*h+f*g*e,this.w=c*d*e-f*g*h):"YXZ"===b?(this.x=f*d*e+c*g*h,this.y=c*g*e-f*d*h,this.z=c*d*h-f*g*e,this.w=c*
 d*e+f*g*h):"ZXY"===b?(this.x=f*d*e-c*g*h,this.y=c*g*e+f*d*h,this.z=c*d*h+f*g*e,this.w=c*d*e-f*g*h):"ZYX"===b?(this.x=f*d*e-c*g*h,this.y=c*g*e+f*d*h,this.z=c*d*h-f*g*e,this.w=c*d*e+f*g*h):"YZX"===b?(this.x=f*d*e+c*g*h,this.y=c*g*e+f*d*h,this.z=c*d*h-f*g*e,this.w=c*d*e-f*g*h):"XZY"===b&&(this.x=f*d*e-c*g*h,this.y=c*g*e-f*d*h,this.z=c*d*h+f*g*e,this.w=c*d*e+f*g*h);return this},setFromAxisAngle:function(a,b){var c=b/2,d=Math.sin(c);this.x=a.x*d;this.y=a.y*d;this.z=a.z*d;this.w=Math.cos(c);return this},
 d*e+f*g*h):"ZXY"===b?(this.x=f*d*e-c*g*h,this.y=c*g*e+f*d*h,this.z=c*d*h+f*g*e,this.w=c*d*e-f*g*h):"ZYX"===b?(this.x=f*d*e-c*g*h,this.y=c*g*e+f*d*h,this.z=c*d*h-f*g*e,this.w=c*d*e+f*g*h):"YZX"===b?(this.x=f*d*e+c*g*h,this.y=c*g*e+f*d*h,this.z=c*d*h-f*g*e,this.w=c*d*e-f*g*h):"XZY"===b&&(this.x=f*d*e-c*g*h,this.y=c*g*e-f*d*h,this.z=c*d*h+f*g*e,this.w=c*d*e+f*g*h);return this},setFromAxisAngle:function(a,b){var c=b/2,d=Math.sin(c);this.x=a.x*d;this.y=a.y*d;this.z=a.z*d;this.w=Math.cos(c);return this},
-setFromRotationMatrix:function(a){var b=a.elements,c=b[0],a=b[4],d=b[8],e=b[1],f=b[5],g=b[9],h=b[2],i=b[6],b=b[10],k=c+f+b;0<k?(c=0.5/Math.sqrt(k+1),this.w=0.25/c,this.x=(i-g)*c,this.y=(d-h)*c,this.z=(e-a)*c):c>f&&c>b?(c=2*Math.sqrt(1+c-f-b),this.w=(i-g)/c,this.x=0.25*c,this.y=(a+e)/c,this.z=(d+h)/c):f>b?(c=2*Math.sqrt(1+f-c-b),this.w=(d-h)/c,this.x=(a+e)/c,this.y=0.25*c,this.z=(g+i)/c):(c=2*Math.sqrt(1+b-c-f),this.w=(e-a)/c,this.x=(d+h)/c,this.y=(g+i)/c,this.z=0.25*c);return this},inverse:function(){this.conjugate().normalize();
+setFromRotationMatrix:function(a){var b=a.elements,c=b[0],a=b[4],d=b[8],e=b[1],f=b[5],g=b[9],h=b[2],i=b[6],b=b[10],j=c+f+b;0<j?(c=0.5/Math.sqrt(j+1),this.w=0.25/c,this.x=(i-g)*c,this.y=(d-h)*c,this.z=(e-a)*c):c>f&&c>b?(c=2*Math.sqrt(1+c-f-b),this.w=(i-g)/c,this.x=0.25*c,this.y=(a+e)/c,this.z=(d+h)/c):f>b?(c=2*Math.sqrt(1+f-c-b),this.w=(d-h)/c,this.x=(a+e)/c,this.y=0.25*c,this.z=(g+i)/c):(c=2*Math.sqrt(1+b-c-f),this.w=(e-a)/c,this.x=(d+h)/c,this.y=(g+i)/c,this.z=0.25*c);return this},inverse:function(){this.conjugate().normalize();
 return this},conjugate:function(){this.x*=-1;this.y*=-1;this.z*=-1;return this},lengthSq:function(){return this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w},length:function(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w)},normalize:function(){var a=this.length();0===a?(this.z=this.y=this.x=0,this.w=1):(a=1/a,this.x*=a,this.y*=a,this.z*=a,this.w*=a);return this},multiply:function(a,b){return void 0!==b?(console.warn("DEPRECATED: Quaternion's .multiply() now only accepts one argument. Use .multiplyQuaternions( a, b ) instead."),
 return this},conjugate:function(){this.x*=-1;this.y*=-1;this.z*=-1;return this},lengthSq:function(){return this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w},length:function(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w)},normalize:function(){var a=this.length();0===a?(this.z=this.y=this.x=0,this.w=1):(a=1/a,this.x*=a,this.y*=a,this.z*=a,this.w*=a);return this},multiply:function(a,b){return void 0!==b?(console.warn("DEPRECATED: Quaternion's .multiply() now only accepts one argument. Use .multiplyQuaternions( a, b ) instead."),
-this.multiplyQuaternions(a,b)):this.multiplyQuaternions(this,a)},multiplyQuaternions:function(a,b){var c=a.x,d=a.y,e=a.z,f=a.w,g=b.x,h=b.y,i=b.z,k=b.w;this.x=c*k+f*g+d*i-e*h;this.y=d*k+f*h+e*g-c*i;this.z=e*k+f*i+c*h-d*g;this.w=f*k-c*g-d*h-e*i;return this},multiplyVector3:function(a){console.warn("DEPRECATED: Quaternion's .multiplyVector3() has been removed. Use is now vector.applyQuaternion( quaternion ) instead.");return a.applyQuaternion(this)},slerp:function(a,b){var c=this.x,d=this.y,e=this.z,
+this.multiplyQuaternions(a,b)):this.multiplyQuaternions(this,a)},multiplyQuaternions:function(a,b){var c=a.x,d=a.y,e=a.z,f=a.w,g=b.x,h=b.y,i=b.z,j=b.w;this.x=c*j+f*g+d*i-e*h;this.y=d*j+f*h+e*g-c*i;this.z=e*j+f*i+c*h-d*g;this.w=f*j-c*g-d*h-e*i;return this},multiplyVector3:function(a){console.warn("DEPRECATED: Quaternion's .multiplyVector3() has been removed. Use is now vector.applyQuaternion( quaternion ) instead.");return a.applyQuaternion(this)},slerp:function(a,b){var c=this.x,d=this.y,e=this.z,
 f=this.w,g=f*a.w+c*a.x+d*a.y+e*a.z;0>g?(this.w=-a.w,this.x=-a.x,this.y=-a.y,this.z=-a.z,g=-g):this.copy(a);if(1<=g)return this.w=f,this.x=c,this.y=d,this.z=e,this;var h=Math.acos(g),i=Math.sqrt(1-g*g);if(0.001>Math.abs(i))return this.w=0.5*(f+this.w),this.x=0.5*(c+this.x),this.y=0.5*(d+this.y),this.z=0.5*(e+this.z),this;g=Math.sin((1-b)*h)/i;h=Math.sin(b*h)/i;this.w=f*g+this.w*h;this.x=c*g+this.x*h;this.y=d*g+this.y*h;this.z=e*g+this.z*h;return this},equals:function(a){return a.x===this.x&&a.y===
 f=this.w,g=f*a.w+c*a.x+d*a.y+e*a.z;0>g?(this.w=-a.w,this.x=-a.x,this.y=-a.y,this.z=-a.z,g=-g):this.copy(a);if(1<=g)return this.w=f,this.x=c,this.y=d,this.z=e,this;var h=Math.acos(g),i=Math.sqrt(1-g*g);if(0.001>Math.abs(i))return this.w=0.5*(f+this.w),this.x=0.5*(c+this.x),this.y=0.5*(d+this.y),this.z=0.5*(e+this.z),this;g=Math.sin((1-b)*h)/i;h=Math.sin(b*h)/i;this.w=f*g+this.w*h;this.x=c*g+this.x*h;this.y=d*g+this.y*h;this.z=e*g+this.z*h;return this},equals:function(a){return a.x===this.x&&a.y===
 this.y&&a.z===this.z&&a.w===this.w},clone:function(){return new THREE.Quaternion(this.x,this.y,this.z,this.w)}});THREE.Quaternion.slerp=function(a,b,c,d){return c.copy(a).slerp(b,d)};THREE.Vector2=function(a,b){this.x=a||0;this.y=b||0};
 this.y&&a.z===this.z&&a.w===this.w},clone:function(){return new THREE.Quaternion(this.x,this.y,this.z,this.w)}});THREE.Quaternion.slerp=function(a,b,c,d){return c.copy(a).slerp(b,d)};THREE.Vector2=function(a,b){this.x=a||0;this.y=b||0};
 THREE.extend(THREE.Vector2.prototype,{set:function(a,b){this.x=a;this.y=b;return this},setX:function(a){this.x=a;return this},setY:function(a){this.y=a;return this},setComponent:function(a,b){switch(a){case 0:this.x=b;break;case 1:this.y=b;break;default:throw Error("index is out of range: "+a);}},getComponent:function(a){switch(a){case 0:return this.x;case 1:return this.y;default:throw Error("index is out of range: "+a);}},copy:function(a){this.x=a.x;this.y=a.y;return this},add:function(a,b){if(void 0!==
 THREE.extend(THREE.Vector2.prototype,{set:function(a,b){this.x=a;this.y=b;return this},setX:function(a){this.x=a;return this},setY:function(a){this.y=a;return this},setComponent:function(a,b){switch(a){case 0:this.x=b;break;case 1:this.y=b;break;default:throw Error("index is out of range: "+a);}},getComponent:function(a){switch(a){case 0:return this.x;case 1:return this.y;default:throw Error("index is out of range: "+a);}},copy:function(a){this.x=a.x;this.y=a.y;return this},add:function(a,b){if(void 0!==
@@ -36,14 +36,14 @@ THREE.extend(THREE.Vector3.prototype,{set:function(a,b,c){this.x=a;this.y=b;this
 a);}},copy:function(a){this.x=a.x;this.y=a.y;this.z=a.z;return this},add:function(a,b){if(void 0!==b)return console.warn("DEPRECATED: Vector3's .add() now only accepts one argument. Use .addVectors( a, b ) instead."),this.addVectors(a,b);this.x+=a.x;this.y+=a.y;this.z+=a.z;return this},addScalar:function(a){this.x+=a;this.y+=a;this.z+=a;return this},addVectors:function(a,b){this.x=a.x+b.x;this.y=a.y+b.y;this.z=a.z+b.z;return this},sub:function(a,b){if(void 0!==b)return console.warn("DEPRECATED: Vector3's .sub() now only accepts one argument. Use .subVectors( a, b ) instead."),
 a);}},copy:function(a){this.x=a.x;this.y=a.y;this.z=a.z;return this},add:function(a,b){if(void 0!==b)return console.warn("DEPRECATED: Vector3's .add() now only accepts one argument. Use .addVectors( a, b ) instead."),this.addVectors(a,b);this.x+=a.x;this.y+=a.y;this.z+=a.z;return this},addScalar:function(a){this.x+=a;this.y+=a;this.z+=a;return this},addVectors:function(a,b){this.x=a.x+b.x;this.y=a.y+b.y;this.z=a.z+b.z;return this},sub:function(a,b){if(void 0!==b)return console.warn("DEPRECATED: Vector3's .sub() now only accepts one argument. Use .subVectors( a, b ) instead."),
 this.subVectors(a,b);this.x-=a.x;this.y-=a.y;this.z-=a.z;return this},subVectors:function(a,b){this.x=a.x-b.x;this.y=a.y-b.y;this.z=a.z-b.z;return this},multiply:function(a,b){if(void 0!==b)return console.warn("DEPRECATED: Vector3's .multiply() now only accepts one argument. Use .multiplyVectors( a, b ) instead."),this.multiplyVectors(a,b);this.x*=a.x;this.y*=a.y;this.z*=a.z;return this},multiplyScalar:function(a){this.x*=a;this.y*=a;this.z*=a;return this},multiplyVectors:function(a,b){this.x=a.x*
 this.subVectors(a,b);this.x-=a.x;this.y-=a.y;this.z-=a.z;return this},subVectors:function(a,b){this.x=a.x-b.x;this.y=a.y-b.y;this.z=a.z-b.z;return this},multiply:function(a,b){if(void 0!==b)return console.warn("DEPRECATED: Vector3's .multiply() now only accepts one argument. Use .multiplyVectors( a, b ) instead."),this.multiplyVectors(a,b);this.x*=a.x;this.y*=a.y;this.z*=a.z;return this},multiplyScalar:function(a){this.x*=a;this.y*=a;this.z*=a;return this},multiplyVectors:function(a,b){this.x=a.x*
 b.x;this.y=a.y*b.y;this.z=a.z*b.z;return this},applyMatrix3:function(a){var b=this.x,c=this.y,d=this.z,a=a.elements;this.x=a[0]*b+a[3]*c+a[6]*d;this.y=a[1]*b+a[4]*c+a[7]*d;this.z=a[2]*b+a[5]*c+a[8]*d;return this},applyMatrix4:function(a){var b=this.x,c=this.y,d=this.z,a=a.elements;this.x=a[0]*b+a[4]*c+a[8]*d+a[12];this.y=a[1]*b+a[5]*c+a[9]*d+a[13];this.z=a[2]*b+a[6]*c+a[10]*d+a[14];return this},applyProjection:function(a){var b=this.x,c=this.y,d=this.z,a=a.elements,e=1/(a[3]*b+a[7]*c+a[11]*d+a[15]);
 b.x;this.y=a.y*b.y;this.z=a.z*b.z;return this},applyMatrix3:function(a){var b=this.x,c=this.y,d=this.z,a=a.elements;this.x=a[0]*b+a[3]*c+a[6]*d;this.y=a[1]*b+a[4]*c+a[7]*d;this.z=a[2]*b+a[5]*c+a[8]*d;return this},applyMatrix4:function(a){var b=this.x,c=this.y,d=this.z,a=a.elements;this.x=a[0]*b+a[4]*c+a[8]*d+a[12];this.y=a[1]*b+a[5]*c+a[9]*d+a[13];this.z=a[2]*b+a[6]*c+a[10]*d+a[14];return this},applyProjection:function(a){var b=this.x,c=this.y,d=this.z,a=a.elements,e=1/(a[3]*b+a[7]*c+a[11]*d+a[15]);
-this.x=(a[0]*b+a[4]*c+a[8]*d+a[12])*e;this.y=(a[1]*b+a[5]*c+a[9]*d+a[13])*e;this.z=(a[2]*b+a[6]*c+a[10]*d+a[14])*e;return this},applyQuaternion:function(a){var b=this.x,c=this.y,d=this.z,e=a.x,f=a.y,g=a.z,a=a.w,h=a*b+f*d-g*c,i=a*c+g*b-e*d,k=a*d+e*c-f*b,b=-e*b-f*c-g*d;this.x=h*a+b*-e+i*-g-k*-f;this.y=i*a+b*-f+k*-e-h*-g;this.z=k*a+b*-g+h*-f-i*-e;return this},applyEuler:function(){var a=new THREE.Quaternion;return function(b,c){var d=a.setFromEuler(b,c);this.applyQuaternion(d);return this}}(),applyAxisAngle:function(){var a=
+this.x=(a[0]*b+a[4]*c+a[8]*d+a[12])*e;this.y=(a[1]*b+a[5]*c+a[9]*d+a[13])*e;this.z=(a[2]*b+a[6]*c+a[10]*d+a[14])*e;return this},applyQuaternion:function(a){var b=this.x,c=this.y,d=this.z,e=a.x,f=a.y,g=a.z,a=a.w,h=a*b+f*d-g*c,i=a*c+g*b-e*d,j=a*d+e*c-f*b,b=-e*b-f*c-g*d;this.x=h*a+b*-e+i*-g-j*-f;this.y=i*a+b*-f+j*-e-h*-g;this.z=j*a+b*-g+h*-f-i*-e;return this},applyEuler:function(){var a=new THREE.Quaternion;return function(b,c){var d=a.setFromEuler(b,c);this.applyQuaternion(d);return this}}(),applyAxisAngle:function(){var a=
 new THREE.Quaternion;return function(b,c){var d=a.setFromAxisAngle(b,c);this.applyQuaternion(d);return this}}(),transformDirection:function(a){var b=this.x,c=this.y,d=this.z,a=a.elements;this.x=a[0]*b+a[4]*c+a[8]*d;this.y=a[1]*b+a[5]*c+a[9]*d;this.z=a[2]*b+a[6]*c+a[10]*d;this.normalize();return this},divide:function(a){this.x/=a.x;this.y/=a.y;this.z/=a.z;return this},divideScalar:function(a){0!==a?(this.x/=a,this.y/=a,this.z/=a):this.z=this.y=this.x=0;return this},min:function(a){this.x>a.x&&(this.x=
 new THREE.Quaternion;return function(b,c){var d=a.setFromAxisAngle(b,c);this.applyQuaternion(d);return this}}(),transformDirection:function(a){var b=this.x,c=this.y,d=this.z,a=a.elements;this.x=a[0]*b+a[4]*c+a[8]*d;this.y=a[1]*b+a[5]*c+a[9]*d;this.z=a[2]*b+a[6]*c+a[10]*d;this.normalize();return this},divide:function(a){this.x/=a.x;this.y/=a.y;this.z/=a.z;return this},divideScalar:function(a){0!==a?(this.x/=a,this.y/=a,this.z/=a):this.z=this.y=this.x=0;return this},min:function(a){this.x>a.x&&(this.x=
 a.x);this.y>a.y&&(this.y=a.y);this.z>a.z&&(this.z=a.z);return this},max:function(a){this.x<a.x&&(this.x=a.x);this.y<a.y&&(this.y=a.y);this.z<a.z&&(this.z=a.z);return this},clamp:function(a,b){this.x<a.x?this.x=a.x:this.x>b.x&&(this.x=b.x);this.y<a.y?this.y=a.y:this.y>b.y&&(this.y=b.y);this.z<a.z?this.z=a.z:this.z>b.z&&(this.z=b.z);return this},negate:function(){return this.multiplyScalar(-1)},dot:function(a){return this.x*a.x+this.y*a.y+this.z*a.z},lengthSq:function(){return this.x*this.x+this.y*
 a.x);this.y>a.y&&(this.y=a.y);this.z>a.z&&(this.z=a.z);return this},max:function(a){this.x<a.x&&(this.x=a.x);this.y<a.y&&(this.y=a.y);this.z<a.z&&(this.z=a.z);return this},clamp:function(a,b){this.x<a.x?this.x=a.x:this.x>b.x&&(this.x=b.x);this.y<a.y?this.y=a.y:this.y>b.y&&(this.y=b.y);this.z<a.z?this.z=a.z:this.z>b.z&&(this.z=b.z);return this},negate:function(){return this.multiplyScalar(-1)},dot:function(a){return this.x*a.x+this.y*a.y+this.z*a.z},lengthSq:function(){return this.x*this.x+this.y*
 this.y+this.z*this.z},length:function(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z)},lengthManhattan:function(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)},normalize:function(){return this.divideScalar(this.length())},setLength:function(a){var b=this.length();0!==b&&a!==b&&this.multiplyScalar(a/b);return this},lerp:function(a,b){this.x+=(a.x-this.x)*b;this.y+=(a.y-this.y)*b;this.z+=(a.z-this.z)*b;return this},cross:function(a,b){if(void 0!==b)return console.warn("DEPRECATED: Vector3's .cross() now only accepts one argument. Use .crossVectors( a, b ) instead."),
 this.y+this.z*this.z},length:function(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z)},lengthManhattan:function(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)},normalize:function(){return this.divideScalar(this.length())},setLength:function(a){var b=this.length();0!==b&&a!==b&&this.multiplyScalar(a/b);return this},lerp:function(a,b){this.x+=(a.x-this.x)*b;this.y+=(a.y-this.y)*b;this.z+=(a.z-this.z)*b;return this},cross:function(a,b){if(void 0!==b)return console.warn("DEPRECATED: Vector3's .cross() now only accepts one argument. Use .crossVectors( a, b ) instead."),
 this.crossVectors(a,b);var c=this.x,d=this.y,e=this.z;this.x=d*a.z-e*a.y;this.y=e*a.x-c*a.z;this.z=c*a.y-d*a.x;return this},crossVectors:function(a,b){this.x=a.y*b.z-a.z*b.y;this.y=a.z*b.x-a.x*b.z;this.z=a.x*b.y-a.y*b.x;return this},projectOnVector:function(){var a=new THREE.Vector3;return function(b){a.copy(b).normalize();b=this.dot(a);return this.copy(a).multiplyScalar(b)}}(),projectOnPlane:function(){var a=new THREE.Vector3;return function(b){a.copy(this).projectOnVector(b);return this.sub(a)}}(),
 this.crossVectors(a,b);var c=this.x,d=this.y,e=this.z;this.x=d*a.z-e*a.y;this.y=e*a.x-c*a.z;this.z=c*a.y-d*a.x;return this},crossVectors:function(a,b){this.x=a.y*b.z-a.z*b.y;this.y=a.z*b.x-a.x*b.z;this.z=a.x*b.y-a.y*b.x;return this},projectOnVector:function(){var a=new THREE.Vector3;return function(b){a.copy(b).normalize();b=this.dot(a);return this.copy(a).multiplyScalar(b)}}(),projectOnPlane:function(){var a=new THREE.Vector3;return function(b){a.copy(this).projectOnVector(b);return this.sub(a)}}(),
 reflect:function(){var a=new THREE.Vector3;return function(b){a.copy(this).projectOnVector(b).multiplyScalar(2);return this.subVectors(a,this)}}(),angleTo:function(a){a=this.dot(a)/(this.length()*a.length());return Math.acos(THREE.Math.clamp(a,-1,1))},distanceTo:function(a){return Math.sqrt(this.distanceToSquared(a))},distanceToSquared:function(a){var b=this.x-a.x,c=this.y-a.y,a=this.z-a.z;return b*b+c*c+a*a},setEulerFromRotationMatrix:function(a,b){function c(a){return Math.min(Math.max(a,-1),1)}
 reflect:function(){var a=new THREE.Vector3;return function(b){a.copy(this).projectOnVector(b).multiplyScalar(2);return this.subVectors(a,this)}}(),angleTo:function(a){a=this.dot(a)/(this.length()*a.length());return Math.acos(THREE.Math.clamp(a,-1,1))},distanceTo:function(a){return Math.sqrt(this.distanceToSquared(a))},distanceToSquared:function(a){var b=this.x-a.x,c=this.y-a.y,a=this.z-a.z;return b*b+c*c+a*a},setEulerFromRotationMatrix:function(a,b){function c(a){return Math.min(Math.max(a,-1),1)}
-var d=a.elements,e=d[0],f=d[4],g=d[8],h=d[1],i=d[5],k=d[9],l=d[2],n=d[6],d=d[10];void 0===b||"XYZ"===b?(this.y=Math.asin(c(g)),0.99999>Math.abs(g)?(this.x=Math.atan2(-k,d),this.z=Math.atan2(-f,e)):(this.x=Math.atan2(n,i),this.z=0)):"YXZ"===b?(this.x=Math.asin(-c(k)),0.99999>Math.abs(k)?(this.y=Math.atan2(g,d),this.z=Math.atan2(h,i)):(this.y=Math.atan2(-l,e),this.z=0)):"ZXY"===b?(this.x=Math.asin(c(n)),0.99999>Math.abs(n)?(this.y=Math.atan2(-l,d),this.z=Math.atan2(-f,i)):(this.y=0,this.z=Math.atan2(h,
-e))):"ZYX"===b?(this.y=Math.asin(-c(l)),0.99999>Math.abs(l)?(this.x=Math.atan2(n,d),this.z=Math.atan2(h,e)):(this.x=0,this.z=Math.atan2(-f,i))):"YZX"===b?(this.z=Math.asin(c(h)),0.99999>Math.abs(h)?(this.x=Math.atan2(-k,i),this.y=Math.atan2(-l,e)):(this.x=0,this.y=Math.atan2(g,d))):"XZY"===b&&(this.z=Math.asin(-c(f)),0.99999>Math.abs(f)?(this.x=Math.atan2(n,i),this.y=Math.atan2(g,e)):(this.x=Math.atan2(-k,d),this.y=0));return this},setEulerFromQuaternion:function(a,b){function c(a){return Math.min(Math.max(a,
+var d=a.elements,e=d[0],f=d[4],g=d[8],h=d[1],i=d[5],j=d[9],l=d[2],n=d[6],d=d[10];void 0===b||"XYZ"===b?(this.y=Math.asin(c(g)),0.99999>Math.abs(g)?(this.x=Math.atan2(-j,d),this.z=Math.atan2(-f,e)):(this.x=Math.atan2(n,i),this.z=0)):"YXZ"===b?(this.x=Math.asin(-c(j)),0.99999>Math.abs(j)?(this.y=Math.atan2(g,d),this.z=Math.atan2(h,i)):(this.y=Math.atan2(-l,e),this.z=0)):"ZXY"===b?(this.x=Math.asin(c(n)),0.99999>Math.abs(n)?(this.y=Math.atan2(-l,d),this.z=Math.atan2(-f,i)):(this.y=0,this.z=Math.atan2(h,
+e))):"ZYX"===b?(this.y=Math.asin(-c(l)),0.99999>Math.abs(l)?(this.x=Math.atan2(n,d),this.z=Math.atan2(h,e)):(this.x=0,this.z=Math.atan2(-f,i))):"YZX"===b?(this.z=Math.asin(c(h)),0.99999>Math.abs(h)?(this.x=Math.atan2(-j,i),this.y=Math.atan2(-l,e)):(this.x=0,this.y=Math.atan2(g,d))):"XZY"===b&&(this.z=Math.asin(-c(f)),0.99999>Math.abs(f)?(this.x=Math.atan2(n,i),this.y=Math.atan2(g,e)):(this.x=Math.atan2(-j,d),this.y=0));return this},setEulerFromQuaternion:function(a,b){function c(a){return Math.min(Math.max(a,
 -1),1)}var d=a.x*a.x,e=a.y*a.y,f=a.z*a.z,g=a.w*a.w;void 0===b||"XYZ"===b?(this.x=Math.atan2(2*(a.x*a.w-a.y*a.z),g-d-e+f),this.y=Math.asin(c(2*(a.x*a.z+a.y*a.w))),this.z=Math.atan2(2*(a.z*a.w-a.x*a.y),g+d-e-f)):"YXZ"===b?(this.x=Math.asin(c(2*(a.x*a.w-a.y*a.z))),this.y=Math.atan2(2*(a.x*a.z+a.y*a.w),g-d-e+f),this.z=Math.atan2(2*(a.x*a.y+a.z*a.w),g-d+e-f)):"ZXY"===b?(this.x=Math.asin(c(2*(a.x*a.w+a.y*a.z))),this.y=Math.atan2(2*(a.y*a.w-a.z*a.x),g-d-e+f),this.z=Math.atan2(2*(a.z*a.w-a.x*a.y),g-d+e-f)):
 -1),1)}var d=a.x*a.x,e=a.y*a.y,f=a.z*a.z,g=a.w*a.w;void 0===b||"XYZ"===b?(this.x=Math.atan2(2*(a.x*a.w-a.y*a.z),g-d-e+f),this.y=Math.asin(c(2*(a.x*a.z+a.y*a.w))),this.z=Math.atan2(2*(a.z*a.w-a.x*a.y),g+d-e-f)):"YXZ"===b?(this.x=Math.asin(c(2*(a.x*a.w-a.y*a.z))),this.y=Math.atan2(2*(a.x*a.z+a.y*a.w),g-d-e+f),this.z=Math.atan2(2*(a.x*a.y+a.z*a.w),g-d+e-f)):"ZXY"===b?(this.x=Math.asin(c(2*(a.x*a.w+a.y*a.z))),this.y=Math.atan2(2*(a.y*a.w-a.z*a.x),g-d-e+f),this.z=Math.atan2(2*(a.z*a.w-a.x*a.y),g-d+e-f)):
 "ZYX"===b?(this.x=Math.atan2(2*(a.x*a.w+a.z*a.y),g-d-e+f),this.y=Math.asin(c(2*(a.y*a.w-a.x*a.z))),this.z=Math.atan2(2*(a.x*a.y+a.z*a.w),g+d-e-f)):"YZX"===b?(this.x=Math.atan2(2*(a.x*a.w-a.z*a.y),g-d+e-f),this.y=Math.atan2(2*(a.y*a.w-a.x*a.z),g+d-e-f),this.z=Math.asin(c(2*(a.x*a.y+a.z*a.w)))):"XZY"===b&&(this.x=Math.atan2(2*(a.x*a.w+a.y*a.z),g-d+e-f),this.y=Math.atan2(2*(a.x*a.z+a.y*a.w),g+d-e-f),this.z=Math.asin(c(2*(a.z*a.w-a.x*a.y))));return this},getPositionFromMatrix:function(a){this.x=a.elements[12];
 "ZYX"===b?(this.x=Math.atan2(2*(a.x*a.w+a.z*a.y),g-d-e+f),this.y=Math.asin(c(2*(a.y*a.w-a.x*a.z))),this.z=Math.atan2(2*(a.x*a.y+a.z*a.w),g+d-e-f)):"YZX"===b?(this.x=Math.atan2(2*(a.x*a.w-a.z*a.y),g-d+e-f),this.y=Math.atan2(2*(a.y*a.w-a.x*a.z),g+d-e-f),this.z=Math.asin(c(2*(a.x*a.y+a.z*a.w)))):"XZY"===b&&(this.x=Math.atan2(2*(a.x*a.w+a.y*a.z),g-d+e-f),this.y=Math.atan2(2*(a.x*a.z+a.y*a.w),g+d-e-f),this.z=Math.asin(c(2*(a.z*a.w-a.x*a.y))));return this},getPositionFromMatrix:function(a){this.x=a.elements[12];
 this.y=a.elements[13];this.z=a.elements[14];return this},getScaleFromMatrix:function(a){var b=this.set(a.elements[0],a.elements[1],a.elements[2]).length(),c=this.set(a.elements[4],a.elements[5],a.elements[6]).length(),a=this.set(a.elements[8],a.elements[9],a.elements[10]).length();this.x=b;this.y=c;this.z=a;return this},getColumnFromMatrix:function(a,b){var c=4*a,d=b.elements;this.x=d[c];this.y=d[c+1];this.z=d[c+2];return this},equals:function(a){return a.x===this.x&&a.y===this.y&&a.z===this.z},toArray:function(){return[this.x,
 this.y=a.elements[13];this.z=a.elements[14];return this},getScaleFromMatrix:function(a){var b=this.set(a.elements[0],a.elements[1],a.elements[2]).length(),c=this.set(a.elements[4],a.elements[5],a.elements[6]).length(),a=this.set(a.elements[8],a.elements[9],a.elements[10]).length();this.x=b;this.y=c;this.z=a;return this},getColumnFromMatrix:function(a,b){var c=4*a,d=b.elements;this.x=d[c];this.y=d[c+1];this.z=d[c+2];return this},equals:function(a){return a.x===this.x&&a.y===this.y&&a.z===this.z},toArray:function(){return[this.x,
@@ -52,14 +52,11 @@ THREE.extend(THREE.Vector4.prototype,{set:function(a,b,c,d){this.x=a;this.y=b;th
 case 2:return this.z;case 3:return this.w;default:throw Error("index is out of range: "+a);}},copy:function(a){this.x=a.x;this.y=a.y;this.z=a.z;this.w=void 0!==a.w?a.w:1;return this},add:function(a,b){if(void 0!==b)return console.warn("DEPRECATED: Vector4's .add() now only accepts one argument. Use .addVectors( a, b ) instead."),this.addVectors(a,b);this.x+=a.x;this.y+=a.y;this.z+=a.z;this.w+=a.w;return this},addScalar:function(a){this.x+=a;this.y+=a;this.z+=a;this.w+=a;return this},addVectors:function(a,
 case 2:return this.z;case 3:return this.w;default:throw Error("index is out of range: "+a);}},copy:function(a){this.x=a.x;this.y=a.y;this.z=a.z;this.w=void 0!==a.w?a.w:1;return this},add:function(a,b){if(void 0!==b)return console.warn("DEPRECATED: Vector4's .add() now only accepts one argument. Use .addVectors( a, b ) instead."),this.addVectors(a,b);this.x+=a.x;this.y+=a.y;this.z+=a.z;this.w+=a.w;return this},addScalar:function(a){this.x+=a;this.y+=a;this.z+=a;this.w+=a;return this},addVectors:function(a,
 b){this.x=a.x+b.x;this.y=a.y+b.y;this.z=a.z+b.z;this.w=a.w+b.w;return this},sub:function(a,b){if(void 0!==b)return console.warn("DEPRECATED: Vector4's .sub() now only accepts one argument. Use .subVectors( a, b ) instead."),this.subVectors(a,b);this.x-=a.x;this.y-=a.y;this.z-=a.z;this.w-=a.w;return this},subVectors:function(a,b){this.x=a.x-b.x;this.y=a.y-b.y;this.z=a.z-b.z;this.w=a.w-b.w;return this},multiplyScalar:function(a){this.x*=a;this.y*=a;this.z*=a;this.w*=a;return this},applyMatrix4:function(a){var b=
 b){this.x=a.x+b.x;this.y=a.y+b.y;this.z=a.z+b.z;this.w=a.w+b.w;return this},sub:function(a,b){if(void 0!==b)return console.warn("DEPRECATED: Vector4's .sub() now only accepts one argument. Use .subVectors( a, b ) instead."),this.subVectors(a,b);this.x-=a.x;this.y-=a.y;this.z-=a.z;this.w-=a.w;return this},subVectors:function(a,b){this.x=a.x-b.x;this.y=a.y-b.y;this.z=a.z-b.z;this.w=a.w-b.w;return this},multiplyScalar:function(a){this.x*=a;this.y*=a;this.z*=a;this.w*=a;return this},applyMatrix4:function(a){var b=
 this.x,c=this.y,d=this.z,e=this.w,a=a.elements;this.x=a[0]*b+a[4]*c+a[8]*d+a[12]*e;this.y=a[1]*b+a[5]*c+a[9]*d+a[13]*e;this.z=a[2]*b+a[6]*c+a[10]*d+a[14]*e;this.w=a[3]*b+a[7]*c+a[11]*d+a[15]*e;return this},divideScalar:function(a){0!==a?(this.x/=a,this.y/=a,this.z/=a,this.w/=a):(this.z=this.y=this.x=0,this.w=1);return this},setAxisAngleFromQuaternion:function(a){this.w=2*Math.acos(a.w);var b=Math.sqrt(1-a.w*a.w);1E-4>b?(this.x=1,this.z=this.y=0):(this.x=a.x/b,this.y=a.y/b,this.z=a.z/b);return this},
 this.x,c=this.y,d=this.z,e=this.w,a=a.elements;this.x=a[0]*b+a[4]*c+a[8]*d+a[12]*e;this.y=a[1]*b+a[5]*c+a[9]*d+a[13]*e;this.z=a[2]*b+a[6]*c+a[10]*d+a[14]*e;this.w=a[3]*b+a[7]*c+a[11]*d+a[15]*e;return this},divideScalar:function(a){0!==a?(this.x/=a,this.y/=a,this.z/=a,this.w/=a):(this.z=this.y=this.x=0,this.w=1);return this},setAxisAngleFromQuaternion:function(a){this.w=2*Math.acos(a.w);var b=Math.sqrt(1-a.w*a.w);1E-4>b?(this.x=1,this.z=this.y=0):(this.x=a.x/b,this.y=a.y/b,this.z=a.z/b);return this},
-setAxisAngleFromRotationMatrix:function(a){var b,c,d,a=a.elements,e=a[0];d=a[4];var f=a[8],g=a[1],h=a[5],i=a[9];c=a[2];b=a[6];var k=a[10];if(0.01>Math.abs(d-g)&&0.01>Math.abs(f-c)&&0.01>Math.abs(i-b)){if(0.1>Math.abs(d+g)&&0.1>Math.abs(f+c)&&0.1>Math.abs(i+b)&&0.1>Math.abs(e+h+k-3))return this.set(1,0,0,0),this;a=Math.PI;e=(e+1)/2;h=(h+1)/2;k=(k+1)/2;d=(d+g)/4;f=(f+c)/4;i=(i+b)/4;e>h&&e>k?0.01>e?(b=0,d=c=0.707106781):(b=Math.sqrt(e),c=d/b,d=f/b):h>k?0.01>h?(b=0.707106781,c=0,d=0.707106781):(c=Math.sqrt(h),
-b=d/c,d=i/c):0.01>k?(c=b=0.707106781,d=0):(d=Math.sqrt(k),b=f/d,c=i/d);this.set(b,c,d,a);return this}a=Math.sqrt((b-i)*(b-i)+(f-c)*(f-c)+(g-d)*(g-d));0.001>Math.abs(a)&&(a=1);this.x=(b-i)/a;this.y=(f-c)/a;this.z=(g-d)/a;this.w=Math.acos((e+h+k-1)/2);return this},min:function(a){this.x>a.x&&(this.x=a.x);this.y>a.y&&(this.y=a.y);this.z>a.z&&(this.z=a.z);this.w>a.w&&(this.w=a.w);return this},max:function(a){this.x<a.x&&(this.x=a.x);this.y<a.y&&(this.y=a.y);this.z<a.z&&(this.z=a.z);this.w<a.w&&(this.w=
+setAxisAngleFromRotationMatrix:function(a){var b,c,d,a=a.elements,e=a[0];d=a[4];var f=a[8],g=a[1],h=a[5],i=a[9];c=a[2];b=a[6];var j=a[10];if(0.01>Math.abs(d-g)&&0.01>Math.abs(f-c)&&0.01>Math.abs(i-b)){if(0.1>Math.abs(d+g)&&0.1>Math.abs(f+c)&&0.1>Math.abs(i+b)&&0.1>Math.abs(e+h+j-3))return this.set(1,0,0,0),this;a=Math.PI;e=(e+1)/2;h=(h+1)/2;j=(j+1)/2;d=(d+g)/4;f=(f+c)/4;i=(i+b)/4;e>h&&e>j?0.01>e?(b=0,d=c=0.707106781):(b=Math.sqrt(e),c=d/b,d=f/b):h>j?0.01>h?(b=0.707106781,c=0,d=0.707106781):(c=Math.sqrt(h),
+b=d/c,d=i/c):0.01>j?(c=b=0.707106781,d=0):(d=Math.sqrt(j),b=f/d,c=i/d);this.set(b,c,d,a);return this}a=Math.sqrt((b-i)*(b-i)+(f-c)*(f-c)+(g-d)*(g-d));0.001>Math.abs(a)&&(a=1);this.x=(b-i)/a;this.y=(f-c)/a;this.z=(g-d)/a;this.w=Math.acos((e+h+j-1)/2);return this},min:function(a){this.x>a.x&&(this.x=a.x);this.y>a.y&&(this.y=a.y);this.z>a.z&&(this.z=a.z);this.w>a.w&&(this.w=a.w);return this},max:function(a){this.x<a.x&&(this.x=a.x);this.y<a.y&&(this.y=a.y);this.z<a.z&&(this.z=a.z);this.w<a.w&&(this.w=
 a.w);return this},clamp:function(a,b){this.x<a.x?this.x=a.x:this.x>b.x&&(this.x=b.x);this.y<a.y?this.y=a.y:this.y>b.y&&(this.y=b.y);this.z<a.z?this.z=a.z:this.z>b.z&&(this.z=b.z);this.w<a.w?this.w=a.w:this.w>b.w&&(this.w=b.w);return this},negate:function(){return this.multiplyScalar(-1)},dot:function(a){return this.x*a.x+this.y*a.y+this.z*a.z+this.w*a.w},lengthSq:function(){return this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w},length:function(){return Math.sqrt(this.x*this.x+this.y*this.y+
 a.w);return this},clamp:function(a,b){this.x<a.x?this.x=a.x:this.x>b.x&&(this.x=b.x);this.y<a.y?this.y=a.y:this.y>b.y&&(this.y=b.y);this.z<a.z?this.z=a.z:this.z>b.z&&(this.z=b.z);this.w<a.w?this.w=a.w:this.w>b.w&&(this.w=b.w);return this},negate:function(){return this.multiplyScalar(-1)},dot:function(a){return this.x*a.x+this.y*a.y+this.z*a.z+this.w*a.w},lengthSq:function(){return this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w},length:function(){return Math.sqrt(this.x*this.x+this.y*this.y+
 this.z*this.z+this.w*this.w)},lengthManhattan:function(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)+Math.abs(this.w)},normalize:function(){return this.divideScalar(this.length())},setLength:function(a){var b=this.length();0!==b&&a!==b&&this.multiplyScalar(a/b);return this},lerp:function(a,b){this.x+=(a.x-this.x)*b;this.y+=(a.y-this.y)*b;this.z+=(a.z-this.z)*b;this.w+=(a.w-this.w)*b;return this},equals:function(a){return a.x===this.x&&a.y===this.y&&a.z===this.z&&a.w===this.w},toArray:function(){return[this.x,
 this.z*this.z+this.w*this.w)},lengthManhattan:function(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)+Math.abs(this.w)},normalize:function(){return this.divideScalar(this.length())},setLength:function(a){var b=this.length();0!==b&&a!==b&&this.multiplyScalar(a/b);return this},lerp:function(a,b){this.x+=(a.x-this.x)*b;this.y+=(a.y-this.y)*b;this.z+=(a.z-this.z)*b;this.w+=(a.w-this.w)*b;return this},equals:function(a){return a.x===this.x&&a.y===this.y&&a.z===this.z&&a.w===this.w},toArray:function(){return[this.x,
-this.y,this.z,this.w]},clone:function(){return new THREE.Vector4(this.x,this.y,this.z,this.w)}});THREE.Line3=function(a,b){this.start=void 0!==a?a:new THREE.Vector3;this.end=void 0!==b?b:new THREE.Vector3};
-THREE.extend(THREE.Line3.prototype,{set:function(a,b){this.start.copy(a);this.end.copy(b);return this},copy:function(a){this.start.copy(a.start);this.end.copy(a.end);return this},center:function(a){return(a||new THREE.Vector3).addVectors(this.start,this.end).multiplyScalar(0.5)},delta:function(a){return(a||new THREE.Vector3).subVectors(this.end,this.start)},distanceSq:function(){return this.start.distanceToSquared(this.end)},distance:function(){return this.start.distanceTo(this.end)},at:function(a,
-b){var c=b||new THREE.Vector3;return this.delta(c).multiplyScalar(a).add(this.start)},closestPointToPointParameter:function(){var a=new THREE.Vector3,b=new THREE.Vector3;return function(c,d){a.subVectors(c,this.start);b.subVectors(this.end,this.start);var e=b.dot(b),e=b.dot(a)/e;d&&(e=THREE.Math.clamp(e,0,1));return e}}(),closestPointToPoint:function(a,b,c){a=this.closestPointToPointParameter(a,b);c=c||new THREE.Vector3;return this.delta(c).multiplyScalar(a).add(this.start)},applyMatrix4:function(a){this.start.applyMatrix4(a);
-this.end.applyMatrix4(a);return this},equals:function(a){return a.start.equals(this.start)&&a.end.equals(this.end)},clone:function(){return(new THREE.Line3).copy(this)}});THREE.Box2=function(a,b){this.min=void 0!==a?a:new THREE.Vector2(Infinity,Infinity);this.max=void 0!==b?b:new THREE.Vector2(-Infinity,-Infinity)};
+this.y,this.z,this.w]},clone:function(){return new THREE.Vector4(this.x,this.y,this.z,this.w)}});THREE.Box2=function(a,b){this.min=void 0!==a?a:new THREE.Vector2(Infinity,Infinity);this.max=void 0!==b?b:new THREE.Vector2(-Infinity,-Infinity)};
 THREE.extend(THREE.Box2.prototype,{set:function(a,b){this.min.copy(a);this.max.copy(b);return this},setFromPoints:function(a){if(0<a.length){var b=a[0];this.min.copy(b);this.max.copy(b);for(var c=1,d=a.length;c<d;c++)b=a[c],b.x<this.min.x?this.min.x=b.x:b.x>this.max.x&&(this.max.x=b.x),b.y<this.min.y?this.min.y=b.y:b.y>this.max.y&&(this.max.y=b.y)}else this.makeEmpty();return this},setFromCenterAndSize:function(){var a=new THREE.Vector2;return function(b,c){var d=a.copy(c).multiplyScalar(0.5);this.min.copy(b).sub(d);
 THREE.extend(THREE.Box2.prototype,{set:function(a,b){this.min.copy(a);this.max.copy(b);return this},setFromPoints:function(a){if(0<a.length){var b=a[0];this.min.copy(b);this.max.copy(b);for(var c=1,d=a.length;c<d;c++)b=a[c],b.x<this.min.x?this.min.x=b.x:b.x>this.max.x&&(this.max.x=b.x),b.y<this.min.y?this.min.y=b.y:b.y>this.max.y&&(this.max.y=b.y)}else this.makeEmpty();return this},setFromCenterAndSize:function(){var a=new THREE.Vector2;return function(b,c){var d=a.copy(c).multiplyScalar(0.5);this.min.copy(b).sub(d);
 this.max.copy(b).add(d);return this}}(),copy:function(a){this.min.copy(a.min);this.max.copy(a.max);return this},makeEmpty:function(){this.min.x=this.min.y=Infinity;this.max.x=this.max.y=-Infinity;return this},empty:function(){return this.max.x<this.min.x||this.max.y<this.min.y},center:function(a){return(a||new THREE.Vector2).addVectors(this.min,this.max).multiplyScalar(0.5)},size:function(a){return(a||new THREE.Vector2).subVectors(this.max,this.min)},expandByPoint:function(a){this.min.min(a);this.max.max(a);
 this.max.copy(b).add(d);return this}}(),copy:function(a){this.min.copy(a.min);this.max.copy(a.max);return this},makeEmpty:function(){this.min.x=this.min.y=Infinity;this.max.x=this.max.y=-Infinity;return this},empty:function(){return this.max.x<this.min.x||this.max.y<this.min.y},center:function(a){return(a||new THREE.Vector2).addVectors(this.min,this.max).multiplyScalar(0.5)},size:function(a){return(a||new THREE.Vector2).subVectors(this.max,this.min)},expandByPoint:function(a){this.min.min(a);this.max.max(a);
 return this},expandByVector:function(a){this.min.sub(a);this.max.add(a);return this},expandByScalar:function(a){this.min.addScalar(-a);this.max.addScalar(a);return this},containsPoint:function(a){return a.x<this.min.x||a.x>this.max.x||a.y<this.min.y||a.y>this.max.y?!1:!0},containsBox:function(a){return this.min.x<=a.min.x&&a.max.x<=this.max.x&&this.min.y<=a.min.y&&a.max.y<=this.max.y?!0:!1},getParameter:function(a){return new THREE.Vector2((a.x-this.min.x)/(this.max.x-this.min.x),(a.y-this.min.y)/
 return this},expandByVector:function(a){this.min.sub(a);this.max.add(a);return this},expandByScalar:function(a){this.min.addScalar(-a);this.max.addScalar(a);return this},containsPoint:function(a){return a.x<this.min.x||a.x>this.max.x||a.y<this.min.y||a.y>this.max.y?!1:!0},containsBox:function(a){return this.min.x<=a.min.x&&a.max.x<=this.max.x&&this.min.y<=a.min.y&&a.max.y<=this.max.y?!0:!1},getParameter:function(a){return new THREE.Vector2((a.x-this.min.x)/(this.max.x-this.min.x),(a.y-this.min.y)/
@@ -72,84 +69,84 @@ this.max.x&&this.min.y<=a.min.y&&a.max.y<=this.max.y&&this.min.z<=a.min.z&&a.max
 this.max)},distanceToPoint:function(){var a=new THREE.Vector3;return function(b){return a.copy(b).clamp(this.min,this.max).sub(b).length()}}(),getBoundingSphere:function(){var a=new THREE.Vector3;return function(b){b=b||new THREE.Sphere;b.center=this.center();b.radius=0.5*this.size(a).length();return b}}(),intersect:function(a){this.min.max(a.min);this.max.min(a.max);return this},union:function(a){this.min.min(a.min);this.max.max(a.max);return this},applyMatrix4:function(){var a=[new THREE.Vector3,
 this.max)},distanceToPoint:function(){var a=new THREE.Vector3;return function(b){return a.copy(b).clamp(this.min,this.max).sub(b).length()}}(),getBoundingSphere:function(){var a=new THREE.Vector3;return function(b){b=b||new THREE.Sphere;b.center=this.center();b.radius=0.5*this.size(a).length();return b}}(),intersect:function(a){this.min.max(a.min);this.max.min(a.max);return this},union:function(a){this.min.min(a.min);this.max.max(a.max);return this},applyMatrix4:function(){var a=[new THREE.Vector3,
 new THREE.Vector3,new THREE.Vector3,new THREE.Vector3,new THREE.Vector3,new THREE.Vector3,new THREE.Vector3,new THREE.Vector3];return function(b){a[0].set(this.min.x,this.min.y,this.min.z).applyMatrix4(b);a[1].set(this.min.x,this.min.y,this.max.z).applyMatrix4(b);a[2].set(this.min.x,this.max.y,this.min.z).applyMatrix4(b);a[3].set(this.min.x,this.max.y,this.max.z).applyMatrix4(b);a[4].set(this.max.x,this.min.y,this.min.z).applyMatrix4(b);a[5].set(this.max.x,this.min.y,this.max.z).applyMatrix4(b);a[6].set(this.max.x,
 new THREE.Vector3,new THREE.Vector3,new THREE.Vector3,new THREE.Vector3,new THREE.Vector3,new THREE.Vector3,new THREE.Vector3];return function(b){a[0].set(this.min.x,this.min.y,this.min.z).applyMatrix4(b);a[1].set(this.min.x,this.min.y,this.max.z).applyMatrix4(b);a[2].set(this.min.x,this.max.y,this.min.z).applyMatrix4(b);a[3].set(this.min.x,this.max.y,this.max.z).applyMatrix4(b);a[4].set(this.max.x,this.min.y,this.min.z).applyMatrix4(b);a[5].set(this.max.x,this.min.y,this.max.z).applyMatrix4(b);a[6].set(this.max.x,
 this.max.y,this.min.z).applyMatrix4(b);a[7].set(this.max.x,this.max.y,this.max.z).applyMatrix4(b);this.makeEmpty();this.setFromPoints(a);return this}}(),translate:function(a){this.min.add(a);this.max.add(a);return this},equals:function(a){return a.min.equals(this.min)&&a.max.equals(this.max)},clone:function(){return(new THREE.Box3).copy(this)}});THREE.Matrix3=function(a,b,c,d,e,f,g,h,i){this.elements=new Float32Array(9);this.set(void 0!==a?a:1,b||0,c||0,d||0,void 0!==e?e:1,f||0,g||0,h||0,void 0!==i?i:1)};
 this.max.y,this.min.z).applyMatrix4(b);a[7].set(this.max.x,this.max.y,this.max.z).applyMatrix4(b);this.makeEmpty();this.setFromPoints(a);return this}}(),translate:function(a){this.min.add(a);this.max.add(a);return this},equals:function(a){return a.min.equals(this.min)&&a.max.equals(this.max)},clone:function(){return(new THREE.Box3).copy(this)}});THREE.Matrix3=function(a,b,c,d,e,f,g,h,i){this.elements=new Float32Array(9);this.set(void 0!==a?a:1,b||0,c||0,d||0,void 0!==e?e:1,f||0,g||0,h||0,void 0!==i?i:1)};
-THREE.extend(THREE.Matrix3.prototype,{set:function(a,b,c,d,e,f,g,h,i){var k=this.elements;k[0]=a;k[3]=b;k[6]=c;k[1]=d;k[4]=e;k[7]=f;k[2]=g;k[5]=h;k[8]=i;return this},identity:function(){this.set(1,0,0,0,1,0,0,0,1);return this},copy:function(a){a=a.elements;this.set(a[0],a[3],a[6],a[1],a[4],a[7],a[2],a[5],a[8]);return this},multiplyVector3:function(a){console.warn("DEPRECATED: Matrix3's .multiplyVector3() has been removed. Use vector.applyMatrix3( matrix ) instead.");return a.applyMatrix3(this)},multiplyVector3Array:function(){var a=
+THREE.extend(THREE.Matrix3.prototype,{set:function(a,b,c,d,e,f,g,h,i){var j=this.elements;j[0]=a;j[3]=b;j[6]=c;j[1]=d;j[4]=e;j[7]=f;j[2]=g;j[5]=h;j[8]=i;return this},identity:function(){this.set(1,0,0,0,1,0,0,0,1);return this},copy:function(a){a=a.elements;this.set(a[0],a[3],a[6],a[1],a[4],a[7],a[2],a[5],a[8]);return this},multiplyVector3:function(a){console.warn("DEPRECATED: Matrix3's .multiplyVector3() has been removed. Use vector.applyMatrix3( matrix ) instead.");return a.applyMatrix3(this)},multiplyVector3Array:function(){var a=
 new THREE.Vector3;return function(b){for(var c=0,d=b.length;c<d;c+=3)a.x=b[c],a.y=b[c+1],a.z=b[c+2],a.applyMatrix3(this),b[c]=a.x,b[c+1]=a.y,b[c+2]=a.z;return b}}(),multiplyScalar:function(a){var b=this.elements;b[0]*=a;b[3]*=a;b[6]*=a;b[1]*=a;b[4]*=a;b[7]*=a;b[2]*=a;b[5]*=a;b[8]*=a;return this},determinant:function(){var a=this.elements,b=a[0],c=a[1],d=a[2],e=a[3],f=a[4],g=a[5],h=a[6],i=a[7],a=a[8];return b*f*a-b*g*i-c*e*a+c*g*h+d*e*i-d*f*h},getInverse:function(a,b){var c=a.elements,d=this.elements;
 new THREE.Vector3;return function(b){for(var c=0,d=b.length;c<d;c+=3)a.x=b[c],a.y=b[c+1],a.z=b[c+2],a.applyMatrix3(this),b[c]=a.x,b[c+1]=a.y,b[c+2]=a.z;return b}}(),multiplyScalar:function(a){var b=this.elements;b[0]*=a;b[3]*=a;b[6]*=a;b[1]*=a;b[4]*=a;b[7]*=a;b[2]*=a;b[5]*=a;b[8]*=a;return this},determinant:function(){var a=this.elements,b=a[0],c=a[1],d=a[2],e=a[3],f=a[4],g=a[5],h=a[6],i=a[7],a=a[8];return b*f*a-b*g*i-c*e*a+c*g*h+d*e*i-d*f*h},getInverse:function(a,b){var c=a.elements,d=this.elements;
 d[0]=c[10]*c[5]-c[6]*c[9];d[1]=-c[10]*c[1]+c[2]*c[9];d[2]=c[6]*c[1]-c[2]*c[5];d[3]=-c[10]*c[4]+c[6]*c[8];d[4]=c[10]*c[0]-c[2]*c[8];d[5]=-c[6]*c[0]+c[2]*c[4];d[6]=c[9]*c[4]-c[5]*c[8];d[7]=-c[9]*c[0]+c[1]*c[8];d[8]=c[5]*c[0]-c[1]*c[4];c=c[0]*d[0]+c[1]*d[3]+c[2]*d[6];if(0===c){if(b)throw Error("Matrix3.getInverse(): can't invert matrix, determinant is 0");console.warn("Matrix3.getInverse(): can't invert matrix, determinant is 0");this.identity();return this}this.multiplyScalar(1/c);return this},transpose:function(){var a,
 d[0]=c[10]*c[5]-c[6]*c[9];d[1]=-c[10]*c[1]+c[2]*c[9];d[2]=c[6]*c[1]-c[2]*c[5];d[3]=-c[10]*c[4]+c[6]*c[8];d[4]=c[10]*c[0]-c[2]*c[8];d[5]=-c[6]*c[0]+c[2]*c[4];d[6]=c[9]*c[4]-c[5]*c[8];d[7]=-c[9]*c[0]+c[1]*c[8];d[8]=c[5]*c[0]-c[1]*c[4];c=c[0]*d[0]+c[1]*d[3]+c[2]*d[6];if(0===c){if(b)throw Error("Matrix3.getInverse(): can't invert matrix, determinant is 0");console.warn("Matrix3.getInverse(): can't invert matrix, determinant is 0");this.identity();return this}this.multiplyScalar(1/c);return this},transpose:function(){var a,
-b=this.elements;a=b[1];b[1]=b[3];b[3]=a;a=b[2];b[2]=b[6];b[6]=a;a=b[5];b[5]=b[7];b[7]=a;return this},getNormalMatrix:function(a){this.getInverse(a).transpose();return this},transposeIntoArray:function(a){var b=this.elements;a[0]=b[0];a[1]=b[3];a[2]=b[6];a[3]=b[1];a[4]=b[4];a[5]=b[7];a[6]=b[2];a[7]=b[5];a[8]=b[8];return this},clone:function(){var a=this.elements;return new THREE.Matrix3(a[0],a[3],a[6],a[1],a[4],a[7],a[2],a[5],a[8])}});THREE.Matrix4=function(a,b,c,d,e,f,g,h,i,k,l,n,m,t,r,p){var q=this.elements=new Float32Array(16);q[0]=void 0!==a?a:1;q[4]=b||0;q[8]=c||0;q[12]=d||0;q[1]=e||0;q[5]=void 0!==f?f:1;q[9]=g||0;q[13]=h||0;q[2]=i||0;q[6]=k||0;q[10]=void 0!==l?l:1;q[14]=n||0;q[3]=m||0;q[7]=t||0;q[11]=r||0;q[15]=void 0!==p?p:1};
-THREE.extend(THREE.Matrix4.prototype,{set:function(a,b,c,d,e,f,g,h,i,k,l,n,m,t,r,p){var q=this.elements;q[0]=a;q[4]=b;q[8]=c;q[12]=d;q[1]=e;q[5]=f;q[9]=g;q[13]=h;q[2]=i;q[6]=k;q[10]=l;q[14]=n;q[3]=m;q[7]=t;q[11]=r;q[15]=p;return this},identity:function(){this.set(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1);return this},copy:function(a){a=a.elements;this.set(a[0],a[4],a[8],a[12],a[1],a[5],a[9],a[13],a[2],a[6],a[10],a[14],a[3],a[7],a[11],a[15]);return this},setRotationFromEuler:function(a,b){var c=this.elements,
-d=a.x,e=a.y,f=a.z,g=Math.cos(d),d=Math.sin(d),h=Math.cos(e),e=Math.sin(e),i=Math.cos(f),f=Math.sin(f);if(void 0===b||"XYZ"===b){var k=g*i,l=g*f,n=d*i,m=d*f;c[0]=h*i;c[4]=-h*f;c[8]=e;c[1]=l+n*e;c[5]=k-m*e;c[9]=-d*h;c[2]=m-k*e;c[6]=n+l*e;c[10]=g*h}else"YXZ"===b?(k=h*i,l=h*f,n=e*i,m=e*f,c[0]=k+m*d,c[4]=n*d-l,c[8]=g*e,c[1]=g*f,c[5]=g*i,c[9]=-d,c[2]=l*d-n,c[6]=m+k*d,c[10]=g*h):"ZXY"===b?(k=h*i,l=h*f,n=e*i,m=e*f,c[0]=k-m*d,c[4]=-g*f,c[8]=n+l*d,c[1]=l+n*d,c[5]=g*i,c[9]=m-k*d,c[2]=-g*e,c[6]=d,c[10]=g*h):
-"ZYX"===b?(k=g*i,l=g*f,n=d*i,m=d*f,c[0]=h*i,c[4]=n*e-l,c[8]=k*e+m,c[1]=h*f,c[5]=m*e+k,c[9]=l*e-n,c[2]=-e,c[6]=d*h,c[10]=g*h):"YZX"===b?(k=g*h,l=g*e,n=d*h,m=d*e,c[0]=h*i,c[4]=m-k*f,c[8]=n*f+l,c[1]=f,c[5]=g*i,c[9]=-d*i,c[2]=-e*i,c[6]=l*f+n,c[10]=k-m*f):"XZY"===b&&(k=g*h,l=g*e,n=d*h,m=d*e,c[0]=h*i,c[4]=-f,c[8]=e*i,c[1]=k*f+m,c[5]=g*i,c[9]=l*f-n,c[2]=n*f-l,c[6]=d*i,c[10]=m*f+k);return this},setRotationFromQuaternion:function(a){var b=this.elements,c=a.x,d=a.y,e=a.z,f=a.w,g=c+c,h=d+d,i=e+e,a=c*g,k=c*h,
-c=c*i,l=d*h,d=d*i,e=e*i,g=f*g,h=f*h,f=f*i;b[0]=1-(l+e);b[4]=k-f;b[8]=c+h;b[1]=k+f;b[5]=1-(a+e);b[9]=d-g;b[2]=c-h;b[6]=d+g;b[10]=1-(a+l);return this},lookAt:function(){var a=new THREE.Vector3,b=new THREE.Vector3,c=new THREE.Vector3;return function(d,e,f){var g=this.elements;c.subVectors(d,e).normalize();0===c.length()&&(c.z=1);a.crossVectors(f,c).normalize();0===a.length()&&(c.x+=1E-4,a.crossVectors(f,c).normalize());b.crossVectors(c,a);g[0]=a.x;g[4]=b.x;g[8]=c.x;g[1]=a.y;g[5]=b.y;g[9]=c.y;g[2]=a.z;
-g[6]=b.z;g[10]=c.z;return this}}(),multiply:function(a,b){return void 0!==b?(console.warn("DEPRECATED: Matrix4's .multiply() now only accepts one argument. Use .multiplyMatrices( a, b ) instead."),this.multiplyMatrices(a,b)):this.multiplyMatrices(this,a)},multiplyMatrices:function(a,b){var c=a.elements,d=b.elements,e=this.elements,f=c[0],g=c[4],h=c[8],i=c[12],k=c[1],l=c[5],n=c[9],m=c[13],t=c[2],r=c[6],p=c[10],q=c[14],y=c[3],v=c[7],z=c[11],c=c[15],s=d[0],C=d[4],H=d[8],B=d[12],w=d[1],I=d[5],J=d[9],
-E=d[13],Z=d[2],A=d[6],U=d[10],F=d[14],G=d[3],K=d[7],N=d[11],d=d[15];e[0]=f*s+g*w+h*Z+i*G;e[4]=f*C+g*I+h*A+i*K;e[8]=f*H+g*J+h*U+i*N;e[12]=f*B+g*E+h*F+i*d;e[1]=k*s+l*w+n*Z+m*G;e[5]=k*C+l*I+n*A+m*K;e[9]=k*H+l*J+n*U+m*N;e[13]=k*B+l*E+n*F+m*d;e[2]=t*s+r*w+p*Z+q*G;e[6]=t*C+r*I+p*A+q*K;e[10]=t*H+r*J+p*U+q*N;e[14]=t*B+r*E+p*F+q*d;e[3]=y*s+v*w+z*Z+c*G;e[7]=y*C+v*I+z*A+c*K;e[11]=y*H+v*J+z*U+c*N;e[15]=y*B+v*E+z*F+c*d;return this},multiplyToArray:function(a,b,c){var d=this.elements;this.multiplyMatrices(a,b);
+b=this.elements;a=b[1];b[1]=b[3];b[3]=a;a=b[2];b[2]=b[6];b[6]=a;a=b[5];b[5]=b[7];b[7]=a;return this},getNormalMatrix:function(a){this.getInverse(a).transpose();return this},transposeIntoArray:function(a){var b=this.elements;a[0]=b[0];a[1]=b[3];a[2]=b[6];a[3]=b[1];a[4]=b[4];a[5]=b[7];a[6]=b[2];a[7]=b[5];a[8]=b[8];return this},clone:function(){var a=this.elements;return new THREE.Matrix3(a[0],a[3],a[6],a[1],a[4],a[7],a[2],a[5],a[8])}});THREE.Matrix4=function(a,b,c,d,e,f,g,h,i,j,l,n,m,r,u,p){var q=this.elements=new Float32Array(16);q[0]=void 0!==a?a:1;q[4]=b||0;q[8]=c||0;q[12]=d||0;q[1]=e||0;q[5]=void 0!==f?f:1;q[9]=g||0;q[13]=h||0;q[2]=i||0;q[6]=j||0;q[10]=void 0!==l?l:1;q[14]=n||0;q[3]=m||0;q[7]=r||0;q[11]=u||0;q[15]=void 0!==p?p:1};
+THREE.extend(THREE.Matrix4.prototype,{set:function(a,b,c,d,e,f,g,h,i,j,l,n,m,r,u,p){var q=this.elements;q[0]=a;q[4]=b;q[8]=c;q[12]=d;q[1]=e;q[5]=f;q[9]=g;q[13]=h;q[2]=i;q[6]=j;q[10]=l;q[14]=n;q[3]=m;q[7]=r;q[11]=u;q[15]=p;return this},identity:function(){this.set(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1);return this},copy:function(a){a=a.elements;this.set(a[0],a[4],a[8],a[12],a[1],a[5],a[9],a[13],a[2],a[6],a[10],a[14],a[3],a[7],a[11],a[15]);return this},setRotationFromEuler:function(a,b){var c=this.elements,
+d=a.x,e=a.y,f=a.z,g=Math.cos(d),d=Math.sin(d),h=Math.cos(e),e=Math.sin(e),i=Math.cos(f),f=Math.sin(f);if(void 0===b||"XYZ"===b){var j=g*i,l=g*f,n=d*i,m=d*f;c[0]=h*i;c[4]=-h*f;c[8]=e;c[1]=l+n*e;c[5]=j-m*e;c[9]=-d*h;c[2]=m-j*e;c[6]=n+l*e;c[10]=g*h}else"YXZ"===b?(j=h*i,l=h*f,n=e*i,m=e*f,c[0]=j+m*d,c[4]=n*d-l,c[8]=g*e,c[1]=g*f,c[5]=g*i,c[9]=-d,c[2]=l*d-n,c[6]=m+j*d,c[10]=g*h):"ZXY"===b?(j=h*i,l=h*f,n=e*i,m=e*f,c[0]=j-m*d,c[4]=-g*f,c[8]=n+l*d,c[1]=l+n*d,c[5]=g*i,c[9]=m-j*d,c[2]=-g*e,c[6]=d,c[10]=g*h):
+"ZYX"===b?(j=g*i,l=g*f,n=d*i,m=d*f,c[0]=h*i,c[4]=n*e-l,c[8]=j*e+m,c[1]=h*f,c[5]=m*e+j,c[9]=l*e-n,c[2]=-e,c[6]=d*h,c[10]=g*h):"YZX"===b?(j=g*h,l=g*e,n=d*h,m=d*e,c[0]=h*i,c[4]=m-j*f,c[8]=n*f+l,c[1]=f,c[5]=g*i,c[9]=-d*i,c[2]=-e*i,c[6]=l*f+n,c[10]=j-m*f):"XZY"===b&&(j=g*h,l=g*e,n=d*h,m=d*e,c[0]=h*i,c[4]=-f,c[8]=e*i,c[1]=j*f+m,c[5]=g*i,c[9]=l*f-n,c[2]=n*f-l,c[6]=d*i,c[10]=m*f+j);return this},setRotationFromQuaternion:function(a){var b=this.elements,c=a.x,d=a.y,e=a.z,f=a.w,g=c+c,h=d+d,i=e+e,a=c*g,j=c*h,
+c=c*i,l=d*h,d=d*i,e=e*i,g=f*g,h=f*h,f=f*i;b[0]=1-(l+e);b[4]=j-f;b[8]=c+h;b[1]=j+f;b[5]=1-(a+e);b[9]=d-g;b[2]=c-h;b[6]=d+g;b[10]=1-(a+l);return this},lookAt:function(){var a=new THREE.Vector3,b=new THREE.Vector3,c=new THREE.Vector3;return function(d,e,f){var g=this.elements;c.subVectors(d,e).normalize();0===c.length()&&(c.z=1);a.crossVectors(f,c).normalize();0===a.length()&&(c.x+=1E-4,a.crossVectors(f,c).normalize());b.crossVectors(c,a);g[0]=a.x;g[4]=b.x;g[8]=c.x;g[1]=a.y;g[5]=b.y;g[9]=c.y;g[2]=a.z;
+g[6]=b.z;g[10]=c.z;return this}}(),multiply:function(a,b){return void 0!==b?(console.warn("DEPRECATED: Matrix4's .multiply() now only accepts one argument. Use .multiplyMatrices( a, b ) instead."),this.multiplyMatrices(a,b)):this.multiplyMatrices(this,a)},multiplyMatrices:function(a,b){var c=a.elements,d=b.elements,e=this.elements,f=c[0],g=c[4],h=c[8],i=c[12],j=c[1],l=c[5],n=c[9],m=c[13],r=c[2],u=c[6],p=c[10],q=c[14],w=c[3],v=c[7],z=c[11],c=c[15],y=d[0],t=d[4],D=d[8],C=d[12],k=d[1],I=d[5],J=d[9],
+B=d[13],P=d[2],A=d[6],G=d[10],E=d[14],F=d[3],s=d[7],H=d[11],d=d[15];e[0]=f*y+g*k+h*P+i*F;e[4]=f*t+g*I+h*A+i*s;e[8]=f*D+g*J+h*G+i*H;e[12]=f*C+g*B+h*E+i*d;e[1]=j*y+l*k+n*P+m*F;e[5]=j*t+l*I+n*A+m*s;e[9]=j*D+l*J+n*G+m*H;e[13]=j*C+l*B+n*E+m*d;e[2]=r*y+u*k+p*P+q*F;e[6]=r*t+u*I+p*A+q*s;e[10]=r*D+u*J+p*G+q*H;e[14]=r*C+u*B+p*E+q*d;e[3]=w*y+v*k+z*P+c*F;e[7]=w*t+v*I+z*A+c*s;e[11]=w*D+v*J+z*G+c*H;e[15]=w*C+v*B+z*E+c*d;return this},multiplyToArray:function(a,b,c){var d=this.elements;this.multiplyMatrices(a,b);
 c[0]=d[0];c[1]=d[1];c[2]=d[2];c[3]=d[3];c[4]=d[4];c[5]=d[5];c[6]=d[6];c[7]=d[7];c[8]=d[8];c[9]=d[9];c[10]=d[10];c[11]=d[11];c[12]=d[12];c[13]=d[13];c[14]=d[14];c[15]=d[15];return this},multiplyScalar:function(a){var b=this.elements;b[0]*=a;b[4]*=a;b[8]*=a;b[12]*=a;b[1]*=a;b[5]*=a;b[9]*=a;b[13]*=a;b[2]*=a;b[6]*=a;b[10]*=a;b[14]*=a;b[3]*=a;b[7]*=a;b[11]*=a;b[15]*=a;return this},multiplyVector3:function(a){console.warn("DEPRECATED: Matrix4's .multiplyVector3() has been removed. Use vector.applyMatrix4( matrix ) or vector.applyProjection( matrix ) instead.");
 c[0]=d[0];c[1]=d[1];c[2]=d[2];c[3]=d[3];c[4]=d[4];c[5]=d[5];c[6]=d[6];c[7]=d[7];c[8]=d[8];c[9]=d[9];c[10]=d[10];c[11]=d[11];c[12]=d[12];c[13]=d[13];c[14]=d[14];c[15]=d[15];return this},multiplyScalar:function(a){var b=this.elements;b[0]*=a;b[4]*=a;b[8]*=a;b[12]*=a;b[1]*=a;b[5]*=a;b[9]*=a;b[13]*=a;b[2]*=a;b[6]*=a;b[10]*=a;b[14]*=a;b[3]*=a;b[7]*=a;b[11]*=a;b[15]*=a;return this},multiplyVector3:function(a){console.warn("DEPRECATED: Matrix4's .multiplyVector3() has been removed. Use vector.applyMatrix4( matrix ) or vector.applyProjection( matrix ) instead.");
 return a.applyProjection(this)},multiplyVector4:function(a){console.warn("DEPRECATED: Matrix4's .multiplyVector4() has been removed. Use vector.applyMatrix4( matrix ) instead.");return a.applyMatrix4(this)},multiplyVector3Array:function(){var a=new THREE.Vector3;return function(b){for(var c=0,d=b.length;c<d;c+=3)a.x=b[c],a.y=b[c+1],a.z=b[c+2],a.applyProjection(this),b[c]=a.x,b[c+1]=a.y,b[c+2]=a.z;return b}}(),rotateAxis:function(a){console.warn("DEPRECATED: Matrix4's .rotateAxis() has been removed. Use Vector3.transformDirection( matrix ) instead.");
 return a.applyProjection(this)},multiplyVector4:function(a){console.warn("DEPRECATED: Matrix4's .multiplyVector4() has been removed. Use vector.applyMatrix4( matrix ) instead.");return a.applyMatrix4(this)},multiplyVector3Array:function(){var a=new THREE.Vector3;return function(b){for(var c=0,d=b.length;c<d;c+=3)a.x=b[c],a.y=b[c+1],a.z=b[c+2],a.applyProjection(this),b[c]=a.x,b[c+1]=a.y,b[c+2]=a.z;return b}}(),rotateAxis:function(a){console.warn("DEPRECATED: Matrix4's .rotateAxis() has been removed. Use Vector3.transformDirection( matrix ) instead.");
-a.transformDirection(this)},crossVector:function(a){var b=this.elements,c=new THREE.Vector4;c.x=b[0]*a.x+b[4]*a.y+b[8]*a.z+b[12]*a.w;c.y=b[1]*a.x+b[5]*a.y+b[9]*a.z+b[13]*a.w;c.z=b[2]*a.x+b[6]*a.y+b[10]*a.z+b[14]*a.w;c.w=a.w?b[3]*a.x+b[7]*a.y+b[11]*a.z+b[15]*a.w:1;return c},determinant:function(){var a=this.elements,b=a[0],c=a[4],d=a[8],e=a[12],f=a[1],g=a[5],h=a[9],i=a[13],k=a[2],l=a[6],n=a[10],m=a[14];return a[3]*(+e*h*l-d*i*l-e*g*n+c*i*n+d*g*m-c*h*m)+a[7]*(+b*h*m-b*i*n+e*f*n-d*f*m+d*i*k-e*h*k)+a[11]*
-(+b*i*l-b*g*m-e*f*l+c*f*m+e*g*k-c*i*k)+a[15]*(-d*g*k-b*h*l+b*g*n+d*f*l-c*f*n+c*h*k)},transpose:function(){var a=this.elements,b;b=a[1];a[1]=a[4];a[4]=b;b=a[2];a[2]=a[8];a[8]=b;b=a[6];a[6]=a[9];a[9]=b;b=a[3];a[3]=a[12];a[12]=b;b=a[7];a[7]=a[13];a[13]=b;b=a[11];a[11]=a[14];a[14]=b;return this},flattenToArray:function(a){var b=this.elements;a[0]=b[0];a[1]=b[1];a[2]=b[2];a[3]=b[3];a[4]=b[4];a[5]=b[5];a[6]=b[6];a[7]=b[7];a[8]=b[8];a[9]=b[9];a[10]=b[10];a[11]=b[11];a[12]=b[12];a[13]=b[13];a[14]=b[14];a[15]=
+a.transformDirection(this)},crossVector:function(a){var b=this.elements,c=new THREE.Vector4;c.x=b[0]*a.x+b[4]*a.y+b[8]*a.z+b[12]*a.w;c.y=b[1]*a.x+b[5]*a.y+b[9]*a.z+b[13]*a.w;c.z=b[2]*a.x+b[6]*a.y+b[10]*a.z+b[14]*a.w;c.w=a.w?b[3]*a.x+b[7]*a.y+b[11]*a.z+b[15]*a.w:1;return c},determinant:function(){var a=this.elements,b=a[0],c=a[4],d=a[8],e=a[12],f=a[1],g=a[5],h=a[9],i=a[13],j=a[2],l=a[6],n=a[10],m=a[14];return a[3]*(+e*h*l-d*i*l-e*g*n+c*i*n+d*g*m-c*h*m)+a[7]*(+b*h*m-b*i*n+e*f*n-d*f*m+d*i*j-e*h*j)+a[11]*
+(+b*i*l-b*g*m-e*f*l+c*f*m+e*g*j-c*i*j)+a[15]*(-d*g*j-b*h*l+b*g*n+d*f*l-c*f*n+c*h*j)},transpose:function(){var a=this.elements,b;b=a[1];a[1]=a[4];a[4]=b;b=a[2];a[2]=a[8];a[8]=b;b=a[6];a[6]=a[9];a[9]=b;b=a[3];a[3]=a[12];a[12]=b;b=a[7];a[7]=a[13];a[13]=b;b=a[11];a[11]=a[14];a[14]=b;return this},flattenToArray:function(a){var b=this.elements;a[0]=b[0];a[1]=b[1];a[2]=b[2];a[3]=b[3];a[4]=b[4];a[5]=b[5];a[6]=b[6];a[7]=b[7];a[8]=b[8];a[9]=b[9];a[10]=b[10];a[11]=b[11];a[12]=b[12];a[13]=b[13];a[14]=b[14];a[15]=
 b[15];return a},flattenToArrayOffset:function(a,b){var c=this.elements;a[b]=c[0];a[b+1]=c[1];a[b+2]=c[2];a[b+3]=c[3];a[b+4]=c[4];a[b+5]=c[5];a[b+6]=c[6];a[b+7]=c[7];a[b+8]=c[8];a[b+9]=c[9];a[b+10]=c[10];a[b+11]=c[11];a[b+12]=c[12];a[b+13]=c[13];a[b+14]=c[14];a[b+15]=c[15];return a},getPosition:function(){var a=new THREE.Vector3;return function(){console.warn("DEPRECATED: Matrix4's .getPosition() has been removed. Use Vector3.getPositionFromMatrix( matrix ) instead.");var b=this.elements;return a.set(b[12],
 b[15];return a},flattenToArrayOffset:function(a,b){var c=this.elements;a[b]=c[0];a[b+1]=c[1];a[b+2]=c[2];a[b+3]=c[3];a[b+4]=c[4];a[b+5]=c[5];a[b+6]=c[6];a[b+7]=c[7];a[b+8]=c[8];a[b+9]=c[9];a[b+10]=c[10];a[b+11]=c[11];a[b+12]=c[12];a[b+13]=c[13];a[b+14]=c[14];a[b+15]=c[15];return a},getPosition:function(){var a=new THREE.Vector3;return function(){console.warn("DEPRECATED: Matrix4's .getPosition() has been removed. Use Vector3.getPositionFromMatrix( matrix ) instead.");var b=this.elements;return a.set(b[12],
-b[13],b[14])}}(),setPosition:function(a){var b=this.elements;b[12]=a.x;b[13]=a.y;b[14]=a.z;return this},getInverse:function(a,b){var c=this.elements,d=a.elements,e=d[0],f=d[4],g=d[8],h=d[12],i=d[1],k=d[5],l=d[9],n=d[13],m=d[2],t=d[6],r=d[10],p=d[14],q=d[3],y=d[7],v=d[11],z=d[15];c[0]=l*p*y-n*r*y+n*t*v-k*p*v-l*t*z+k*r*z;c[4]=h*r*y-g*p*y-h*t*v+f*p*v+g*t*z-f*r*z;c[8]=g*n*y-h*l*y+h*k*v-f*n*v-g*k*z+f*l*z;c[12]=h*l*t-g*n*t-h*k*r+f*n*r+g*k*p-f*l*p;c[1]=n*r*q-l*p*q-n*m*v+i*p*v+l*m*z-i*r*z;c[5]=g*p*q-h*r*
-q+h*m*v-e*p*v-g*m*z+e*r*z;c[9]=h*l*q-g*n*q-h*i*v+e*n*v+g*i*z-e*l*z;c[13]=g*n*m-h*l*m+h*i*r-e*n*r-g*i*p+e*l*p;c[2]=k*p*q-n*t*q+n*m*y-i*p*y-k*m*z+i*t*z;c[6]=h*t*q-f*p*q-h*m*y+e*p*y+f*m*z-e*t*z;c[10]=f*n*q-h*k*q+h*i*y-e*n*y-f*i*z+e*k*z;c[14]=h*k*m-f*n*m-h*i*t+e*n*t+f*i*p-e*k*p;c[3]=l*t*q-k*r*q-l*m*y+i*r*y+k*m*v-i*t*v;c[7]=f*r*q-g*t*q+g*m*y-e*r*y-f*m*v+e*t*v;c[11]=g*k*q-f*l*q-g*i*y+e*l*y+f*i*v-e*k*v;c[15]=f*l*m-g*k*m+g*i*t-e*l*t-f*i*r+e*k*r;c=d[0]*c[0]+d[1]*c[4]+d[2]*c[8]+d[3]*c[12];if(0==c){if(b)throw Error("Matrix4.getInverse(): can't invert matrix, determinant is 0");
+b[13],b[14])}}(),setPosition:function(a){var b=this.elements;b[12]=a.x;b[13]=a.y;b[14]=a.z;return this},getInverse:function(a,b){var c=this.elements,d=a.elements,e=d[0],f=d[4],g=d[8],h=d[12],i=d[1],j=d[5],l=d[9],n=d[13],m=d[2],r=d[6],u=d[10],p=d[14],q=d[3],w=d[7],v=d[11],z=d[15];c[0]=l*p*w-n*u*w+n*r*v-j*p*v-l*r*z+j*u*z;c[4]=h*u*w-g*p*w-h*r*v+f*p*v+g*r*z-f*u*z;c[8]=g*n*w-h*l*w+h*j*v-f*n*v-g*j*z+f*l*z;c[12]=h*l*r-g*n*r-h*j*u+f*n*u+g*j*p-f*l*p;c[1]=n*u*q-l*p*q-n*m*v+i*p*v+l*m*z-i*u*z;c[5]=g*p*q-h*u*
+q+h*m*v-e*p*v-g*m*z+e*u*z;c[9]=h*l*q-g*n*q-h*i*v+e*n*v+g*i*z-e*l*z;c[13]=g*n*m-h*l*m+h*i*u-e*n*u-g*i*p+e*l*p;c[2]=j*p*q-n*r*q+n*m*w-i*p*w-j*m*z+i*r*z;c[6]=h*r*q-f*p*q-h*m*w+e*p*w+f*m*z-e*r*z;c[10]=f*n*q-h*j*q+h*i*w-e*n*w-f*i*z+e*j*z;c[14]=h*j*m-f*n*m-h*i*r+e*n*r+f*i*p-e*j*p;c[3]=l*r*q-j*u*q-l*m*w+i*u*w+j*m*v-i*r*v;c[7]=f*u*q-g*r*q+g*m*w-e*u*w-f*m*v+e*r*v;c[11]=g*j*q-f*l*q-g*i*w+e*l*w+f*i*v-e*j*v;c[15]=f*l*m-g*j*m+g*i*r-e*l*r-f*i*u+e*j*u;c=d[0]*c[0]+d[1]*c[4]+d[2]*c[8]+d[3]*c[12];if(0==c){if(b)throw Error("Matrix4.getInverse(): can't invert matrix, determinant is 0");
 console.warn("Matrix4.getInverse(): can't invert matrix, determinant is 0");this.identity();return this}this.multiplyScalar(1/c);return this},compose:function(){var a=new THREE.Matrix4,b=new THREE.Matrix4;return function(c,d,e){var f=this.elements;a.identity();a.setRotationFromQuaternion(d);b.makeScale(e.x,e.y,e.z);this.multiplyMatrices(a,b);f[12]=c.x;f[13]=c.y;f[14]=c.z;return this}}(),decompose:function(){var a=new THREE.Vector3,b=new THREE.Vector3,c=new THREE.Vector3,d=new THREE.Matrix4;return function(e,
 console.warn("Matrix4.getInverse(): can't invert matrix, determinant is 0");this.identity();return this}this.multiplyScalar(1/c);return this},compose:function(){var a=new THREE.Matrix4,b=new THREE.Matrix4;return function(c,d,e){var f=this.elements;a.identity();a.setRotationFromQuaternion(d);b.makeScale(e.x,e.y,e.z);this.multiplyMatrices(a,b);f[12]=c.x;f[13]=c.y;f[14]=c.z;return this}}(),decompose:function(){var a=new THREE.Vector3,b=new THREE.Vector3,c=new THREE.Vector3,d=new THREE.Matrix4;return function(e,
 f,g){var h=this.elements;a.set(h[0],h[1],h[2]);b.set(h[4],h[5],h[6]);c.set(h[8],h[9],h[10]);e=e instanceof THREE.Vector3?e:new THREE.Vector3;f=f instanceof THREE.Quaternion?f:new THREE.Quaternion;g=g instanceof THREE.Vector3?g:new THREE.Vector3;g.x=a.length();g.y=b.length();g.z=c.length();e.x=h[12];e.y=h[13];e.z=h[14];d.copy(this);d.elements[0]/=g.x;d.elements[1]/=g.x;d.elements[2]/=g.x;d.elements[4]/=g.y;d.elements[5]/=g.y;d.elements[6]/=g.y;d.elements[8]/=g.z;d.elements[9]/=g.z;d.elements[10]/=
 f,g){var h=this.elements;a.set(h[0],h[1],h[2]);b.set(h[4],h[5],h[6]);c.set(h[8],h[9],h[10]);e=e instanceof THREE.Vector3?e:new THREE.Vector3;f=f instanceof THREE.Quaternion?f:new THREE.Quaternion;g=g instanceof THREE.Vector3?g:new THREE.Vector3;g.x=a.length();g.y=b.length();g.z=c.length();e.x=h[12];e.y=h[13];e.z=h[14];d.copy(this);d.elements[0]/=g.x;d.elements[1]/=g.x;d.elements[2]/=g.x;d.elements[4]/=g.y;d.elements[5]/=g.y;d.elements[6]/=g.y;d.elements[8]/=g.z;d.elements[9]/=g.z;d.elements[10]/=
 g.z;f.setFromRotationMatrix(d);return[e,f,g]}}(),extractPosition:function(a){var b=this.elements,a=a.elements;b[12]=a[12];b[13]=a[13];b[14]=a[14];return this},extractRotation:function(){var a=new THREE.Vector3;return function(b){var c=this.elements,b=b.elements,d=1/a.set(b[0],b[1],b[2]).length(),e=1/a.set(b[4],b[5],b[6]).length(),f=1/a.set(b[8],b[9],b[10]).length();c[0]=b[0]*d;c[1]=b[1]*d;c[2]=b[2]*d;c[4]=b[4]*e;c[5]=b[5]*e;c[6]=b[6]*e;c[8]=b[8]*f;c[9]=b[9]*f;c[10]=b[10]*f;return this}}(),translate:function(a){var b=
 g.z;f.setFromRotationMatrix(d);return[e,f,g]}}(),extractPosition:function(a){var b=this.elements,a=a.elements;b[12]=a[12];b[13]=a[13];b[14]=a[14];return this},extractRotation:function(){var a=new THREE.Vector3;return function(b){var c=this.elements,b=b.elements,d=1/a.set(b[0],b[1],b[2]).length(),e=1/a.set(b[4],b[5],b[6]).length(),f=1/a.set(b[8],b[9],b[10]).length();c[0]=b[0]*d;c[1]=b[1]*d;c[2]=b[2]*d;c[4]=b[4]*e;c[5]=b[5]*e;c[6]=b[6]*e;c[8]=b[8]*f;c[9]=b[9]*f;c[10]=b[10]*f;return this}}(),translate:function(a){var b=
-this.elements,c=a.x,d=a.y,a=a.z;b[12]=b[0]*c+b[4]*d+b[8]*a+b[12];b[13]=b[1]*c+b[5]*d+b[9]*a+b[13];b[14]=b[2]*c+b[6]*d+b[10]*a+b[14];b[15]=b[3]*c+b[7]*d+b[11]*a+b[15];return this},rotateX:function(a){var b=this.elements,c=b[4],d=b[5],e=b[6],f=b[7],g=b[8],h=b[9],i=b[10],k=b[11],l=Math.cos(a),a=Math.sin(a);b[4]=l*c+a*g;b[5]=l*d+a*h;b[6]=l*e+a*i;b[7]=l*f+a*k;b[8]=l*g-a*c;b[9]=l*h-a*d;b[10]=l*i-a*e;b[11]=l*k-a*f;return this},rotateY:function(a){var b=this.elements,c=b[0],d=b[1],e=b[2],f=b[3],g=b[8],h=
-b[9],i=b[10],k=b[11],l=Math.cos(a),a=Math.sin(a);b[0]=l*c-a*g;b[1]=l*d-a*h;b[2]=l*e-a*i;b[3]=l*f-a*k;b[8]=l*g+a*c;b[9]=l*h+a*d;b[10]=l*i+a*e;b[11]=l*k+a*f;return this},rotateZ:function(a){var b=this.elements,c=b[0],d=b[1],e=b[2],f=b[3],g=b[4],h=b[5],i=b[6],k=b[7],l=Math.cos(a),a=Math.sin(a);b[0]=l*c+a*g;b[1]=l*d+a*h;b[2]=l*e+a*i;b[3]=l*f+a*k;b[4]=l*g-a*c;b[5]=l*h-a*d;b[6]=l*i-a*e;b[7]=l*k-a*f;return this},rotateByAxis:function(a,b){var c=this.elements;if(1===a.x&&0===a.y&&0===a.z)return this.rotateX(b);
-if(0===a.x&&1===a.y&&0===a.z)return this.rotateY(b);if(0===a.x&&0===a.y&&1===a.z)return this.rotateZ(b);var d=a.x,e=a.y,f=a.z,g=Math.sqrt(d*d+e*e+f*f),d=d/g,e=e/g,f=f/g,g=d*d,h=e*e,i=f*f,k=Math.cos(b),l=Math.sin(b),n=1-k,m=d*e*n,t=d*f*n,n=e*f*n,d=d*l,r=e*l,l=f*l,f=g+(1-g)*k,g=m+l,e=t-r,m=m-l,h=h+(1-h)*k,l=n+d,t=t+r,n=n-d,i=i+(1-i)*k,k=c[0],d=c[1],r=c[2],p=c[3],q=c[4],y=c[5],v=c[6],z=c[7],s=c[8],C=c[9],H=c[10],B=c[11];c[0]=f*k+g*q+e*s;c[1]=f*d+g*y+e*C;c[2]=f*r+g*v+e*H;c[3]=f*p+g*z+e*B;c[4]=m*k+h*q+
-l*s;c[5]=m*d+h*y+l*C;c[6]=m*r+h*v+l*H;c[7]=m*p+h*z+l*B;c[8]=t*k+n*q+i*s;c[9]=t*d+n*y+i*C;c[10]=t*r+n*v+i*H;c[11]=t*p+n*z+i*B;return this},scale:function(a){var b=this.elements,c=a.x,d=a.y,a=a.z;b[0]*=c;b[4]*=d;b[8]*=a;b[1]*=c;b[5]*=d;b[9]*=a;b[2]*=c;b[6]*=d;b[10]*=a;b[3]*=c;b[7]*=d;b[11]*=a;return this},getMaxScaleOnAxis:function(){var a=this.elements;return Math.sqrt(Math.max(a[0]*a[0]+a[1]*a[1]+a[2]*a[2],Math.max(a[4]*a[4]+a[5]*a[5]+a[6]*a[6],a[8]*a[8]+a[9]*a[9]+a[10]*a[10])))},makeTranslation:function(a,
-b,c){this.set(1,0,0,a,0,1,0,b,0,0,1,c,0,0,0,1);return this},makeRotationX:function(a){var b=Math.cos(a),a=Math.sin(a);this.set(1,0,0,0,0,b,-a,0,0,a,b,0,0,0,0,1);return this},makeRotationY:function(a){var b=Math.cos(a),a=Math.sin(a);this.set(b,0,a,0,0,1,0,0,-a,0,b,0,0,0,0,1);return this},makeRotationZ:function(a){var b=Math.cos(a),a=Math.sin(a);this.set(b,-a,0,0,a,b,0,0,0,0,1,0,0,0,0,1);return this},makeRotationAxis:function(a,b){var c=Math.cos(b),d=Math.sin(b),e=1-c,f=a.x,g=a.y,h=a.z,i=e*f,k=e*g;
-this.set(i*f+c,i*g-d*h,i*h+d*g,0,i*g+d*h,k*g+c,k*h-d*f,0,i*h-d*g,k*h+d*f,e*h*h+c,0,0,0,0,1);return this},makeScale:function(a,b,c){this.set(a,0,0,0,0,b,0,0,0,0,c,0,0,0,0,1);return this},makeFrustum:function(a,b,c,d,e,f){var g=this.elements;g[0]=2*e/(b-a);g[4]=0;g[8]=(b+a)/(b-a);g[12]=0;g[1]=0;g[5]=2*e/(d-c);g[9]=(d+c)/(d-c);g[13]=0;g[2]=0;g[6]=0;g[10]=-(f+e)/(f-e);g[14]=-2*f*e/(f-e);g[3]=0;g[7]=0;g[11]=-1;g[15]=0;return this},makePerspective:function(a,b,c,d){var a=c*Math.tan(THREE.Math.degToRad(0.5*
-a)),e=-a;return this.makeFrustum(e*b,a*b,e,a,c,d)},makeOrthographic:function(a,b,c,d,e,f){var g=this.elements,h=b-a,i=c-d,k=f-e;g[0]=2/h;g[4]=0;g[8]=0;g[12]=-((b+a)/h);g[1]=0;g[5]=2/i;g[9]=0;g[13]=-((c+d)/i);g[2]=0;g[6]=0;g[10]=-2/k;g[14]=-((f+e)/k);g[3]=0;g[7]=0;g[11]=0;g[15]=1;return this},clone:function(){var a=this.elements;return new THREE.Matrix4(a[0],a[4],a[8],a[12],a[1],a[5],a[9],a[13],a[2],a[6],a[10],a[14],a[3],a[7],a[11],a[15])}});THREE.Ray=function(a,b){this.origin=void 0!==a?a:new THREE.Vector3;this.direction=void 0!==b?b:new THREE.Vector3};
+this.elements,c=a.x,d=a.y,a=a.z;b[12]=b[0]*c+b[4]*d+b[8]*a+b[12];b[13]=b[1]*c+b[5]*d+b[9]*a+b[13];b[14]=b[2]*c+b[6]*d+b[10]*a+b[14];b[15]=b[3]*c+b[7]*d+b[11]*a+b[15];return this},rotateX:function(a){var b=this.elements,c=b[4],d=b[5],e=b[6],f=b[7],g=b[8],h=b[9],i=b[10],j=b[11],l=Math.cos(a),a=Math.sin(a);b[4]=l*c+a*g;b[5]=l*d+a*h;b[6]=l*e+a*i;b[7]=l*f+a*j;b[8]=l*g-a*c;b[9]=l*h-a*d;b[10]=l*i-a*e;b[11]=l*j-a*f;return this},rotateY:function(a){var b=this.elements,c=b[0],d=b[1],e=b[2],f=b[3],g=b[8],h=
+b[9],i=b[10],j=b[11],l=Math.cos(a),a=Math.sin(a);b[0]=l*c-a*g;b[1]=l*d-a*h;b[2]=l*e-a*i;b[3]=l*f-a*j;b[8]=l*g+a*c;b[9]=l*h+a*d;b[10]=l*i+a*e;b[11]=l*j+a*f;return this},rotateZ:function(a){var b=this.elements,c=b[0],d=b[1],e=b[2],f=b[3],g=b[4],h=b[5],i=b[6],j=b[7],l=Math.cos(a),a=Math.sin(a);b[0]=l*c+a*g;b[1]=l*d+a*h;b[2]=l*e+a*i;b[3]=l*f+a*j;b[4]=l*g-a*c;b[5]=l*h-a*d;b[6]=l*i-a*e;b[7]=l*j-a*f;return this},rotateByAxis:function(a,b){var c=this.elements;if(1===a.x&&0===a.y&&0===a.z)return this.rotateX(b);
+if(0===a.x&&1===a.y&&0===a.z)return this.rotateY(b);if(0===a.x&&0===a.y&&1===a.z)return this.rotateZ(b);var d=a.x,e=a.y,f=a.z,g=Math.sqrt(d*d+e*e+f*f),d=d/g,e=e/g,f=f/g,g=d*d,h=e*e,i=f*f,j=Math.cos(b),l=Math.sin(b),n=1-j,m=d*e*n,r=d*f*n,n=e*f*n,d=d*l,u=e*l,l=f*l,f=g+(1-g)*j,g=m+l,e=r-u,m=m-l,h=h+(1-h)*j,l=n+d,r=r+u,n=n-d,i=i+(1-i)*j,j=c[0],d=c[1],u=c[2],p=c[3],q=c[4],w=c[5],v=c[6],z=c[7],y=c[8],t=c[9],D=c[10],C=c[11];c[0]=f*j+g*q+e*y;c[1]=f*d+g*w+e*t;c[2]=f*u+g*v+e*D;c[3]=f*p+g*z+e*C;c[4]=m*j+h*q+
+l*y;c[5]=m*d+h*w+l*t;c[6]=m*u+h*v+l*D;c[7]=m*p+h*z+l*C;c[8]=r*j+n*q+i*y;c[9]=r*d+n*w+i*t;c[10]=r*u+n*v+i*D;c[11]=r*p+n*z+i*C;return this},scale:function(a){var b=this.elements,c=a.x,d=a.y,a=a.z;b[0]*=c;b[4]*=d;b[8]*=a;b[1]*=c;b[5]*=d;b[9]*=a;b[2]*=c;b[6]*=d;b[10]*=a;b[3]*=c;b[7]*=d;b[11]*=a;return this},getMaxScaleOnAxis:function(){var a=this.elements;return Math.sqrt(Math.max(a[0]*a[0]+a[1]*a[1]+a[2]*a[2],Math.max(a[4]*a[4]+a[5]*a[5]+a[6]*a[6],a[8]*a[8]+a[9]*a[9]+a[10]*a[10])))},makeTranslation:function(a,
+b,c){this.set(1,0,0,a,0,1,0,b,0,0,1,c,0,0,0,1);return this},makeRotationX:function(a){var b=Math.cos(a),a=Math.sin(a);this.set(1,0,0,0,0,b,-a,0,0,a,b,0,0,0,0,1);return this},makeRotationY:function(a){var b=Math.cos(a),a=Math.sin(a);this.set(b,0,a,0,0,1,0,0,-a,0,b,0,0,0,0,1);return this},makeRotationZ:function(a){var b=Math.cos(a),a=Math.sin(a);this.set(b,-a,0,0,a,b,0,0,0,0,1,0,0,0,0,1);return this},makeRotationAxis:function(a,b){var c=Math.cos(b),d=Math.sin(b),e=1-c,f=a.x,g=a.y,h=a.z,i=e*f,j=e*g;
+this.set(i*f+c,i*g-d*h,i*h+d*g,0,i*g+d*h,j*g+c,j*h-d*f,0,i*h-d*g,j*h+d*f,e*h*h+c,0,0,0,0,1);return this},makeScale:function(a,b,c){this.set(a,0,0,0,0,b,0,0,0,0,c,0,0,0,0,1);return this},makeFrustum:function(a,b,c,d,e,f){var g=this.elements;g[0]=2*e/(b-a);g[4]=0;g[8]=(b+a)/(b-a);g[12]=0;g[1]=0;g[5]=2*e/(d-c);g[9]=(d+c)/(d-c);g[13]=0;g[2]=0;g[6]=0;g[10]=-(f+e)/(f-e);g[14]=-2*f*e/(f-e);g[3]=0;g[7]=0;g[11]=-1;g[15]=0;return this},makePerspective:function(a,b,c,d){var a=c*Math.tan(THREE.Math.degToRad(0.5*
+a)),e=-a;return this.makeFrustum(e*b,a*b,e,a,c,d)},makeOrthographic:function(a,b,c,d,e,f){var g=this.elements,h=b-a,i=c-d,j=f-e;g[0]=2/h;g[4]=0;g[8]=0;g[12]=-((b+a)/h);g[1]=0;g[5]=2/i;g[9]=0;g[13]=-((c+d)/i);g[2]=0;g[6]=0;g[10]=-2/j;g[14]=-((f+e)/j);g[3]=0;g[7]=0;g[11]=0;g[15]=1;return this},clone:function(){var a=this.elements;return new THREE.Matrix4(a[0],a[4],a[8],a[12],a[1],a[5],a[9],a[13],a[2],a[6],a[10],a[14],a[3],a[7],a[11],a[15])}});THREE.Ray=function(a,b){this.origin=void 0!==a?a:new THREE.Vector3;this.direction=void 0!==b?b:new THREE.Vector3};
 THREE.extend(THREE.Ray.prototype,{set:function(a,b){this.origin.copy(a);this.direction.copy(b);return this},copy:function(a){this.origin.copy(a.origin);this.direction.copy(a.direction);return this},at:function(a,b){return(b||new THREE.Vector3).copy(this.direction).multiplyScalar(a).add(this.origin)},recast:function(){var a=new THREE.Vector3;return function(b){this.origin.copy(this.at(b,a));return this}}(),closestPointToPoint:function(a,b){var c=b||new THREE.Vector3;c.subVectors(a,this.origin);var d=
 THREE.extend(THREE.Ray.prototype,{set:function(a,b){this.origin.copy(a);this.direction.copy(b);return this},copy:function(a){this.origin.copy(a.origin);this.direction.copy(a.direction);return this},at:function(a,b){return(b||new THREE.Vector3).copy(this.direction).multiplyScalar(a).add(this.origin)},recast:function(){var a=new THREE.Vector3;return function(b){this.origin.copy(this.at(b,a));return this}}(),closestPointToPoint:function(a,b){var c=b||new THREE.Vector3;c.subVectors(a,this.origin);var d=
 c.dot(this.direction);return c.copy(this.direction).multiplyScalar(d).add(this.origin)},distanceToPoint:function(){var a=new THREE.Vector3;return function(b){var c=a.subVectors(b,this.origin).dot(this.direction);a.copy(this.direction).multiplyScalar(c).add(this.origin);return a.distanceTo(b)}}(),isIntersectionSphere:function(a){return this.distanceToPoint(a.center)<=a.radius},isIntersectionPlane:function(a){return 0!=a.normal.dot(this.direction)||0==a.distanceToPoint(this.origin)?!0:!1},distanceToPlane:function(a){var b=
 c.dot(this.direction);return c.copy(this.direction).multiplyScalar(d).add(this.origin)},distanceToPoint:function(){var a=new THREE.Vector3;return function(b){var c=a.subVectors(b,this.origin).dot(this.direction);a.copy(this.direction).multiplyScalar(c).add(this.origin);return a.distanceTo(b)}}(),isIntersectionSphere:function(a){return this.distanceToPoint(a.center)<=a.radius},isIntersectionPlane:function(a){return 0!=a.normal.dot(this.direction)||0==a.distanceToPoint(this.origin)?!0:!1},distanceToPlane:function(a){var b=
 a.normal.dot(this.direction);if(0==b){if(0==a.distanceToPoint(this.origin))return 0}else return-(this.origin.dot(a.normal)+a.constant)/b},intersectPlane:function(a,b){var c=this.distanceToPlane(a);return void 0===c?void 0:this.at(c,b)},applyMatrix4:function(a){this.direction.add(this.origin).applyMatrix4(a);this.origin.applyMatrix4(a);this.direction.sub(this.origin);return this},equals:function(a){return a.origin.equals(this.origin)&&a.direction.equals(this.direction)},clone:function(){return(new THREE.Ray).copy(this)}});THREE.Sphere=function(a,b){this.center=void 0!==a?a:new THREE.Vector3;this.radius=void 0!==b?b:0};
 a.normal.dot(this.direction);if(0==b){if(0==a.distanceToPoint(this.origin))return 0}else return-(this.origin.dot(a.normal)+a.constant)/b},intersectPlane:function(a,b){var c=this.distanceToPlane(a);return void 0===c?void 0:this.at(c,b)},applyMatrix4:function(a){this.direction.add(this.origin).applyMatrix4(a);this.origin.applyMatrix4(a);this.direction.sub(this.origin);return this},equals:function(a){return a.origin.equals(this.origin)&&a.direction.equals(this.direction)},clone:function(){return(new THREE.Ray).copy(this)}});THREE.Sphere=function(a,b){this.center=void 0!==a?a:new THREE.Vector3;this.radius=void 0!==b?b:0};
 THREE.extend(THREE.Sphere.prototype,{set:function(a,b){this.center.copy(a);this.radius=b;return this},setFromCenterAndPoints:function(a,b){for(var c=0,d=0,e=b.length;d<e;d++)var f=a.distanceToSquared(b[d]),c=Math.max(c,f);this.center=a;this.radius=Math.sqrt(c);return this},copy:function(a){this.center.copy(a.center);this.radius=a.radius;return this},empty:function(){return 0>=this.radius},containsPoint:function(a){return a.distanceToSquared(this.center)<=this.radius*this.radius},distanceToPoint:function(a){return a.distanceTo(this.center)-
 THREE.extend(THREE.Sphere.prototype,{set:function(a,b){this.center.copy(a);this.radius=b;return this},setFromCenterAndPoints:function(a,b){for(var c=0,d=0,e=b.length;d<e;d++)var f=a.distanceToSquared(b[d]),c=Math.max(c,f);this.center=a;this.radius=Math.sqrt(c);return this},copy:function(a){this.center.copy(a.center);this.radius=a.radius;return this},empty:function(){return 0>=this.radius},containsPoint:function(a){return a.distanceToSquared(this.center)<=this.radius*this.radius},distanceToPoint:function(a){return a.distanceTo(this.center)-
 this.radius},intersectsSphere:function(a){var b=this.radius+a.radius;return a.center.distanceToSquared(this.center)<=b*b},clampPoint:function(a,b){var c=this.center.distanceToSquared(a),d=b||new THREE.Vector3;d.copy(a);c>this.radius*this.radius&&(d.sub(this.center).normalize(),d.multiplyScalar(this.radius).add(this.center));return d},getBoundingBox:function(a){a=a||new THREE.Box3;a.set(this.center,this.center);a.expandByScalar(this.radius);return a},applyMatrix4:function(a){this.center.applyMatrix4(a);
 this.radius},intersectsSphere:function(a){var b=this.radius+a.radius;return a.center.distanceToSquared(this.center)<=b*b},clampPoint:function(a,b){var c=this.center.distanceToSquared(a),d=b||new THREE.Vector3;d.copy(a);c>this.radius*this.radius&&(d.sub(this.center).normalize(),d.multiplyScalar(this.radius).add(this.center));return d},getBoundingBox:function(a){a=a||new THREE.Box3;a.set(this.center,this.center);a.expandByScalar(this.radius);return a},applyMatrix4:function(a){this.center.applyMatrix4(a);
 this.radius*=a.getMaxScaleOnAxis();return this},translate:function(a){this.center.add(a);return this},equals:function(a){return a.center.equals(this.center)&&a.radius===this.radius},clone:function(){return(new THREE.Sphere).copy(this)}});THREE.Frustum=function(a,b,c,d,e,f){this.planes=[void 0!==a?a:new THREE.Plane,void 0!==b?b:new THREE.Plane,void 0!==c?c:new THREE.Plane,void 0!==d?d:new THREE.Plane,void 0!==e?e:new THREE.Plane,void 0!==f?f:new THREE.Plane]};
 this.radius*=a.getMaxScaleOnAxis();return this},translate:function(a){this.center.add(a);return this},equals:function(a){return a.center.equals(this.center)&&a.radius===this.radius},clone:function(){return(new THREE.Sphere).copy(this)}});THREE.Frustum=function(a,b,c,d,e,f){this.planes=[void 0!==a?a:new THREE.Plane,void 0!==b?b:new THREE.Plane,void 0!==c?c:new THREE.Plane,void 0!==d?d:new THREE.Plane,void 0!==e?e:new THREE.Plane,void 0!==f?f:new THREE.Plane]};
-THREE.extend(THREE.Frustum.prototype,{set:function(a,b,c,d,e,f){var g=this.planes;g[0].copy(a);g[1].copy(b);g[2].copy(c);g[3].copy(d);g[4].copy(e);g[5].copy(f);return this},copy:function(a){for(var b=this.planes,c=0;6>c;c++)b[c].copy(a.planes[c]);return this},setFromMatrix:function(a){var b=this.planes,c=a.elements,a=c[0],d=c[1],e=c[2],f=c[3],g=c[4],h=c[5],i=c[6],k=c[7],l=c[8],n=c[9],m=c[10],t=c[11],r=c[12],p=c[13],q=c[14],c=c[15];b[0].setComponents(f-a,k-g,t-l,c-r).normalize();b[1].setComponents(f+
-a,k+g,t+l,c+r).normalize();b[2].setComponents(f+d,k+h,t+n,c+p).normalize();b[3].setComponents(f-d,k-h,t-n,c-p).normalize();b[4].setComponents(f-e,k-i,t-m,c-q).normalize();b[5].setComponents(f+e,k+i,t+m,c+q).normalize();return this},intersectsObject:function(){var a=new THREE.Vector3;return function(b){var c=b.matrixWorld,d=this.planes,b=-b.geometry.boundingSphere.radius*c.getMaxScaleOnAxis();a.getPositionFromMatrix(c);for(c=0;6>c;c++)if(d[c].distanceToPoint(a)<b)return!1;return!0}}(),intersectsSphere:function(a){for(var b=
+THREE.extend(THREE.Frustum.prototype,{set:function(a,b,c,d,e,f){var g=this.planes;g[0].copy(a);g[1].copy(b);g[2].copy(c);g[3].copy(d);g[4].copy(e);g[5].copy(f);return this},copy:function(a){for(var b=this.planes,c=0;6>c;c++)b[c].copy(a.planes[c]);return this},setFromMatrix:function(a){var b=this.planes,c=a.elements,a=c[0],d=c[1],e=c[2],f=c[3],g=c[4],h=c[5],i=c[6],j=c[7],l=c[8],n=c[9],m=c[10],r=c[11],u=c[12],p=c[13],q=c[14],c=c[15];b[0].setComponents(f-a,j-g,r-l,c-u).normalize();b[1].setComponents(f+
+a,j+g,r+l,c+u).normalize();b[2].setComponents(f+d,j+h,r+n,c+p).normalize();b[3].setComponents(f-d,j-h,r-n,c-p).normalize();b[4].setComponents(f-e,j-i,r-m,c-q).normalize();b[5].setComponents(f+e,j+i,r+m,c+q).normalize();return this},intersectsObject:function(){var a=new THREE.Vector3;return function(b){var c=b.matrixWorld,d=this.planes,b=-b.geometry.boundingSphere.radius*c.getMaxScaleOnAxis();a.getPositionFromMatrix(c);for(c=0;6>c;c++)if(d[c].distanceToPoint(a)<b)return!1;return!0}}(),intersectsSphere:function(a){for(var b=
 this.planes,c=a.center,a=-a.radius,d=0;6>d;d++)if(b[d].distanceToPoint(c)<a)return!1;return!0},containsPoint:function(a){for(var b=this.planes,c=0;6>c;c++)if(0>b[c].distanceToPoint(a))return!1;return!0},clone:function(){return(new THREE.Frustum).copy(this)}});THREE.Plane=function(a,b){this.normal=void 0!==a?a:new THREE.Vector3(1,0,0);this.constant=void 0!==b?b:0};
 this.planes,c=a.center,a=-a.radius,d=0;6>d;d++)if(b[d].distanceToPoint(c)<a)return!1;return!0},containsPoint:function(a){for(var b=this.planes,c=0;6>c;c++)if(0>b[c].distanceToPoint(a))return!1;return!0},clone:function(){return(new THREE.Frustum).copy(this)}});THREE.Plane=function(a,b){this.normal=void 0!==a?a:new THREE.Vector3(1,0,0);this.constant=void 0!==b?b:0};
 THREE.extend(THREE.Plane.prototype,{set:function(a,b){this.normal.copy(a);this.constant=b;return this},setComponents:function(a,b,c,d){this.normal.set(a,b,c);this.constant=d;return this},setFromNormalAndCoplanarPoint:function(a,b){this.normal.copy(a);this.constant=-b.dot(this.normal);return this},setFromCoplanarPoints:function(){var a=new THREE.Vector3,b=new THREE.Vector3;return function(c,d,e){d=a.subVectors(e,d).cross(b.subVectors(c,d)).normalize();this.setFromNormalAndCoplanarPoint(d,c);return this}}(),
 THREE.extend(THREE.Plane.prototype,{set:function(a,b){this.normal.copy(a);this.constant=b;return this},setComponents:function(a,b,c,d){this.normal.set(a,b,c);this.constant=d;return this},setFromNormalAndCoplanarPoint:function(a,b){this.normal.copy(a);this.constant=-b.dot(this.normal);return this},setFromCoplanarPoints:function(){var a=new THREE.Vector3,b=new THREE.Vector3;return function(c,d,e){d=a.subVectors(e,d).cross(b.subVectors(c,d)).normalize();this.setFromNormalAndCoplanarPoint(d,c);return this}}(),
 copy:function(a){this.normal.copy(a.normal);this.constant=a.constant;return this},normalize:function(){var a=1/this.normal.length();this.normal.multiplyScalar(a);this.constant*=a;return this},negate:function(){this.constant*=-1;this.normal.negate();return this},distanceToPoint:function(a){return this.normal.dot(a)+this.constant},distanceToSphere:function(a){return this.distanceToPoint(a.center)-a.radius},projectPoint:function(a,b){return this.orthoPoint(a,b).sub(a).negate()},orthoPoint:function(a,
 copy:function(a){this.normal.copy(a.normal);this.constant=a.constant;return this},normalize:function(){var a=1/this.normal.length();this.normal.multiplyScalar(a);this.constant*=a;return this},negate:function(){this.constant*=-1;this.normal.negate();return this},distanceToPoint:function(a){return this.normal.dot(a)+this.constant},distanceToSphere:function(a){return this.distanceToPoint(a.center)-a.radius},projectPoint:function(a,b){return this.orthoPoint(a,b).sub(a).negate()},orthoPoint:function(a,
 b){var c=this.distanceToPoint(a);return(b||new THREE.Vector3).copy(this.normal).multiplyScalar(c)},isIntersectionLine:function(a){var b=this.distanceToPoint(a.start),a=this.distanceToPoint(a.end);return 0>b&&0<a||0>a&&0<b},intersectLine:function(){var a=new THREE.Vector3;return function(b,c){var d=c||new THREE.Vector3,e=b.delta(a),f=this.normal.dot(e);if(0==f){if(0==this.distanceToPoint(b.start))return d.copy(b.start)}else return f=-(b.start.dot(this.normal)+this.constant)/f,0>f||1<f?void 0:d.copy(e).multiplyScalar(f).add(b.start)}}(),
 b){var c=this.distanceToPoint(a);return(b||new THREE.Vector3).copy(this.normal).multiplyScalar(c)},isIntersectionLine:function(a){var b=this.distanceToPoint(a.start),a=this.distanceToPoint(a.end);return 0>b&&0<a||0>a&&0<b},intersectLine:function(){var a=new THREE.Vector3;return function(b,c){var d=c||new THREE.Vector3,e=b.delta(a),f=this.normal.dot(e);if(0==f){if(0==this.distanceToPoint(b.start))return d.copy(b.start)}else return f=-(b.start.dot(this.normal)+this.constant)/f,0>f||1<f?void 0:d.copy(e).multiplyScalar(f).add(b.start)}}(),
 coplanarPoint:function(a){return(a||new THREE.Vector3).copy(this.normal).multiplyScalar(-this.constant)},applyMatrix4:function(){var a=new THREE.Vector3,b=new THREE.Vector3;return function(c,d){var d=d||(new THREE.Matrix3).getInverse(c).transpose(),e=a.copy(this.normal).applyMatrix3(d),f=this.coplanarPoint(b);f.applyMatrix4(c);this.setFromNormalAndCoplanarPoint(e,f);return this}}(),translate:function(a){this.constant-=a.dot(this.normal);return this},equals:function(a){return a.normal.equals(this.normal)&&
 coplanarPoint:function(a){return(a||new THREE.Vector3).copy(this.normal).multiplyScalar(-this.constant)},applyMatrix4:function(){var a=new THREE.Vector3,b=new THREE.Vector3;return function(c,d){var d=d||(new THREE.Matrix3).getInverse(c).transpose(),e=a.copy(this.normal).applyMatrix3(d),f=this.coplanarPoint(b);f.applyMatrix4(c);this.setFromNormalAndCoplanarPoint(e,f);return this}}(),translate:function(a){this.constant-=a.dot(this.normal);return this},equals:function(a){return a.normal.equals(this.normal)&&
 a.constant==this.constant},clone:function(){return(new THREE.Plane).copy(this)}});THREE.Math={clamp:function(a,b,c){return a<b?b:a>c?c:a},clampBottom:function(a,b){return a<b?b:a},mapLinear:function(a,b,c,d,e){return d+(a-b)*(e-d)/(c-b)},smoothstep:function(a,b,c){if(a<=b)return 0;if(a>=c)return 1;a=(a-b)/(c-b);return a*a*(3-2*a)},smootherstep:function(a,b,c){if(a<=b)return 0;if(a>=c)return 1;a=(a-b)/(c-b);return a*a*a*(a*(6*a-15)+10)},random16:function(){return(65280*Math.random()+255*Math.random())/65535},randInt:function(a,b){return a+Math.floor(Math.random()*(b-a+1))},randFloat:function(a,
 a.constant==this.constant},clone:function(){return(new THREE.Plane).copy(this)}});THREE.Math={clamp:function(a,b,c){return a<b?b:a>c?c:a},clampBottom:function(a,b){return a<b?b:a},mapLinear:function(a,b,c,d,e){return d+(a-b)*(e-d)/(c-b)},smoothstep:function(a,b,c){if(a<=b)return 0;if(a>=c)return 1;a=(a-b)/(c-b);return a*a*(3-2*a)},smootherstep:function(a,b,c){if(a<=b)return 0;if(a>=c)return 1;a=(a-b)/(c-b);return a*a*a*(a*(6*a-15)+10)},random16:function(){return(65280*Math.random()+255*Math.random())/65535},randInt:function(a,b){return a+Math.floor(Math.random()*(b-a+1))},randFloat:function(a,
-b){return a+Math.random()*(b-a)},randFloatSpread:function(a){return a*(0.5-Math.random())},sign:function(a){return 0>a?-1:0<a?1:0},degToRad:function(){var a=Math.PI/180;return function(b){return b*a}}(),radToDeg:function(){var a=180/Math.PI;return function(b){return b*a}}()};THREE.Spline=function(a){function b(a,b,c,d,e,f,g){a=0.5*(c-a);d=0.5*(d-b);return(2*(b-c)+a+d)*g+(-3*(b-c)-2*a-d)*f+a*e+b}this.points=a;var c=[],d={x:0,y:0,z:0},e,f,g,h,i,k,l,n,m;this.initFromArray=function(a){this.points=[];for(var b=0;b<a.length;b++)this.points[b]={x:a[b][0],y:a[b][1],z:a[b][2]}};this.getPoint=function(a){e=(this.points.length-1)*a;f=Math.floor(e);g=e-f;c[0]=0===f?f:f-1;c[1]=f;c[2]=f>this.points.length-2?this.points.length-1:f+1;c[3]=f>this.points.length-3?this.points.length-1:
-f+2;k=this.points[c[0]];l=this.points[c[1]];n=this.points[c[2]];m=this.points[c[3]];h=g*g;i=g*h;d.x=b(k.x,l.x,n.x,m.x,g,h,i);d.y=b(k.y,l.y,n.y,m.y,g,h,i);d.z=b(k.z,l.z,n.z,m.z,g,h,i);return d};this.getControlPointsArray=function(){var a,b,c=this.points.length,d=[];for(a=0;a<c;a++)b=this.points[a],d[a]=[b.x,b.y,b.z];return d};this.getLength=function(a){var b,c,d,e=b=b=0,f=new THREE.Vector3,g=new THREE.Vector3,h=[],i=0;h[0]=0;a||(a=100);c=this.points.length*a;f.copy(this.points[0]);for(a=1;a<c;a++)b=
-a/c,d=this.getPoint(b),g.copy(d),i+=g.distanceTo(f),f.copy(d),b*=this.points.length-1,b=Math.floor(b),b!=e&&(h[b]=i,e=b);h[h.length]=i;return{chunks:h,total:i}};this.reparametrizeByArcLength=function(a){var b,c,d,e,f,g,h=[],i=new THREE.Vector3,k=this.getLength();h.push(i.copy(this.points[0]).clone());for(b=1;b<this.points.length;b++){c=k.chunks[b]-k.chunks[b-1];g=Math.ceil(a*c/k.total);e=(b-1)/(this.points.length-1);f=b/(this.points.length-1);for(c=1;c<g-1;c++)d=e+c*(1/g)*(f-e),d=this.getPoint(d),
-h.push(i.copy(d).clone());h.push(i.copy(this.points[b]).clone())}this.points=h}};THREE.Triangle=function(a,b,c){this.a=void 0!==a?a:new THREE.Vector3;this.b=void 0!==b?b:new THREE.Vector3;this.c=void 0!==c?c:new THREE.Vector3};THREE.Triangle.normal=function(){var a=new THREE.Vector3;return function(b,c,d,e){e=e||new THREE.Vector3;e.subVectors(d,c);a.subVectors(b,c);e.cross(a);b=e.lengthSq();return 0<b?e.multiplyScalar(1/Math.sqrt(b)):e.set(0,0,0)}}();
-THREE.Triangle.barycoordFromPoint=function(){var a=new THREE.Vector3,b=new THREE.Vector3,c=new THREE.Vector3;return function(d,e,f,g,h){a.subVectors(g,e);b.subVectors(f,e);c.subVectors(d,e);var d=a.dot(a),e=a.dot(b),f=a.dot(c),i=b.dot(b),g=b.dot(c),k=d*i-e*e,h=h||new THREE.Vector3;if(0==k)return h.set(-2,-1,-1);k=1/k;i=(i*f-e*g)*k;d=(d*g-e*f)*k;return h.set(1-i-d,d,i)}}();
+b){return a+Math.random()*(b-a)},randFloatSpread:function(a){return a*(0.5-Math.random())},sign:function(a){return 0>a?-1:0<a?1:0},degToRad:function(){var a=Math.PI/180;return function(b){return b*a}}(),radToDeg:function(){var a=180/Math.PI;return function(b){return b*a}}()};THREE.Spline=function(a){function b(a,b,c,d,e,f,g){a=0.5*(c-a);d=0.5*(d-b);return(2*(b-c)+a+d)*g+(-3*(b-c)-2*a-d)*f+a*e+b}this.points=a;var c=[],d={x:0,y:0,z:0},e,f,g,h,i,j,l,n,m;this.initFromArray=function(a){this.points=[];for(var b=0;b<a.length;b++)this.points[b]={x:a[b][0],y:a[b][1],z:a[b][2]}};this.getPoint=function(a){e=(this.points.length-1)*a;f=Math.floor(e);g=e-f;c[0]=0===f?f:f-1;c[1]=f;c[2]=f>this.points.length-2?this.points.length-1:f+1;c[3]=f>this.points.length-3?this.points.length-1:
+f+2;j=this.points[c[0]];l=this.points[c[1]];n=this.points[c[2]];m=this.points[c[3]];h=g*g;i=g*h;d.x=b(j.x,l.x,n.x,m.x,g,h,i);d.y=b(j.y,l.y,n.y,m.y,g,h,i);d.z=b(j.z,l.z,n.z,m.z,g,h,i);return d};this.getControlPointsArray=function(){var a,b,c=this.points.length,d=[];for(a=0;a<c;a++)b=this.points[a],d[a]=[b.x,b.y,b.z];return d};this.getLength=function(a){var b,c,d,e=b=b=0,f=new THREE.Vector3,g=new THREE.Vector3,i=[],h=0;i[0]=0;a||(a=100);c=this.points.length*a;f.copy(this.points[0]);for(a=1;a<c;a++)b=
+a/c,d=this.getPoint(b),g.copy(d),h+=g.distanceTo(f),f.copy(d),b*=this.points.length-1,b=Math.floor(b),b!=e&&(i[b]=h,e=b);i[i.length]=h;return{chunks:i,total:h}};this.reparametrizeByArcLength=function(a){var b,c,d,e,f,g,i=[],h=new THREE.Vector3,l=this.getLength();i.push(h.copy(this.points[0]).clone());for(b=1;b<this.points.length;b++){c=l.chunks[b]-l.chunks[b-1];g=Math.ceil(a*c/l.total);e=(b-1)/(this.points.length-1);f=b/(this.points.length-1);for(c=1;c<g-1;c++)d=e+c*(1/g)*(f-e),d=this.getPoint(d),
+i.push(h.copy(d).clone());i.push(h.copy(this.points[b]).clone())}this.points=i}};THREE.Triangle=function(a,b,c){this.a=void 0!==a?a:new THREE.Vector3;this.b=void 0!==b?b:new THREE.Vector3;this.c=void 0!==c?c:new THREE.Vector3};THREE.Triangle.normal=function(){var a=new THREE.Vector3;return function(b,c,d,e){e=e||new THREE.Vector3;e.subVectors(d,c);a.subVectors(b,c);e.cross(a);b=e.lengthSq();return 0<b?e.multiplyScalar(1/Math.sqrt(b)):e.set(0,0,0)}}();
+THREE.Triangle.barycoordFromPoint=function(){var a=new THREE.Vector3,b=new THREE.Vector3,c=new THREE.Vector3;return function(d,e,f,g,h){a.subVectors(g,e);b.subVectors(f,e);c.subVectors(d,e);var d=a.dot(a),e=a.dot(b),f=a.dot(c),i=b.dot(b),g=b.dot(c),j=d*i-e*e,h=h||new THREE.Vector3;if(0==j)return h.set(-2,-1,-1);j=1/j;i=(i*f-e*g)*j;d=(d*g-e*f)*j;return h.set(1-i-d,d,i)}}();
 THREE.Triangle.containsPoint=function(){var a=new THREE.Vector3;return function(b,c,d,e){b=THREE.Triangle.barycoordFromPoint(b,c,d,e,a);return 0<=b.x&&0<=b.y&&1>=b.x+b.y}}();
 THREE.Triangle.containsPoint=function(){var a=new THREE.Vector3;return function(b,c,d,e){b=THREE.Triangle.barycoordFromPoint(b,c,d,e,a);return 0<=b.x&&0<=b.y&&1>=b.x+b.y}}();
 THREE.extend(THREE.Triangle.prototype,{constructor:THREE.Triangle,set:function(a,b,c){this.a.copy(a);this.b.copy(b);this.c.copy(c);return this},setFromPointsAndIndices:function(a,b,c,d){this.a.copy(a[b]);this.b.copy(a[c]);this.c.copy(a[d]);return this},copy:function(a){this.a.copy(a.a);this.b.copy(a.b);this.c.copy(a.c);return this},area:function(){var a=new THREE.Vector3,b=new THREE.Vector3;return function(){a.subVectors(this.c,this.b);b.subVectors(this.a,this.b);return 0.5*a.cross(b).length()}}(),
 THREE.extend(THREE.Triangle.prototype,{constructor:THREE.Triangle,set:function(a,b,c){this.a.copy(a);this.b.copy(b);this.c.copy(c);return this},setFromPointsAndIndices:function(a,b,c,d){this.a.copy(a[b]);this.b.copy(a[c]);this.c.copy(a[d]);return this},copy:function(a){this.a.copy(a.a);this.b.copy(a.b);this.c.copy(a.c);return this},area:function(){var a=new THREE.Vector3,b=new THREE.Vector3;return function(){a.subVectors(this.c,this.b);b.subVectors(this.a,this.b);return 0.5*a.cross(b).length()}}(),
 midpoint:function(a){return(a||new THREE.Vector3).addVectors(this.a,this.b).add(this.c).multiplyScalar(1/3)},normal:function(a){return THREE.Triangle.normal(this.a,this.b,this.c,a)},plane:function(a){return(a||new THREE.Plane).setFromCoplanarPoints(this.a,this.b,this.c)},barycoordFromPoint:function(a,b){return THREE.Triangle.barycoordFromPoint(a,this.a,this.b,this.c,b)},containsPoint:function(a){return THREE.Triangle.containsPoint(a,this.a,this.b,this.c)},equals:function(a){return a.a.equals(this.a)&&
 midpoint:function(a){return(a||new THREE.Vector3).addVectors(this.a,this.b).add(this.c).multiplyScalar(1/3)},normal:function(a){return THREE.Triangle.normal(this.a,this.b,this.c,a)},plane:function(a){return(a||new THREE.Plane).setFromCoplanarPoints(this.a,this.b,this.c)},barycoordFromPoint:function(a,b){return THREE.Triangle.barycoordFromPoint(a,this.a,this.b,this.c,b)},containsPoint:function(a){return THREE.Triangle.containsPoint(a,this.a,this.b,this.c)},equals:function(a){return a.a.equals(this.a)&&
 a.b.equals(this.b)&&a.c.equals(this.c)},clone:function(){return(new THREE.Triangle).copy(this)}});THREE.Vertex=function(a){console.warn("THREE.Vertex has been DEPRECATED. Use THREE.Vector3 instead.");return a};THREE.UV=function(a,b){console.warn("THREE.UV has been DEPRECATED. Use THREE.Vector2 instead.");return new THREE.Vector2(a,b)};THREE.Clock=function(a){this.autoStart=void 0!==a?a:!0;this.elapsedTime=this.oldTime=this.startTime=0;this.running=!1};
 a.b.equals(this.b)&&a.c.equals(this.c)},clone:function(){return(new THREE.Triangle).copy(this)}});THREE.Vertex=function(a){console.warn("THREE.Vertex has been DEPRECATED. Use THREE.Vector3 instead.");return a};THREE.UV=function(a,b){console.warn("THREE.UV has been DEPRECATED. Use THREE.Vector2 instead.");return new THREE.Vector2(a,b)};THREE.Clock=function(a){this.autoStart=void 0!==a?a:!0;this.elapsedTime=this.oldTime=this.startTime=0;this.running=!1};
 THREE.extend(THREE.Clock.prototype,{start:function(){this.oldTime=this.startTime=void 0!==window.performance&&void 0!==window.performance.now?window.performance.now():Date.now();this.running=!0},stop:function(){this.getElapsedTime();this.running=!1},getElapsedTime:function(){this.getDelta();return this.elapsedTime},getDelta:function(){var a=0;this.autoStart&&!this.running&&this.start();if(this.running){var b=void 0!==window.performance&&void 0!==window.performance.now?window.performance.now():Date.now(),
 THREE.extend(THREE.Clock.prototype,{start:function(){this.oldTime=this.startTime=void 0!==window.performance&&void 0!==window.performance.now?window.performance.now():Date.now();this.running=!0},stop:function(){this.getElapsedTime();this.running=!1},getElapsedTime:function(){this.getDelta();return this.elapsedTime},getDelta:function(){var a=0;this.autoStart&&!this.running&&this.start();if(this.running){var b=void 0!==window.performance&&void 0!==window.performance.now?window.performance.now():Date.now(),
-a=0.001*(b-this.oldTime);this.oldTime=b;this.elapsedTime+=a}return a}});THREE.EventDispatcher=function(){var a={};this.addEventListener=function(b,c){void 0===a[b]&&(a[b]=[]);-1===a[b].indexOf(c)&&a[b].push(c)};this.removeEventListener=function(b,c){var d=a[b].indexOf(c);-1!==d&&a[b].splice(d,1)};this.dispatchEvent=function(b){var c=a[b.type];if(void 0!==c){b.target=this;for(var d=0,e=c.length;d<e;d++)c[d].call(this,b)}}};(function(a){a.Raycaster=function(b,c,d,e){this.ray=new a.Ray(b,c);0<this.ray.direction.lengthSq()&&this.ray.direction.normalize();this.near=d||0;this.far=e||Infinity};var b=new a.Sphere,c=new a.Ray,d=new a.Plane,e=new a.Vector3,f=new a.Vector3,g=new a.Matrix4,h=function(a,b){return a.distance-b.distance},i=function(h,i,k){if(h instanceof a.Particle){f.getPositionFromMatrix(h.matrixWorld);i=i.ray.distanceToPoint(f);if(i>h.scale.x)return k;k.push({distance:i,point:h.position,face:null,object:h})}else if(h instanceof
-a.Mesh){f.getPositionFromMatrix(h.matrixWorld);b.set(f,h.geometry.boundingSphere.radius*h.matrixWorld.getMaxScaleOnAxis());if(!i.ray.isIntersectionSphere(b))return k;var t=h.geometry,r=t.vertices,p=h.material instanceof a.MeshFaceMaterial,q=!0===p?h.material.materials:null,y=h.material.side,v,z,s,C=i.precision;h.matrixRotationWorld.extractRotation(h.matrixWorld);g.getInverse(h.matrixWorld);c.copy(i.ray).applyMatrix4(g);for(var H=0,B=t.faces.length;H<B;H++){var w=t.faces[H],y=!0===p?q[w.materialIndex]:
-h.material;if(void 0!==y){d.setFromNormalAndCoplanarPoint(w.normal,r[w.a]);var I=c.distanceToPlane(d);if(!(Math.abs(I)<C)&&!(0>I)){y=y.side;if(y!==a.DoubleSide&&(v=c.direction.dot(d.normal),!(y===a.FrontSide?0>v:0<v)))continue;if(!(I<i.near||I>i.far)){e=c.at(I,e);if(w instanceof a.Face3){if(y=r[w.a],v=r[w.b],z=r[w.c],!a.Triangle.containsPoint(e,y,v,z))continue}else if(w instanceof a.Face4){if(y=r[w.a],v=r[w.b],z=r[w.c],s=r[w.d],!a.Triangle.containsPoint(e,y,v,s)&&!a.Triangle.containsPoint(e,v,z,s))continue}else throw Error("face type not supported");
-k.push({distance:I,point:i.ray.at(I),face:w,faceIndex:H,object:h})}}}}}},k=function(a,b,c){for(var a=a.getDescendants(),d=0,e=a.length;d<e;d++)i(a[d],b,c)};a.Raycaster.prototype.precision=1E-4;a.Raycaster.prototype.set=function(a,b){this.ray.set(a,b);0<this.ray.direction.length()&&this.ray.direction.normalize()};a.Raycaster.prototype.intersectObject=function(a,b){var c=[];!0===b&&k(a,this,c);i(a,this,c);c.sort(h);return c};a.Raycaster.prototype.intersectObjects=function(a,b){for(var c=[],d=0,e=a.length;d<
-e;d++)i(a[d],this,c),!0===b&&k(a[d],this,c);c.sort(h);return c}})(THREE);THREE.Object3D=function(){this.id=THREE.Object3DIdCount++;this.name="";this.properties={};this.parent=void 0;this.children=[];this.up=new THREE.Vector3(0,1,0);this.position=new THREE.Vector3;this.rotation=new THREE.Vector3;this.eulerOrder=THREE.Object3D.defaultEulerOrder;this.scale=new THREE.Vector3(1,1,1);this.renderDepth=null;this.rotationAutoUpdate=!0;this.matrix=new THREE.Matrix4;this.matrixWorld=new THREE.Matrix4;this.matrixRotationWorld=new THREE.Matrix4;this.matrixWorldNeedsUpdate=this.matrixAutoUpdate=
-!0;this.quaternion=new THREE.Quaternion;this.useQuaternion=!1;this.visible=!0;this.receiveShadow=this.castShadow=!1;this.frustumCulled=!0;this._vector=new THREE.Vector3};
-THREE.Object3D.prototype={constructor:THREE.Object3D,applyMatrix:function(){var a=new THREE.Matrix4;return function(b){this.matrix.multiplyMatrices(b,this.matrix);this.position.getPositionFromMatrix(this.matrix);this.scale.getScaleFromMatrix(this.matrix);a.extractRotation(this.matrix);!0===this.useQuaternion?this.quaternion.setFromRotationMatrix(a):this.rotation.setEulerFromRotationMatrix(a,this.eulerOrder)}}(),translate:function(a,b){b.transformDirection(this.matrix);b.multiplyScalar(a);this.position.add(b)},
-translateX:function(a){this.translate(a,this._vector.set(1,0,0))},translateY:function(a){this.translate(a,this._vector.set(0,1,0))},translateZ:function(a){this.translate(a,this._vector.set(0,0,1))},localToWorld:function(a){return a.applyMatrix4(this.matrixWorld)},worldToLocal:function(){var a=new THREE.Matrix4;return function(b){return b.applyMatrix4(a.getInverse(this.matrixWorld))}}(),lookAt:function(){var a=new THREE.Matrix4;return function(b){a.lookAt(b,this.position,this.up);!0===this.useQuaternion?
-this.quaternion.setFromRotationMatrix(a):this.rotation.setEulerFromRotationMatrix(a,this.eulerOrder)}}(),add:function(a){if(a===this)console.warn("THREE.Object3D.add: An object can't be added as a child of itself.");else if(a instanceof THREE.Object3D){void 0!==a.parent&&a.parent.remove(a);a.parent=this;this.children.push(a);for(var b=this;void 0!==b.parent;)b=b.parent;void 0!==b&&b instanceof THREE.Scene&&b.__addObject(a)}},remove:function(a){var b=this.children.indexOf(a);if(-1!==b){a.parent=void 0;
-this.children.splice(b,1);for(b=this;void 0!==b.parent;)b=b.parent;void 0!==b&&b instanceof THREE.Scene&&b.__removeObject(a)}},traverse:function(a){a(this);for(var b=0,c=this.children.length;b<c;b++)this.children[b].traverse(a)},getChildByName:function(a,b){for(var c=0,d=this.children.length;c<d;c++){var e=this.children[c];if(e.name===a||!0===b&&(e=e.getChildByName(a,b),void 0!==e))return e}},getDescendants:function(a){void 0===a&&(a=[]);Array.prototype.push.apply(a,this.children);for(var b=0,c=this.children.length;b<
-c;b++)this.children[b].getDescendants(a);return a},updateMatrix:function(){this.matrix.setPosition(this.position);!1===this.useQuaternion?this.matrix.setRotationFromEuler(this.rotation,this.eulerOrder):this.matrix.setRotationFromQuaternion(this.quaternion);(1!==this.scale.x||1!==this.scale.y||1!==this.scale.z)&&this.matrix.scale(this.scale);this.matrixWorldNeedsUpdate=!0},updateMatrixWorld:function(a){!0===this.matrixAutoUpdate&&this.updateMatrix();if(!0===this.matrixWorldNeedsUpdate||!0===a)void 0===
-this.parent?this.matrixWorld.copy(this.matrix):this.matrixWorld.multiplyMatrices(this.parent.matrixWorld,this.matrix),this.matrixWorldNeedsUpdate=!1,a=!0;for(var b=0,c=this.children.length;b<c;b++)this.children[b].updateMatrixWorld(a)},clone:function(a){void 0===a&&(a=new THREE.Object3D);a.name=this.name;a.up.copy(this.up);a.position.copy(this.position);a.rotation instanceof THREE.Vector3&&a.rotation.copy(this.rotation);a.eulerOrder=this.eulerOrder;a.scale.copy(this.scale);a.renderDepth=this.renderDepth;
-a.rotationAutoUpdate=this.rotationAutoUpdate;a.matrix.copy(this.matrix);a.matrixWorld.copy(this.matrixWorld);a.matrixRotationWorld.copy(this.matrixRotationWorld);a.matrixAutoUpdate=this.matrixAutoUpdate;a.matrixWorldNeedsUpdate=this.matrixWorldNeedsUpdate;a.quaternion.copy(this.quaternion);a.useQuaternion=this.useQuaternion;a.visible=this.visible;a.castShadow=this.castShadow;a.receiveShadow=this.receiveShadow;a.frustumCulled=this.frustumCulled;for(var b=0;b<this.children.length;b++)a.add(this.children[b].clone());
-return a}};THREE.Object3D.defaultEulerOrder="XYZ";THREE.Object3DIdCount=0;THREE.Projector=function(){function a(){if(f===h){var a=new THREE.RenderableObject;g.push(a);h++;f++;return a}return g[f++]}function b(){if(k===n){var a=new THREE.RenderableVertex;l.push(a);n++;k++;return a}return l[k++]}function c(a,b){return b.z-a.z}function d(a,b){var c=0,d=1,e=a.z+a.w,f=b.z+b.w,g=-a.z+a.w,h=-b.z+b.w;if(0<=e&&0<=f&&0<=g&&0<=h)return!0;if(0>e&&0>f||0>g&&0>h)return!1;0>e?c=Math.max(c,e/(e-f)):0>f&&(d=Math.min(d,e/(e-f)));0>g?c=Math.max(c,g/(g-h)):0>h&&(d=Math.min(d,g/(g-h)));if(d<
-c)return!1;a.lerp(b,c);b.lerp(a,1-d);return!0}var e,f,g=[],h=0,i,k,l=[],n=0,m,t,r=[],p=0,q,y=[],v=0,z,s,C=[],H=0,B,w,I=[],J=0,E={objects:[],sprites:[],lights:[],elements:[]},Z=new THREE.Vector3,A=new THREE.Vector4,U=new THREE.Box3(new THREE.Vector3(-1,-1,-1),new THREE.Vector3(1,1,1)),F=new THREE.Box3,G=Array(3),K=Array(4),N=new THREE.Matrix4,fa=new THREE.Matrix4,ma,eb=new THREE.Matrix4,M=new THREE.Matrix3,T=new THREE.Matrix3,ja=new THREE.Vector3,L=new THREE.Frustum,ca=new THREE.Vector4,ra=new THREE.Vector4;
-this.projectVector=function(a,b){b.matrixWorldInverse.getInverse(b.matrixWorld);fa.multiplyMatrices(b.projectionMatrix,b.matrixWorldInverse);return a.applyProjection(fa)};this.unprojectVector=function(a,b){b.projectionMatrixInverse.getInverse(b.projectionMatrix);fa.multiplyMatrices(b.matrixWorld,b.projectionMatrixInverse);return a.applyProjection(fa)};this.pickingRay=function(a,b){a.z=-1;var c=new THREE.Vector3(a.x,a.y,1);this.unprojectVector(a,b);this.unprojectVector(c,b);c.sub(a).normalize();return new THREE.Raycaster(a,
-c)};this.projectScene=function(g,h,n,db){var La=!1,Oa,ea,ha,V,$,Y,ia,sa,na,Pa,Ba,fb,jb;w=s=q=t=0;E.elements.length=0;g.updateMatrixWorld();void 0===h.parent&&h.updateMatrixWorld();N.copy(h.matrixWorldInverse.getInverse(h.matrixWorld));fa.multiplyMatrices(h.projectionMatrix,N);T.getInverse(N);T.transpose();L.setFromMatrix(fa);f=0;E.objects.length=0;E.sprites.length=0;E.lights.length=0;var Sa=function(b){for(var c=0,d=b.children.length;c<d;c++){var f=b.children[c];if(!1!==f.visible){if(f instanceof
-THREE.Light)E.lights.push(f);else if(f instanceof THREE.Mesh||f instanceof THREE.Line){if(!1===f.frustumCulled||!0===L.intersectsObject(f))e=a(),e.object=f,null!==f.renderDepth?e.z=f.renderDepth:(Z.getPositionFromMatrix(f.matrixWorld),Z.applyProjection(fa),e.z=Z.z),E.objects.push(e)}else f instanceof THREE.Sprite||f instanceof THREE.Particle?(e=a(),e.object=f,null!==f.renderDepth?e.z=f.renderDepth:(Z.getPositionFromMatrix(f.matrixWorld),Z.applyProjection(fa),e.z=Z.z),E.sprites.push(e)):(e=a(),e.object=
-f,null!==f.renderDepth?e.z=f.renderDepth:(Z.getPositionFromMatrix(f.matrixWorld),Z.applyProjection(fa),e.z=Z.z),E.objects.push(e));Sa(f)}}};Sa(g);!0===n&&E.objects.sort(c);g=0;for(n=E.objects.length;g<n;g++)if(sa=E.objects[g].object,ma=sa.matrixWorld,k=0,sa instanceof THREE.Mesh){na=sa.geometry;ha=na.vertices;Pa=na.faces;na=na.faceVertexUvs;M.getInverse(ma);M.transpose();fb=sa.material instanceof THREE.MeshFaceMaterial;jb=!0===fb?sa.material:null;Oa=0;for(ea=ha.length;Oa<ea;Oa++)i=b(),i.positionWorld.copy(ha[Oa]).applyMatrix4(ma),
-i.positionScreen.copy(i.positionWorld).applyMatrix4(fa),i.positionScreen.x/=i.positionScreen.w,i.positionScreen.y/=i.positionScreen.w,i.positionScreen.z/=i.positionScreen.w,i.visible=!(-1>i.positionScreen.x||1<i.positionScreen.x||-1>i.positionScreen.y||1<i.positionScreen.y||-1>i.positionScreen.z||1<i.positionScreen.z);ha=0;for(Oa=Pa.length;ha<Oa;ha++){ea=Pa[ha];var ob=!0===fb?jb.materials[ea.materialIndex]:sa.material;if(void 0!==ob){Y=ob.side;if(ea instanceof THREE.Face3)if(V=l[ea.a],$=l[ea.b],ia=
-l[ea.c],G[0]=V.positionScreen,G[1]=$.positionScreen,G[2]=ia.positionScreen,!0===V.visible||!0===$.visible||!0===ia.visible||U.isIntersectionBox(F.setFromPoints(G)))if(La=0>(ia.positionScreen.x-V.positionScreen.x)*($.positionScreen.y-V.positionScreen.y)-(ia.positionScreen.y-V.positionScreen.y)*($.positionScreen.x-V.positionScreen.x),Y===THREE.DoubleSide||La===(Y===THREE.FrontSide))t===p?(Ba=new THREE.RenderableFace3,r.push(Ba),p++,t++,m=Ba):m=r[t++],m.v1.copy(V),m.v2.copy($),m.v3.copy(ia);else continue;
-else continue;else if(ea instanceof THREE.Face4)if(V=l[ea.a],$=l[ea.b],ia=l[ea.c],Ba=l[ea.d],K[0]=V.positionScreen,K[1]=$.positionScreen,K[2]=ia.positionScreen,K[3]=Ba.positionScreen,!0===V.visible||!0===$.visible||!0===ia.visible||!0===Ba.visible||U.isIntersectionBox(F.setFromPoints(K)))if(La=0>(Ba.positionScreen.x-V.positionScreen.x)*($.positionScreen.y-V.positionScreen.y)-(Ba.positionScreen.y-V.positionScreen.y)*($.positionScreen.x-V.positionScreen.x)||0>($.positionScreen.x-ia.positionScreen.x)*
-(Ba.positionScreen.y-ia.positionScreen.y)-($.positionScreen.y-ia.positionScreen.y)*(Ba.positionScreen.x-ia.positionScreen.x),Y===THREE.DoubleSide||La===(Y===THREE.FrontSide)){if(q===v){var Gb=new THREE.RenderableFace4;y.push(Gb);v++;q++;m=Gb}else m=y[q++];m.v1.copy(V);m.v2.copy($);m.v3.copy(ia);m.v4.copy(Ba)}else continue;else continue;m.normalModel.copy(ea.normal);!1===La&&(Y===THREE.BackSide||Y===THREE.DoubleSide)&&m.normalModel.negate();m.normalModel.applyMatrix3(M).normalize();m.normalModelView.copy(m.normalModel).applyMatrix3(T);
-m.centroidModel.copy(ea.centroid).applyMatrix4(ma);ia=ea.vertexNormals;V=0;for($=ia.length;V<$;V++)Ba=m.vertexNormalsModel[V],Ba.copy(ia[V]),!1===La&&(Y===THREE.BackSide||Y===THREE.DoubleSide)&&Ba.negate(),Ba.applyMatrix3(M).normalize(),m.vertexNormalsModelView[V].copy(Ba).applyMatrix3(T);m.vertexNormalsLength=ia.length;V=0;for($=na.length;V<$;V++)if(Ba=na[V][ha],void 0!==Ba){Y=0;for(ia=Ba.length;Y<ia;Y++)m.uvs[V][Y]=Ba[Y]}m.color=ea.color;m.material=ob;ja.copy(m.centroidModel).applyProjection(fa);
-m.z=ja.z;E.elements.push(m)}}}else if(sa instanceof THREE.Line){eb.multiplyMatrices(fa,ma);ha=sa.geometry.vertices;V=b();V.positionScreen.copy(ha[0]).applyMatrix4(eb);Pa=sa.type===THREE.LinePieces?2:1;Oa=1;for(ea=ha.length;Oa<ea;Oa++)V=b(),V.positionScreen.copy(ha[Oa]).applyMatrix4(eb),0<(Oa+1)%Pa||($=l[k-2],ca.copy(V.positionScreen),ra.copy($.positionScreen),!0===d(ca,ra)&&(ca.multiplyScalar(1/ca.w),ra.multiplyScalar(1/ra.w),s===H?(na=new THREE.RenderableLine,C.push(na),H++,s++,z=na):z=C[s++],z.v1.positionScreen.copy(ca),
-z.v2.positionScreen.copy(ra),z.z=Math.max(ca.z,ra.z),z.material=sa.material,E.elements.push(z)))}g=0;for(n=E.sprites.length;g<n;g++)sa=E.sprites[g].object,ma=sa.matrixWorld,sa instanceof THREE.Particle&&(A.set(ma.elements[12],ma.elements[13],ma.elements[14],1),A.applyMatrix4(fa),A.z/=A.w,0<A.z&&1>A.z&&(w===J?(La=new THREE.RenderableParticle,I.push(La),J++,w++,B=La):B=I[w++],B.object=sa,B.x=A.x/A.w,B.y=A.y/A.w,B.z=A.z,B.rotation=sa.rotation.z,B.scale.x=sa.scale.x*Math.abs(B.x-(A.x+h.projectionMatrix.elements[0])/
-(A.w+h.projectionMatrix.elements[12])),B.scale.y=sa.scale.y*Math.abs(B.y-(A.y+h.projectionMatrix.elements[5])/(A.w+h.projectionMatrix.elements[13])),B.material=sa.material,E.elements.push(B)));!0===db&&E.elements.sort(c);return E}};THREE.Face3=function(a,b,c,d,e,f){this.a=a;this.b=b;this.c=c;this.normal=d instanceof THREE.Vector3?d:new THREE.Vector3;this.vertexNormals=d instanceof Array?d:[];this.color=e instanceof THREE.Color?e:new THREE.Color;this.vertexColors=e instanceof Array?e:[];this.vertexTangents=[];this.materialIndex=void 0!==f?f:0;this.centroid=new THREE.Vector3};
+a=0.001*(b-this.oldTime);this.oldTime=b;this.elapsedTime+=a}return a}});THREE.EventDispatcher=function(){var a={};this.addEventListener=function(b,c){void 0===a[b]&&(a[b]=[]);-1===a[b].indexOf(c)&&a[b].push(c)};this.removeEventListener=function(b,c){var d=a[b].indexOf(c);-1!==d&&a[b].splice(d,1)};this.dispatchEvent=function(b){var c=a[b.type];if(void 0!==c){b.target=this;for(var d=0,e=c.length;d<e;d++)c[d].call(this,b)}}};(function(a){a.Raycaster=function(b,c,d,e){this.ray=new a.Ray(b,c);0<this.ray.direction.lengthSq()&&this.ray.direction.normalize();this.near=d||0;this.far=e||Infinity};var b=new a.Sphere,c=new a.Ray,d=new a.Plane,e=new a.Vector3,f=new a.Vector3,g=new a.Matrix4,h=function(a,b){return a.distance-b.distance},i=function(i,h,j){if(i instanceof a.Particle){f.getPositionFromMatrix(i.matrixWorld);h=h.ray.distanceToPoint(f);if(h>i.scale.x)return j;j.push({distance:h,point:i.position,face:null,object:i})}else if(i instanceof
+a.Mesh){f.getPositionFromMatrix(i.matrixWorld);b.set(f,i.geometry.boundingSphere.radius*i.matrixWorld.getMaxScaleOnAxis());if(!h.ray.isIntersectionSphere(b))return j;var r=i.geometry,u=r.vertices,p=i.material instanceof a.MeshFaceMaterial,q=!0===p?i.material.materials:null,w=i.material.side,v,z,y,t=h.precision;i.matrixRotationWorld.extractRotation(i.matrixWorld);g.getInverse(i.matrixWorld);c.copy(h.ray).applyMatrix4(g);for(var D=0,C=r.faces.length;D<C;D++){var k=r.faces[D],w=!0===p?q[k.materialIndex]:
+i.material;if(void 0!==w){d.setFromNormalAndCoplanarPoint(k.normal,u[k.a]);var I=c.distanceToPlane(d);if(!(Math.abs(I)<t)&&!(0>I)){w=w.side;if(w!==a.DoubleSide&&(v=c.direction.dot(d.normal),!(w===a.FrontSide?0>v:0<v)))continue;if(!(I<h.near||I>h.far)){e=c.at(I,e);if(k instanceof a.Face3){if(w=u[k.a],v=u[k.b],z=u[k.c],!a.Triangle.containsPoint(e,w,v,z))continue}else if(k instanceof a.Face4){if(w=u[k.a],v=u[k.b],z=u[k.c],y=u[k.d],!a.Triangle.containsPoint(e,w,v,y)&&!a.Triangle.containsPoint(e,v,z,y))continue}else throw Error("face type not supported");
+j.push({distance:I,point:h.ray.at(I),face:k,faceIndex:D,object:i})}}}}}},j=function(a,b,c){for(var a=a.getDescendants(),d=0,e=a.length;d<e;d++)i(a[d],b,c)};a.Raycaster.prototype.precision=1E-4;a.Raycaster.prototype.set=function(a,b){this.ray.set(a,b);0<this.ray.direction.length()&&this.ray.direction.normalize()};a.Raycaster.prototype.intersectObject=function(a,b){var c=[];!0===b&&j(a,this,c);i(a,this,c);c.sort(h);return c};a.Raycaster.prototype.intersectObjects=function(a,b){for(var c=[],d=0,e=a.length;d<
+e;d++)i(a[d],this,c),!0===b&&j(a[d],this,c);c.sort(h);return c}})(THREE);THREE.Object3D=function(){this.id=THREE.Object3DIdCount++;this.name="";this.properties={};this.parent=void 0;this.children=[];this.up=new THREE.Vector3(0,1,0);this.position=new THREE.Vector3;this.rotation=new THREE.Vector3;this.eulerOrder=THREE.Object3D.defaultEulerOrder;this.scale=new THREE.Vector3(1,1,1);this.renderDepth=null;this.rotationAutoUpdate=!0;this.matrix=new THREE.Matrix4;this.matrixWorld=new THREE.Matrix4;this.matrixRotationWorld=new THREE.Matrix4;this.matrixWorldNeedsUpdate=this.matrixAutoUpdate=
+!0;this.quaternion=new THREE.Quaternion;this.useQuaternion=!1;this.visible=!0;this.receiveShadow=this.castShadow=!1;this.frustumCulled=!0};
+THREE.Object3D.prototype={constructor:THREE.Object3D,applyMatrix:function(){var a=new THREE.Matrix4;return function(b){this.matrix.multiplyMatrices(b,this.matrix);this.position.getPositionFromMatrix(this.matrix);this.scale.getScaleFromMatrix(this.matrix);a.extractRotation(this.matrix);!0===this.useQuaternion?this.quaternion.setFromRotationMatrix(a):this.rotation.setEulerFromRotationMatrix(a,this.eulerOrder)}}(),translate:function(){var a=new THREE.Vector3;return function(b,c){a.copy(c);!0===this.useQuaternion?
+a.applyQuaternion(this.quaternion):a.applyEuler(this.rotation,this.eulerOrder);a.multiplyScalar(b);this.position.add(a);return this}}(),translateX:function(){var a=new THREE.Vector3(1,0,0);return function(b){return this.translate(b,a)}}(),translateY:function(){var a=new THREE.Vector3(0,1,0);return function(b){return this.translate(b,a)}}(),translateZ:function(){var a=new THREE.Vector3(0,0,1);return function(b){return this.translate(b,a)}}(),localToWorld:function(a){return a.applyMatrix4(this.matrixWorld)},
+worldToLocal:function(){var a=new THREE.Matrix4;return function(b){return b.applyMatrix4(a.getInverse(this.matrixWorld))}}(),lookAt:function(){var a=new THREE.Matrix4;return function(b){a.lookAt(b,this.position,this.up);!0===this.useQuaternion?this.quaternion.setFromRotationMatrix(a):this.rotation.setEulerFromRotationMatrix(a,this.eulerOrder)}}(),add:function(a){if(a===this)console.warn("THREE.Object3D.add: An object can't be added as a child of itself.");else if(a instanceof THREE.Object3D){void 0!==
+a.parent&&a.parent.remove(a);a.parent=this;this.children.push(a);for(var b=this;void 0!==b.parent;)b=b.parent;void 0!==b&&b instanceof THREE.Scene&&b.__addObject(a)}},remove:function(a){var b=this.children.indexOf(a);if(-1!==b){a.parent=void 0;this.children.splice(b,1);for(b=this;void 0!==b.parent;)b=b.parent;void 0!==b&&b instanceof THREE.Scene&&b.__removeObject(a)}},traverse:function(a){a(this);for(var b=0,c=this.children.length;b<c;b++)this.children[b].traverse(a)},getChildByName:function(a,b){for(var c=
+0,d=this.children.length;c<d;c++){var e=this.children[c];if(e.name===a||!0===b&&(e=e.getChildByName(a,b),void 0!==e))return e}},getDescendants:function(a){void 0===a&&(a=[]);Array.prototype.push.apply(a,this.children);for(var b=0,c=this.children.length;b<c;b++)this.children[b].getDescendants(a);return a},updateMatrix:function(){this.matrix.setPosition(this.position);!1===this.useQuaternion?this.matrix.setRotationFromEuler(this.rotation,this.eulerOrder):this.matrix.setRotationFromQuaternion(this.quaternion);
+(1!==this.scale.x||1!==this.scale.y||1!==this.scale.z)&&this.matrix.scale(this.scale);this.matrixWorldNeedsUpdate=!0},updateMatrixWorld:function(a){!0===this.matrixAutoUpdate&&this.updateMatrix();if(!0===this.matrixWorldNeedsUpdate||!0===a)void 0===this.parent?this.matrixWorld.copy(this.matrix):this.matrixWorld.multiplyMatrices(this.parent.matrixWorld,this.matrix),this.matrixWorldNeedsUpdate=!1,a=!0;for(var b=0,c=this.children.length;b<c;b++)this.children[b].updateMatrixWorld(a)},clone:function(a){void 0===
+a&&(a=new THREE.Object3D);a.name=this.name;a.up.copy(this.up);a.position.copy(this.position);a.rotation instanceof THREE.Vector3&&a.rotation.copy(this.rotation);a.eulerOrder=this.eulerOrder;a.scale.copy(this.scale);a.renderDepth=this.renderDepth;a.rotationAutoUpdate=this.rotationAutoUpdate;a.matrix.copy(this.matrix);a.matrixWorld.copy(this.matrixWorld);a.matrixRotationWorld.copy(this.matrixRotationWorld);a.matrixAutoUpdate=this.matrixAutoUpdate;a.matrixWorldNeedsUpdate=this.matrixWorldNeedsUpdate;
+a.quaternion.copy(this.quaternion);a.useQuaternion=this.useQuaternion;a.visible=this.visible;a.castShadow=this.castShadow;a.receiveShadow=this.receiveShadow;a.frustumCulled=this.frustumCulled;for(var b=0;b<this.children.length;b++)a.add(this.children[b].clone());return a}};THREE.Object3D.defaultEulerOrder="XYZ";THREE.Object3DIdCount=0;THREE.Projector=function(){function a(){if(f===h){var a=new THREE.RenderableObject;g.push(a);h++;f++;return a}return g[f++]}function b(){if(j===n){var a=new THREE.RenderableVertex;l.push(a);n++;j++;return a}return l[j++]}function c(a,b){return b.z-a.z}function d(a,b){var c=0,d=1,e=a.z+a.w,f=b.z+b.w,g=-a.z+a.w,i=-b.z+b.w;if(0<=e&&0<=f&&0<=g&&0<=i)return!0;if(0>e&&0>f||0>g&&0>i)return!1;0>e?c=Math.max(c,e/(e-f)):0>f&&(d=Math.min(d,e/(e-f)));0>g?c=Math.max(c,g/(g-i)):0>i&&(d=Math.min(d,g/(g-i)));if(d<
+c)return!1;a.lerp(b,c);b.lerp(a,1-d);return!0}var e,f,g=[],h=0,i,j,l=[],n=0,m,r,u=[],p=0,q,w=[],v=0,z,y,t=[],D=0,C,k,I=[],J=0,B={objects:[],sprites:[],lights:[],elements:[]},P=new THREE.Vector3,A=new THREE.Vector4,G=new THREE.Box3(new THREE.Vector3(-1,-1,-1),new THREE.Vector3(1,1,1)),E=new THREE.Box3,F=Array(3),s=Array(4),H=new THREE.Matrix4,O=new THREE.Matrix4,K,x=new THREE.Matrix4,N=new THREE.Matrix3,R=new THREE.Matrix3,$=new THREE.Vector3,Y=new THREE.Frustum,W=new THREE.Vector4,M=new THREE.Vector4;
+this.projectVector=function(a,b){b.matrixWorldInverse.getInverse(b.matrixWorld);O.multiplyMatrices(b.projectionMatrix,b.matrixWorldInverse);return a.applyProjection(O)};this.unprojectVector=function(a,b){b.projectionMatrixInverse.getInverse(b.projectionMatrix);O.multiplyMatrices(b.matrixWorld,b.projectionMatrixInverse);return a.applyProjection(O)};this.pickingRay=function(a,b){a.z=-1;var c=new THREE.Vector3(a.x,a.y,1);this.unprojectVector(a,b);this.unprojectVector(c,b);c.sub(a).normalize();return new THREE.Raycaster(a,
+c)};this.projectScene=function(g,h,n,X){var S=!1,Z,T,aa,L,U,ba,ca,da,pa,Aa,ea,ra,wa;k=y=q=r=0;B.elements.length=0;g.updateMatrixWorld();void 0===h.parent&&h.updateMatrixWorld();H.copy(h.matrixWorldInverse.getInverse(h.matrixWorld));O.multiplyMatrices(h.projectionMatrix,H);R.getInverse(H);R.transpose();Y.setFromMatrix(O);f=0;B.objects.length=0;B.sprites.length=0;B.lights.length=0;var ka=function(b){for(var c=0,d=b.children.length;c<d;c++){var f=b.children[c];if(!1!==f.visible){if(f instanceof THREE.Light)B.lights.push(f);
+else if(f instanceof THREE.Mesh||f instanceof THREE.Line){if(!1===f.frustumCulled||!0===Y.intersectsObject(f))e=a(),e.object=f,null!==f.renderDepth?e.z=f.renderDepth:(P.getPositionFromMatrix(f.matrixWorld),P.applyProjection(O),e.z=P.z),B.objects.push(e)}else f instanceof THREE.Sprite||f instanceof THREE.Particle?(e=a(),e.object=f,null!==f.renderDepth?e.z=f.renderDepth:(P.getPositionFromMatrix(f.matrixWorld),P.applyProjection(O),e.z=P.z),B.sprites.push(e)):(e=a(),e.object=f,null!==f.renderDepth?e.z=
+f.renderDepth:(P.getPositionFromMatrix(f.matrixWorld),P.applyProjection(O),e.z=P.z),B.objects.push(e));ka(f)}}};ka(g);!0===n&&B.objects.sort(c);g=0;for(n=B.objects.length;g<n;g++)if(da=B.objects[g].object,K=da.matrixWorld,j=0,da instanceof THREE.Mesh){pa=da.geometry;aa=pa.vertices;Aa=pa.faces;pa=pa.faceVertexUvs;N.getInverse(K);N.transpose();ra=da.material instanceof THREE.MeshFaceMaterial;wa=!0===ra?da.material:null;Z=0;for(T=aa.length;Z<T;Z++)i=b(),i.positionWorld.copy(aa[Z]).applyMatrix4(K),i.positionScreen.copy(i.positionWorld).applyMatrix4(O),
+i.positionScreen.x/=i.positionScreen.w,i.positionScreen.y/=i.positionScreen.w,i.positionScreen.z/=i.positionScreen.w,i.visible=!(-1>i.positionScreen.x||1<i.positionScreen.x||-1>i.positionScreen.y||1<i.positionScreen.y||-1>i.positionScreen.z||1<i.positionScreen.z);aa=0;for(Z=Aa.length;aa<Z;aa++){T=Aa[aa];var ya=!0===ra?wa.materials[T.materialIndex]:da.material;if(void 0!==ya){ba=ya.side;if(T instanceof THREE.Face3)if(L=l[T.a],U=l[T.b],ca=l[T.c],F[0]=L.positionScreen,F[1]=U.positionScreen,F[2]=ca.positionScreen,
+!0===L.visible||!0===U.visible||!0===ca.visible||G.isIntersectionBox(E.setFromPoints(F)))if(S=0>(ca.positionScreen.x-L.positionScreen.x)*(U.positionScreen.y-L.positionScreen.y)-(ca.positionScreen.y-L.positionScreen.y)*(U.positionScreen.x-L.positionScreen.x),ba===THREE.DoubleSide||S===(ba===THREE.FrontSide))r===p?(ea=new THREE.RenderableFace3,u.push(ea),p++,r++,m=ea):m=u[r++],m.v1.copy(L),m.v2.copy(U),m.v3.copy(ca);else continue;else continue;else if(T instanceof THREE.Face4)if(L=l[T.a],U=l[T.b],ca=
+l[T.c],ea=l[T.d],s[0]=L.positionScreen,s[1]=U.positionScreen,s[2]=ca.positionScreen,s[3]=ea.positionScreen,!0===L.visible||!0===U.visible||!0===ca.visible||!0===ea.visible||G.isIntersectionBox(E.setFromPoints(s)))if(S=0>(ea.positionScreen.x-L.positionScreen.x)*(U.positionScreen.y-L.positionScreen.y)-(ea.positionScreen.y-L.positionScreen.y)*(U.positionScreen.x-L.positionScreen.x)||0>(U.positionScreen.x-ca.positionScreen.x)*(ea.positionScreen.y-ca.positionScreen.y)-(U.positionScreen.y-ca.positionScreen.y)*
+(ea.positionScreen.x-ca.positionScreen.x),ba===THREE.DoubleSide||S===(ba===THREE.FrontSide)){if(q===v){var Ga=new THREE.RenderableFace4;w.push(Ga);v++;q++;m=Ga}else m=w[q++];m.v1.copy(L);m.v2.copy(U);m.v3.copy(ca);m.v4.copy(ea)}else continue;else continue;m.normalModel.copy(T.normal);!1===S&&(ba===THREE.BackSide||ba===THREE.DoubleSide)&&m.normalModel.negate();m.normalModel.applyMatrix3(N).normalize();m.normalModelView.copy(m.normalModel).applyMatrix3(R);m.centroidModel.copy(T.centroid).applyMatrix4(K);
+ca=T.vertexNormals;L=0;for(U=ca.length;L<U;L++)ea=m.vertexNormalsModel[L],ea.copy(ca[L]),!1===S&&(ba===THREE.BackSide||ba===THREE.DoubleSide)&&ea.negate(),ea.applyMatrix3(N).normalize(),m.vertexNormalsModelView[L].copy(ea).applyMatrix3(R);m.vertexNormalsLength=ca.length;L=0;for(U=pa.length;L<U;L++)if(ea=pa[L][aa],void 0!==ea){ba=0;for(ca=ea.length;ba<ca;ba++)m.uvs[L][ba]=ea[ba]}m.color=T.color;m.material=ya;$.copy(m.centroidModel).applyProjection(O);m.z=$.z;B.elements.push(m)}}}else if(da instanceof
+THREE.Line){x.multiplyMatrices(O,K);aa=da.geometry.vertices;L=b();L.positionScreen.copy(aa[0]).applyMatrix4(x);Aa=da.type===THREE.LinePieces?2:1;Z=1;for(T=aa.length;Z<T;Z++)L=b(),L.positionScreen.copy(aa[Z]).applyMatrix4(x),0<(Z+1)%Aa||(U=l[j-2],W.copy(L.positionScreen),M.copy(U.positionScreen),!0===d(W,M)&&(W.multiplyScalar(1/W.w),M.multiplyScalar(1/M.w),y===D?(pa=new THREE.RenderableLine,t.push(pa),D++,y++,z=pa):z=t[y++],z.v1.positionScreen.copy(W),z.v2.positionScreen.copy(M),z.z=Math.max(W.z,M.z),
+z.material=da.material,B.elements.push(z)))}g=0;for(n=B.sprites.length;g<n;g++)da=B.sprites[g].object,K=da.matrixWorld,da instanceof THREE.Particle&&(A.set(K.elements[12],K.elements[13],K.elements[14],1),A.applyMatrix4(O),A.z/=A.w,0<A.z&&1>A.z&&(k===J?(S=new THREE.RenderableParticle,I.push(S),J++,k++,C=S):C=I[k++],C.object=da,C.x=A.x/A.w,C.y=A.y/A.w,C.z=A.z,C.rotation=da.rotation.z,C.scale.x=da.scale.x*Math.abs(C.x-(A.x+h.projectionMatrix.elements[0])/(A.w+h.projectionMatrix.elements[12])),C.scale.y=
+da.scale.y*Math.abs(C.y-(A.y+h.projectionMatrix.elements[5])/(A.w+h.projectionMatrix.elements[13])),C.material=da.material,B.elements.push(C)));!0===X&&B.elements.sort(c);return B}};THREE.Face3=function(a,b,c,d,e,f){this.a=a;this.b=b;this.c=c;this.normal=d instanceof THREE.Vector3?d:new THREE.Vector3;this.vertexNormals=d instanceof Array?d:[];this.color=e instanceof THREE.Color?e:new THREE.Color;this.vertexColors=e instanceof Array?e:[];this.vertexTangents=[];this.materialIndex=void 0!==f?f:0;this.centroid=new THREE.Vector3};
 THREE.Face3.prototype={constructor:THREE.Face3,clone:function(){var a=new THREE.Face3(this.a,this.b,this.c);a.normal.copy(this.normal);a.color.copy(this.color);a.centroid.copy(this.centroid);a.materialIndex=this.materialIndex;var b,c;b=0;for(c=this.vertexNormals.length;b<c;b++)a.vertexNormals[b]=this.vertexNormals[b].clone();b=0;for(c=this.vertexColors.length;b<c;b++)a.vertexColors[b]=this.vertexColors[b].clone();b=0;for(c=this.vertexTangents.length;b<c;b++)a.vertexTangents[b]=this.vertexTangents[b].clone();
 THREE.Face3.prototype={constructor:THREE.Face3,clone:function(){var a=new THREE.Face3(this.a,this.b,this.c);a.normal.copy(this.normal);a.color.copy(this.color);a.centroid.copy(this.centroid);a.materialIndex=this.materialIndex;var b,c;b=0;for(c=this.vertexNormals.length;b<c;b++)a.vertexNormals[b]=this.vertexNormals[b].clone();b=0;for(c=this.vertexColors.length;b<c;b++)a.vertexColors[b]=this.vertexColors[b].clone();b=0;for(c=this.vertexTangents.length;b<c;b++)a.vertexTangents[b]=this.vertexTangents[b].clone();
 return a}};THREE.Face4=function(a,b,c,d,e,f,g){this.a=a;this.b=b;this.c=c;this.d=d;this.normal=e instanceof THREE.Vector3?e:new THREE.Vector3;this.vertexNormals=e instanceof Array?e:[];this.color=f instanceof THREE.Color?f:new THREE.Color;this.vertexColors=f instanceof Array?f:[];this.vertexTangents=[];this.materialIndex=void 0!==g?g:0;this.centroid=new THREE.Vector3};
 return a}};THREE.Face4=function(a,b,c,d,e,f,g){this.a=a;this.b=b;this.c=c;this.d=d;this.normal=e instanceof THREE.Vector3?e:new THREE.Vector3;this.vertexNormals=e instanceof Array?e:[];this.color=f instanceof THREE.Color?f:new THREE.Color;this.vertexColors=f instanceof Array?f:[];this.vertexTangents=[];this.materialIndex=void 0!==g?g:0;this.centroid=new THREE.Vector3};
 THREE.Face4.prototype={constructor:THREE.Face4,clone:function(){var a=new THREE.Face4(this.a,this.b,this.c,this.d);a.normal.copy(this.normal);a.color.copy(this.color);a.centroid.copy(this.centroid);a.materialIndex=this.materialIndex;var b,c;b=0;for(c=this.vertexNormals.length;b<c;b++)a.vertexNormals[b]=this.vertexNormals[b].clone();b=0;for(c=this.vertexColors.length;b<c;b++)a.vertexColors[b]=this.vertexColors[b].clone();b=0;for(c=this.vertexTangents.length;b<c;b++)a.vertexTangents[b]=this.vertexTangents[b].clone();
 THREE.Face4.prototype={constructor:THREE.Face4,clone:function(){var a=new THREE.Face4(this.a,this.b,this.c,this.d);a.normal.copy(this.normal);a.color.copy(this.color);a.centroid.copy(this.centroid);a.materialIndex=this.materialIndex;var b,c;b=0;for(c=this.vertexNormals.length;b<c;b++)a.vertexNormals[b]=this.vertexNormals[b].clone();b=0;for(c=this.vertexColors.length;b<c;b++)a.vertexColors[b]=this.vertexColors[b].clone();b=0;for(c=this.vertexTangents.length;b<c;b++)a.vertexTangents[b]=this.vertexTangents[b].clone();
@@ -158,71 +155,71 @@ this.normalsNeedUpdate=this.uvsNeedUpdate=this.elementsNeedUpdate=this.verticesN
 THREE.Geometry.prototype={constructor:THREE.Geometry,applyMatrix:function(a){for(var b=(new THREE.Matrix3).getInverse(a).transpose(),c=0,d=this.vertices.length;c<d;c++)this.vertices[c].applyMatrix4(a);c=0;for(d=this.faces.length;c<d;c++){var e=this.faces[c];e.normal.applyMatrix3(b).normalize();for(var f=0,g=e.vertexNormals.length;f<g;f++)e.vertexNormals[f].applyMatrix3(b).normalize();e.centroid.applyMatrix4(a)}},computeCentroids:function(){var a,b,c;a=0;for(b=this.faces.length;a<b;a++)c=this.faces[a],
 THREE.Geometry.prototype={constructor:THREE.Geometry,applyMatrix:function(a){for(var b=(new THREE.Matrix3).getInverse(a).transpose(),c=0,d=this.vertices.length;c<d;c++)this.vertices[c].applyMatrix4(a);c=0;for(d=this.faces.length;c<d;c++){var e=this.faces[c];e.normal.applyMatrix3(b).normalize();for(var f=0,g=e.vertexNormals.length;f<g;f++)e.vertexNormals[f].applyMatrix3(b).normalize();e.centroid.applyMatrix4(a)}},computeCentroids:function(){var a,b,c;a=0;for(b=this.faces.length;a<b;a++)c=this.faces[a],
 c.centroid.set(0,0,0),c instanceof THREE.Face3?(c.centroid.add(this.vertices[c.a]),c.centroid.add(this.vertices[c.b]),c.centroid.add(this.vertices[c.c]),c.centroid.divideScalar(3)):c instanceof THREE.Face4&&(c.centroid.add(this.vertices[c.a]),c.centroid.add(this.vertices[c.b]),c.centroid.add(this.vertices[c.c]),c.centroid.add(this.vertices[c.d]),c.centroid.divideScalar(4))},computeFaceNormals:function(){for(var a=new THREE.Vector3,b=new THREE.Vector3,c=0,d=this.faces.length;c<d;c++){var e=this.faces[c],
 c.centroid.set(0,0,0),c instanceof THREE.Face3?(c.centroid.add(this.vertices[c.a]),c.centroid.add(this.vertices[c.b]),c.centroid.add(this.vertices[c.c]),c.centroid.divideScalar(3)):c instanceof THREE.Face4&&(c.centroid.add(this.vertices[c.a]),c.centroid.add(this.vertices[c.b]),c.centroid.add(this.vertices[c.c]),c.centroid.add(this.vertices[c.d]),c.centroid.divideScalar(4))},computeFaceNormals:function(){for(var a=new THREE.Vector3,b=new THREE.Vector3,c=0,d=this.faces.length;c<d;c++){var e=this.faces[c],
 f=this.vertices[e.a],g=this.vertices[e.b];a.subVectors(this.vertices[e.c],g);b.subVectors(f,g);a.cross(b);a.normalize();e.normal.copy(a)}},computeVertexNormals:function(a){var b,c,d,e;if(void 0===this.__tmpVertices){e=this.__tmpVertices=Array(this.vertices.length);b=0;for(c=this.vertices.length;b<c;b++)e[b]=new THREE.Vector3;b=0;for(c=this.faces.length;b<c;b++)d=this.faces[b],d instanceof THREE.Face3?d.vertexNormals=[new THREE.Vector3,new THREE.Vector3,new THREE.Vector3]:d instanceof THREE.Face4&&
 f=this.vertices[e.a],g=this.vertices[e.b];a.subVectors(this.vertices[e.c],g);b.subVectors(f,g);a.cross(b);a.normalize();e.normal.copy(a)}},computeVertexNormals:function(a){var b,c,d,e;if(void 0===this.__tmpVertices){e=this.__tmpVertices=Array(this.vertices.length);b=0;for(c=this.vertices.length;b<c;b++)e[b]=new THREE.Vector3;b=0;for(c=this.faces.length;b<c;b++)d=this.faces[b],d instanceof THREE.Face3?d.vertexNormals=[new THREE.Vector3,new THREE.Vector3,new THREE.Vector3]:d instanceof THREE.Face4&&
-(d.vertexNormals=[new THREE.Vector3,new THREE.Vector3,new THREE.Vector3,new THREE.Vector3])}else{e=this.__tmpVertices;b=0;for(c=this.vertices.length;b<c;b++)e[b].set(0,0,0)}if(a){var f,g,h,i=new THREE.Vector3,k=new THREE.Vector3,l=new THREE.Vector3,n=new THREE.Vector3,m=new THREE.Vector3;b=0;for(c=this.faces.length;b<c;b++)d=this.faces[b],d instanceof THREE.Face3?(a=this.vertices[d.a],f=this.vertices[d.b],g=this.vertices[d.c],i.subVectors(g,f),k.subVectors(a,f),i.cross(k),e[d.a].add(i),e[d.b].add(i),
-e[d.c].add(i)):d instanceof THREE.Face4&&(a=this.vertices[d.a],f=this.vertices[d.b],g=this.vertices[d.c],h=this.vertices[d.d],l.subVectors(h,f),k.subVectors(a,f),l.cross(k),e[d.a].add(l),e[d.b].add(l),e[d.d].add(l),n.subVectors(h,g),m.subVectors(f,g),n.cross(m),e[d.b].add(n),e[d.c].add(n),e[d.d].add(n))}else{b=0;for(c=this.faces.length;b<c;b++)d=this.faces[b],d instanceof THREE.Face3?(e[d.a].add(d.normal),e[d.b].add(d.normal),e[d.c].add(d.normal)):d instanceof THREE.Face4&&(e[d.a].add(d.normal),e[d.b].add(d.normal),
+(d.vertexNormals=[new THREE.Vector3,new THREE.Vector3,new THREE.Vector3,new THREE.Vector3])}else{e=this.__tmpVertices;b=0;for(c=this.vertices.length;b<c;b++)e[b].set(0,0,0)}if(a){var f,g,h,i=new THREE.Vector3,j=new THREE.Vector3,l=new THREE.Vector3,n=new THREE.Vector3,m=new THREE.Vector3;b=0;for(c=this.faces.length;b<c;b++)d=this.faces[b],d instanceof THREE.Face3?(a=this.vertices[d.a],f=this.vertices[d.b],g=this.vertices[d.c],i.subVectors(g,f),j.subVectors(a,f),i.cross(j),e[d.a].add(i),e[d.b].add(i),
+e[d.c].add(i)):d instanceof THREE.Face4&&(a=this.vertices[d.a],f=this.vertices[d.b],g=this.vertices[d.c],h=this.vertices[d.d],l.subVectors(h,f),j.subVectors(a,f),l.cross(j),e[d.a].add(l),e[d.b].add(l),e[d.d].add(l),n.subVectors(h,g),m.subVectors(f,g),n.cross(m),e[d.b].add(n),e[d.c].add(n),e[d.d].add(n))}else{b=0;for(c=this.faces.length;b<c;b++)d=this.faces[b],d instanceof THREE.Face3?(e[d.a].add(d.normal),e[d.b].add(d.normal),e[d.c].add(d.normal)):d instanceof THREE.Face4&&(e[d.a].add(d.normal),e[d.b].add(d.normal),
 e[d.c].add(d.normal),e[d.d].add(d.normal))}b=0;for(c=this.vertices.length;b<c;b++)e[b].normalize();b=0;for(c=this.faces.length;b<c;b++)d=this.faces[b],d instanceof THREE.Face3?(d.vertexNormals[0].copy(e[d.a]),d.vertexNormals[1].copy(e[d.b]),d.vertexNormals[2].copy(e[d.c])):d instanceof THREE.Face4&&(d.vertexNormals[0].copy(e[d.a]),d.vertexNormals[1].copy(e[d.b]),d.vertexNormals[2].copy(e[d.c]),d.vertexNormals[3].copy(e[d.d]))},computeMorphNormals:function(){var a,b,c,d,e;c=0;for(d=this.faces.length;c<
 e[d.c].add(d.normal),e[d.d].add(d.normal))}b=0;for(c=this.vertices.length;b<c;b++)e[b].normalize();b=0;for(c=this.faces.length;b<c;b++)d=this.faces[b],d instanceof THREE.Face3?(d.vertexNormals[0].copy(e[d.a]),d.vertexNormals[1].copy(e[d.b]),d.vertexNormals[2].copy(e[d.c])):d instanceof THREE.Face4&&(d.vertexNormals[0].copy(e[d.a]),d.vertexNormals[1].copy(e[d.b]),d.vertexNormals[2].copy(e[d.c]),d.vertexNormals[3].copy(e[d.d]))},computeMorphNormals:function(){var a,b,c,d,e;c=0;for(d=this.faces.length;c<
 d;c++){e=this.faces[c];e.__originalFaceNormal?e.__originalFaceNormal.copy(e.normal):e.__originalFaceNormal=e.normal.clone();e.__originalVertexNormals||(e.__originalVertexNormals=[]);a=0;for(b=e.vertexNormals.length;a<b;a++)e.__originalVertexNormals[a]?e.__originalVertexNormals[a].copy(e.vertexNormals[a]):e.__originalVertexNormals[a]=e.vertexNormals[a].clone()}var f=new THREE.Geometry;f.faces=this.faces;a=0;for(b=this.morphTargets.length;a<b;a++){if(!this.morphNormals[a]){this.morphNormals[a]={};this.morphNormals[a].faceNormals=
 d;c++){e=this.faces[c];e.__originalFaceNormal?e.__originalFaceNormal.copy(e.normal):e.__originalFaceNormal=e.normal.clone();e.__originalVertexNormals||(e.__originalVertexNormals=[]);a=0;for(b=e.vertexNormals.length;a<b;a++)e.__originalVertexNormals[a]?e.__originalVertexNormals[a].copy(e.vertexNormals[a]):e.__originalVertexNormals[a]=e.vertexNormals[a].clone()}var f=new THREE.Geometry;f.faces=this.faces;a=0;for(b=this.morphTargets.length;a<b;a++){if(!this.morphNormals[a]){this.morphNormals[a]={};this.morphNormals[a].faceNormals=
-[];this.morphNormals[a].vertexNormals=[];var g=this.morphNormals[a].faceNormals,h=this.morphNormals[a].vertexNormals,i,k;c=0;for(d=this.faces.length;c<d;c++)e=this.faces[c],i=new THREE.Vector3,k=e instanceof THREE.Face3?{a:new THREE.Vector3,b:new THREE.Vector3,c:new THREE.Vector3}:{a:new THREE.Vector3,b:new THREE.Vector3,c:new THREE.Vector3,d:new THREE.Vector3},g.push(i),h.push(k)}g=this.morphNormals[a];f.vertices=this.morphTargets[a].vertices;f.computeFaceNormals();f.computeVertexNormals();c=0;for(d=
-this.faces.length;c<d;c++)e=this.faces[c],i=g.faceNormals[c],k=g.vertexNormals[c],i.copy(e.normal),e instanceof THREE.Face3?(k.a.copy(e.vertexNormals[0]),k.b.copy(e.vertexNormals[1]),k.c.copy(e.vertexNormals[2])):(k.a.copy(e.vertexNormals[0]),k.b.copy(e.vertexNormals[1]),k.c.copy(e.vertexNormals[2]),k.d.copy(e.vertexNormals[3]))}c=0;for(d=this.faces.length;c<d;c++)e=this.faces[c],e.normal=e.__originalFaceNormal,e.vertexNormals=e.__originalVertexNormals},computeTangents:function(){function a(a,b,c,
-d,e,f,w){h=a.vertices[b];i=a.vertices[c];k=a.vertices[d];l=g[e];n=g[f];m=g[w];t=i.x-h.x;r=k.x-h.x;p=i.y-h.y;q=k.y-h.y;y=i.z-h.z;v=k.z-h.z;z=n.x-l.x;s=m.x-l.x;C=n.y-l.y;H=m.y-l.y;B=1/(z*H-s*C);E.set((H*t-C*r)*B,(H*p-C*q)*B,(H*y-C*v)*B);Z.set((z*r-s*t)*B,(z*q-s*p)*B,(z*v-s*y)*B);I[b].add(E);I[c].add(E);I[d].add(E);J[b].add(Z);J[c].add(Z);J[d].add(Z)}var b,c,d,e,f,g,h,i,k,l,n,m,t,r,p,q,y,v,z,s,C,H,B,w,I=[],J=[],E=new THREE.Vector3,Z=new THREE.Vector3,A=new THREE.Vector3,U=new THREE.Vector3,F=new THREE.Vector3;
-b=0;for(c=this.vertices.length;b<c;b++)I[b]=new THREE.Vector3,J[b]=new THREE.Vector3;b=0;for(c=this.faces.length;b<c;b++)f=this.faces[b],g=this.faceVertexUvs[0][b],f instanceof THREE.Face3?a(this,f.a,f.b,f.c,0,1,2):f instanceof THREE.Face4&&(a(this,f.a,f.b,f.d,0,1,3),a(this,f.b,f.c,f.d,1,2,3));var G=["a","b","c","d"];b=0;for(c=this.faces.length;b<c;b++){f=this.faces[b];for(d=0;d<f.vertexNormals.length;d++)F.copy(f.vertexNormals[d]),e=f[G[d]],w=I[e],A.copy(w),A.sub(F.multiplyScalar(F.dot(w))).normalize(),
-U.crossVectors(f.vertexNormals[d],w),e=U.dot(J[e]),e=0>e?-1:1,f.vertexTangents[d]=new THREE.Vector4(A.x,A.y,A.z,e)}this.hasTangents=!0},computeLineDistances:function(){for(var a=0,b=this.vertices,c=0,d=b.length;c<d;c++)0<c&&(a+=b[c].distanceTo(b[c-1])),this.lineDistances[c]=a},computeBoundingBox:function(){null===this.boundingBox&&(this.boundingBox=new THREE.Box3);this.boundingBox.setFromPoints(this.vertices)},computeBoundingSphere:function(){null===this.boundingSphere&&(this.boundingSphere=new THREE.Sphere);
-this.boundingSphere.setFromCenterAndPoints(this.boundingSphere.center,this.vertices)},mergeVertices:function(){var a={},b=[],c=[],d,e=Math.pow(10,4),f,g,h,i,k;this.__tmpVertices=void 0;f=0;for(g=this.vertices.length;f<g;f++)d=this.vertices[f],d=[Math.round(d.x*e),Math.round(d.y*e),Math.round(d.z*e)].join("_"),void 0===a[d]?(a[d]=f,b.push(this.vertices[f]),c[f]=b.length-1):c[f]=c[a[d]];e=[];f=0;for(g=this.faces.length;f<g;f++)if(a=this.faces[f],a instanceof THREE.Face3){a.a=c[a.a];a.b=c[a.b];a.c=c[a.c];
-h=[a.a,a.b,a.c];d=-1;for(i=0;3>i;i++)if(h[i]==h[(i+1)%3]){e.push(f);break}}else if(a instanceof THREE.Face4){a.a=c[a.a];a.b=c[a.b];a.c=c[a.c];a.d=c[a.d];h=[a.a,a.b,a.c,a.d];d=-1;for(i=0;4>i;i++)h[i]==h[(i+1)%4]&&(0<=d&&e.push(f),d=i);if(0<=d){h.splice(d,1);var l=new THREE.Face3(h[0],h[1],h[2],a.normal,a.color,a.materialIndex);h=0;for(i=this.faceVertexUvs.length;h<i;h++)(k=this.faceVertexUvs[h][f])&&k.splice(d,1);a.vertexNormals&&0<a.vertexNormals.length&&(l.vertexNormals=a.vertexNormals,l.vertexNormals.splice(d,
+[];this.morphNormals[a].vertexNormals=[];var g=this.morphNormals[a].faceNormals,h=this.morphNormals[a].vertexNormals,i,j;c=0;for(d=this.faces.length;c<d;c++)e=this.faces[c],i=new THREE.Vector3,j=e instanceof THREE.Face3?{a:new THREE.Vector3,b:new THREE.Vector3,c:new THREE.Vector3}:{a:new THREE.Vector3,b:new THREE.Vector3,c:new THREE.Vector3,d:new THREE.Vector3},g.push(i),h.push(j)}g=this.morphNormals[a];f.vertices=this.morphTargets[a].vertices;f.computeFaceNormals();f.computeVertexNormals();c=0;for(d=
+this.faces.length;c<d;c++)e=this.faces[c],i=g.faceNormals[c],j=g.vertexNormals[c],i.copy(e.normal),e instanceof THREE.Face3?(j.a.copy(e.vertexNormals[0]),j.b.copy(e.vertexNormals[1]),j.c.copy(e.vertexNormals[2])):(j.a.copy(e.vertexNormals[0]),j.b.copy(e.vertexNormals[1]),j.c.copy(e.vertexNormals[2]),j.d.copy(e.vertexNormals[3]))}c=0;for(d=this.faces.length;c<d;c++)e=this.faces[c],e.normal=e.__originalFaceNormal,e.vertexNormals=e.__originalVertexNormals},computeTangents:function(){function a(a,b,c,
+d,e,f,k){h=a.vertices[b];i=a.vertices[c];j=a.vertices[d];l=g[e];n=g[f];m=g[k];r=i.x-h.x;u=j.x-h.x;p=i.y-h.y;q=j.y-h.y;w=i.z-h.z;v=j.z-h.z;z=n.x-l.x;y=m.x-l.x;t=n.y-l.y;D=m.y-l.y;C=1/(z*D-y*t);B.set((D*r-t*u)*C,(D*p-t*q)*C,(D*w-t*v)*C);P.set((z*u-y*r)*C,(z*q-y*p)*C,(z*v-y*w)*C);I[b].add(B);I[c].add(B);I[d].add(B);J[b].add(P);J[c].add(P);J[d].add(P)}var b,c,d,e,f,g,h,i,j,l,n,m,r,u,p,q,w,v,z,y,t,D,C,k,I=[],J=[],B=new THREE.Vector3,P=new THREE.Vector3,A=new THREE.Vector3,G=new THREE.Vector3,E=new THREE.Vector3;
+b=0;for(c=this.vertices.length;b<c;b++)I[b]=new THREE.Vector3,J[b]=new THREE.Vector3;b=0;for(c=this.faces.length;b<c;b++)f=this.faces[b],g=this.faceVertexUvs[0][b],f instanceof THREE.Face3?a(this,f.a,f.b,f.c,0,1,2):f instanceof THREE.Face4&&(a(this,f.a,f.b,f.d,0,1,3),a(this,f.b,f.c,f.d,1,2,3));var F=["a","b","c","d"];b=0;for(c=this.faces.length;b<c;b++){f=this.faces[b];for(d=0;d<f.vertexNormals.length;d++)E.copy(f.vertexNormals[d]),e=f[F[d]],k=I[e],A.copy(k),A.sub(E.multiplyScalar(E.dot(k))).normalize(),
+G.crossVectors(f.vertexNormals[d],k),e=G.dot(J[e]),e=0>e?-1:1,f.vertexTangents[d]=new THREE.Vector4(A.x,A.y,A.z,e)}this.hasTangents=!0},computeLineDistances:function(){for(var a=0,b=this.vertices,c=0,d=b.length;c<d;c++)0<c&&(a+=b[c].distanceTo(b[c-1])),this.lineDistances[c]=a},computeBoundingBox:function(){null===this.boundingBox&&(this.boundingBox=new THREE.Box3);this.boundingBox.setFromPoints(this.vertices)},computeBoundingSphere:function(){null===this.boundingSphere&&(this.boundingSphere=new THREE.Sphere);
+this.boundingSphere.setFromCenterAndPoints(this.boundingSphere.center,this.vertices)},mergeVertices:function(){var a={},b=[],c=[],d,e=Math.pow(10,4),f,g,h,i,j;this.__tmpVertices=void 0;f=0;for(g=this.vertices.length;f<g;f++)d=this.vertices[f],d=[Math.round(d.x*e),Math.round(d.y*e),Math.round(d.z*e)].join("_"),void 0===a[d]?(a[d]=f,b.push(this.vertices[f]),c[f]=b.length-1):c[f]=c[a[d]];e=[];f=0;for(g=this.faces.length;f<g;f++)if(a=this.faces[f],a instanceof THREE.Face3){a.a=c[a.a];a.b=c[a.b];a.c=c[a.c];
+h=[a.a,a.b,a.c];d=-1;for(i=0;3>i;i++)if(h[i]==h[(i+1)%3]){e.push(f);break}}else if(a instanceof THREE.Face4){a.a=c[a.a];a.b=c[a.b];a.c=c[a.c];a.d=c[a.d];h=[a.a,a.b,a.c,a.d];d=-1;for(i=0;4>i;i++)h[i]==h[(i+1)%4]&&(0<=d&&e.push(f),d=i);if(0<=d){h.splice(d,1);var l=new THREE.Face3(h[0],h[1],h[2],a.normal,a.color,a.materialIndex);h=0;for(i=this.faceVertexUvs.length;h<i;h++)(j=this.faceVertexUvs[h][f])&&j.splice(d,1);a.vertexNormals&&0<a.vertexNormals.length&&(l.vertexNormals=a.vertexNormals,l.vertexNormals.splice(d,
 1));a.vertexColors&&0<a.vertexColors.length&&(l.vertexColors=a.vertexColors,l.vertexColors.splice(d,1));this.faces[f]=l}}for(f=e.length-1;0<=f;f--){this.faces.splice(f,1);h=0;for(i=this.faceVertexUvs.length;h<i;h++)this.faceVertexUvs[h].splice(f,1)}c=this.vertices.length-b.length;this.vertices=b;return c},clone:function(){for(var a=new THREE.Geometry,b=this.vertices,c=0,d=b.length;c<d;c++)a.vertices.push(b[c].clone());b=this.faces;c=0;for(d=b.length;c<d;c++)a.faces.push(b[c].clone());b=this.faceVertexUvs[0];
 1));a.vertexColors&&0<a.vertexColors.length&&(l.vertexColors=a.vertexColors,l.vertexColors.splice(d,1));this.faces[f]=l}}for(f=e.length-1;0<=f;f--){this.faces.splice(f,1);h=0;for(i=this.faceVertexUvs.length;h<i;h++)this.faceVertexUvs[h].splice(f,1)}c=this.vertices.length-b.length;this.vertices=b;return c},clone:function(){for(var a=new THREE.Geometry,b=this.vertices,c=0,d=b.length;c<d;c++)a.vertices.push(b[c].clone());b=this.faces;c=0;for(d=b.length;c<d;c++)a.faces.push(b[c].clone());b=this.faceVertexUvs[0];
 c=0;for(d=b.length;c<d;c++){for(var e=b[c],f=[],g=0,h=e.length;g<h;g++)f.push(new THREE.Vector2(e[g].x,e[g].y));a.faceVertexUvs[0].push(f)}return a},dispose:function(){this.dispatchEvent({type:"dispose"})}};THREE.GeometryIdCount=0;THREE.BufferGeometry=function(){THREE.EventDispatcher.call(this);this.id=THREE.GeometryIdCount++;this.attributes={};this.dynamic=!1;this.offsets=[];this.boundingSphere=this.boundingBox=null;this.hasTangents=!1;this.morphTargets=[]};
 c=0;for(d=b.length;c<d;c++){for(var e=b[c],f=[],g=0,h=e.length;g<h;g++)f.push(new THREE.Vector2(e[g].x,e[g].y));a.faceVertexUvs[0].push(f)}return a},dispose:function(){this.dispatchEvent({type:"dispose"})}};THREE.GeometryIdCount=0;THREE.BufferGeometry=function(){THREE.EventDispatcher.call(this);this.id=THREE.GeometryIdCount++;this.attributes={};this.dynamic=!1;this.offsets=[];this.boundingSphere=this.boundingBox=null;this.hasTangents=!1;this.morphTargets=[]};
 THREE.BufferGeometry.prototype={constructor:THREE.BufferGeometry,applyMatrix:function(a){var b,c;this.attributes.position&&(b=this.attributes.position.array);this.attributes.normal&&(c=this.attributes.normal.array);void 0!==b&&(a.multiplyVector3Array(b),this.verticesNeedUpdate=!0);void 0!==c&&(b=new THREE.Matrix3,b.getInverse(a).transpose(),b.multiplyVector3Array(c),this.normalizeNormals(),this.normalsNeedUpdate=!0)},computeBoundingBox:function(){null===this.boundingBox&&(this.boundingBox=new THREE.Box3);
 THREE.BufferGeometry.prototype={constructor:THREE.BufferGeometry,applyMatrix:function(a){var b,c;this.attributes.position&&(b=this.attributes.position.array);this.attributes.normal&&(c=this.attributes.normal.array);void 0!==b&&(a.multiplyVector3Array(b),this.verticesNeedUpdate=!0);void 0!==c&&(b=new THREE.Matrix3,b.getInverse(a).transpose(),b.multiplyVector3Array(c),this.normalizeNormals(),this.normalsNeedUpdate=!0)},computeBoundingBox:function(){null===this.boundingBox&&(this.boundingBox=new THREE.Box3);
 var a=this.attributes.position.array;if(a){var b=this.boundingBox,c,d,e;3<=a.length&&(b.min.x=b.max.x=a[0],b.min.y=b.max.y=a[1],b.min.z=b.max.z=a[2]);for(var f=3,g=a.length;f<g;f+=3)c=a[f],d=a[f+1],e=a[f+2],c<b.min.x?b.min.x=c:c>b.max.x&&(b.max.x=c),d<b.min.y?b.min.y=d:d>b.max.y&&(b.max.y=d),e<b.min.z?b.min.z=e:e>b.max.z&&(b.max.z=e)}if(void 0===a||0===a.length)this.boundingBox.min.set(0,0,0),this.boundingBox.max.set(0,0,0)},computeBoundingSphere:function(){null===this.boundingSphere&&(this.boundingSphere=
 var a=this.attributes.position.array;if(a){var b=this.boundingBox,c,d,e;3<=a.length&&(b.min.x=b.max.x=a[0],b.min.y=b.max.y=a[1],b.min.z=b.max.z=a[2]);for(var f=3,g=a.length;f<g;f+=3)c=a[f],d=a[f+1],e=a[f+2],c<b.min.x?b.min.x=c:c>b.max.x&&(b.max.x=c),d<b.min.y?b.min.y=d:d>b.max.y&&(b.max.y=d),e<b.min.z?b.min.z=e:e>b.max.z&&(b.max.z=e)}if(void 0===a||0===a.length)this.boundingBox.min.set(0,0,0),this.boundingBox.max.set(0,0,0)},computeBoundingSphere:function(){null===this.boundingSphere&&(this.boundingSphere=
 new THREE.Sphere);var a=this.attributes.position.array;if(a){for(var b,c=0,d,e,f=0,g=a.length;f<g;f+=3)b=a[f],d=a[f+1],e=a[f+2],b=b*b+d*d+e*e,b>c&&(c=b);this.boundingSphere.radius=Math.sqrt(c)}},computeVertexNormals:function(){if(this.attributes.position){var a,b,c,d;a=this.attributes.position.array.length;if(void 0===this.attributes.normal)this.attributes.normal={itemSize:3,array:new Float32Array(a),numItems:a};else{a=0;for(b=this.attributes.normal.array.length;a<b;a++)this.attributes.normal.array[a]=
 new THREE.Sphere);var a=this.attributes.position.array;if(a){for(var b,c=0,d,e,f=0,g=a.length;f<g;f+=3)b=a[f],d=a[f+1],e=a[f+2],b=b*b+d*d+e*e,b>c&&(c=b);this.boundingSphere.radius=Math.sqrt(c)}},computeVertexNormals:function(){if(this.attributes.position){var a,b,c,d;a=this.attributes.position.array.length;if(void 0===this.attributes.normal)this.attributes.normal={itemSize:3,array:new Float32Array(a),numItems:a};else{a=0;for(b=this.attributes.normal.array.length;a<b;a++)this.attributes.normal.array[a]=
-0}var e=this.attributes.position.array,f=this.attributes.normal.array,g,h,i,k,l,n,m=new THREE.Vector3,t=new THREE.Vector3,r=new THREE.Vector3,p=new THREE.Vector3,q=new THREE.Vector3;if(this.attributes.index){var y=this.attributes.index.array,v=this.offsets;c=0;for(d=v.length;c<d;++c){b=v[c].start;g=v[c].count;var z=v[c].index;a=b;for(b+=g;a<b;a+=3)g=z+y[a],h=z+y[a+1],i=z+y[a+2],k=e[3*g],l=e[3*g+1],n=e[3*g+2],m.set(k,l,n),k=e[3*h],l=e[3*h+1],n=e[3*h+2],t.set(k,l,n),k=e[3*i],l=e[3*i+1],n=e[3*i+2],r.set(k,
-l,n),p.subVectors(r,t),q.subVectors(m,t),p.cross(q),f[3*g]+=p.x,f[3*g+1]+=p.y,f[3*g+2]+=p.z,f[3*h]+=p.x,f[3*h+1]+=p.y,f[3*h+2]+=p.z,f[3*i]+=p.x,f[3*i+1]+=p.y,f[3*i+2]+=p.z}}else{a=0;for(b=e.length;a<b;a+=9)k=e[a],l=e[a+1],n=e[a+2],m.set(k,l,n),k=e[a+3],l=e[a+4],n=e[a+5],t.set(k,l,n),k=e[a+6],l=e[a+7],n=e[a+8],r.set(k,l,n),p.subVectors(r,t),q.subVectors(m,t),p.cross(q),f[a]=p.x,f[a+1]=p.y,f[a+2]=p.z,f[a+3]=p.x,f[a+4]=p.y,f[a+5]=p.z,f[a+6]=p.x,f[a+7]=p.y,f[a+8]=p.z}this.normalizeNormals();this.normalsNeedUpdate=
-!0}},normalizeNormals:function(){for(var a=this.attributes.normal.array,b,c,d,e=0,f=a.length;e<f;e+=3)b=a[e],c=a[e+1],d=a[e+2],b=1/Math.sqrt(b*b+c*c+d*d),a[e]*=b,a[e+1]*=b,a[e+2]*=b},computeTangents:function(){function a(a){ma.x=d[3*a];ma.y=d[3*a+1];ma.z=d[3*a+2];eb.copy(ma);T=i[a];N.copy(T);N.sub(ma.multiplyScalar(ma.dot(T))).normalize();fa.crossVectors(eb,T);ja=fa.dot(k[a]);M=0>ja?-1:1;h[4*a]=N.x;h[4*a+1]=N.y;h[4*a+2]=N.z;h[4*a+3]=M}if(void 0===this.attributes.index||void 0===this.attributes.position||
-void 0===this.attributes.normal||void 0===this.attributes.uv)console.warn("Missing required attributes (index, position, normal or uv) in BufferGeometry.computeTangents()");else{var b=this.attributes.index.array,c=this.attributes.position.array,d=this.attributes.normal.array,e=this.attributes.uv.array,f=c.length/3;if(void 0===this.attributes.tangent){var g=4*f;this.attributes.tangent={itemSize:4,array:new Float32Array(g),numItems:g}}for(var h=this.attributes.tangent.array,i=[],k=[],g=0;g<f;g++)i[g]=
-new THREE.Vector3,k[g]=new THREE.Vector3;var l,n,m,t,r,p,q,y,v,z,s,C,H,B,w,f=new THREE.Vector3,g=new THREE.Vector3,I,J,E,Z,A,U,F,G=this.offsets;E=0;for(Z=G.length;E<Z;++E){J=G[E].start;A=G[E].count;var K=G[E].index;I=J;for(J+=A;I<J;I+=3)A=K+b[I],U=K+b[I+1],F=K+b[I+2],l=c[3*A],n=c[3*A+1],m=c[3*A+2],t=c[3*U],r=c[3*U+1],p=c[3*U+2],q=c[3*F],y=c[3*F+1],v=c[3*F+2],z=e[2*A],s=e[2*A+1],C=e[2*U],H=e[2*U+1],B=e[2*F],w=e[2*F+1],t-=l,l=q-l,r-=n,n=y-n,p-=m,m=v-m,C-=z,z=B-z,H-=s,s=w-s,w=1/(C*s-z*H),f.set((s*t-
-H*l)*w,(s*r-H*n)*w,(s*p-H*m)*w),g.set((C*l-z*t)*w,(C*n-z*r)*w,(C*m-z*p)*w),i[A].add(f),i[U].add(f),i[F].add(f),k[A].add(g),k[U].add(g),k[F].add(g)}var N=new THREE.Vector3,fa=new THREE.Vector3,ma=new THREE.Vector3,eb=new THREE.Vector3,M,T,ja;E=0;for(Z=G.length;E<Z;++E){J=G[E].start;A=G[E].count;K=G[E].index;I=J;for(J+=A;I<J;I+=3)A=K+b[I],U=K+b[I+1],F=K+b[I+2],a(A),a(U),a(F)}this.tangentsNeedUpdate=this.hasTangents=!0}},dispose:function(){this.dispatchEvent({type:"dispose"})}};THREE.Camera=function(){THREE.Object3D.call(this);this.matrixWorldInverse=new THREE.Matrix4;this.projectionMatrix=new THREE.Matrix4;this.projectionMatrixInverse=new THREE.Matrix4};THREE.Camera.prototype=Object.create(THREE.Object3D.prototype);THREE.Camera.prototype.lookAt=function(){var a=new THREE.Matrix4;return function(b){a.lookAt(this.position,b,this.up);!0===this.useQuaternion?this.quaternion.setFromRotationMatrix(a):this.rotation.setEulerFromRotationMatrix(a,this.eulerOrder)}}();THREE.OrthographicCamera=function(a,b,c,d,e,f){THREE.Camera.call(this);this.left=a;this.right=b;this.top=c;this.bottom=d;this.near=void 0!==e?e:0.1;this.far=void 0!==f?f:2E3;this.updateProjectionMatrix()};THREE.OrthographicCamera.prototype=Object.create(THREE.Camera.prototype);THREE.OrthographicCamera.prototype.updateProjectionMatrix=function(){this.projectionMatrix.makeOrthographic(this.left,this.right,this.top,this.bottom,this.near,this.far)};THREE.PerspectiveCamera=function(a,b,c,d){THREE.Camera.call(this);this.fov=void 0!==a?a:50;this.aspect=void 0!==b?b:1;this.near=void 0!==c?c:0.1;this.far=void 0!==d?d:2E3;this.updateProjectionMatrix()};THREE.PerspectiveCamera.prototype=Object.create(THREE.Camera.prototype);THREE.PerspectiveCamera.prototype.setLens=function(a,b){void 0===b&&(b=24);this.fov=2*THREE.Math.radToDeg(Math.atan(b/(2*a)));this.updateProjectionMatrix()};
+0}var e=this.attributes.position.array,f=this.attributes.normal.array,g,h,i,j,l,n,m=new THREE.Vector3,r=new THREE.Vector3,u=new THREE.Vector3,p=new THREE.Vector3,q=new THREE.Vector3;if(this.attributes.index){var w=this.attributes.index.array,v=this.offsets;c=0;for(d=v.length;c<d;++c){b=v[c].start;g=v[c].count;var z=v[c].index;a=b;for(b+=g;a<b;a+=3)g=z+w[a],h=z+w[a+1],i=z+w[a+2],j=e[3*g],l=e[3*g+1],n=e[3*g+2],m.set(j,l,n),j=e[3*h],l=e[3*h+1],n=e[3*h+2],r.set(j,l,n),j=e[3*i],l=e[3*i+1],n=e[3*i+2],u.set(j,
+l,n),p.subVectors(u,r),q.subVectors(m,r),p.cross(q),f[3*g]+=p.x,f[3*g+1]+=p.y,f[3*g+2]+=p.z,f[3*h]+=p.x,f[3*h+1]+=p.y,f[3*h+2]+=p.z,f[3*i]+=p.x,f[3*i+1]+=p.y,f[3*i+2]+=p.z}}else{a=0;for(b=e.length;a<b;a+=9)j=e[a],l=e[a+1],n=e[a+2],m.set(j,l,n),j=e[a+3],l=e[a+4],n=e[a+5],r.set(j,l,n),j=e[a+6],l=e[a+7],n=e[a+8],u.set(j,l,n),p.subVectors(u,r),q.subVectors(m,r),p.cross(q),f[a]=p.x,f[a+1]=p.y,f[a+2]=p.z,f[a+3]=p.x,f[a+4]=p.y,f[a+5]=p.z,f[a+6]=p.x,f[a+7]=p.y,f[a+8]=p.z}this.normalizeNormals();this.normalsNeedUpdate=
+!0}},normalizeNormals:function(){for(var a=this.attributes.normal.array,b,c,d,e=0,f=a.length;e<f;e+=3)b=a[e],c=a[e+1],d=a[e+2],b=1/Math.sqrt(b*b+c*c+d*d),a[e]*=b,a[e+1]*=b,a[e+2]*=b},computeTangents:function(){function a(a){K.x=d[3*a];K.y=d[3*a+1];K.z=d[3*a+2];x.copy(K);R=i[a];H.copy(R);H.sub(K.multiplyScalar(K.dot(R))).normalize();O.crossVectors(x,R);$=O.dot(j[a]);N=0>$?-1:1;h[4*a]=H.x;h[4*a+1]=H.y;h[4*a+2]=H.z;h[4*a+3]=N}if(void 0===this.attributes.index||void 0===this.attributes.position||void 0===
+this.attributes.normal||void 0===this.attributes.uv)console.warn("Missing required attributes (index, position, normal or uv) in BufferGeometry.computeTangents()");else{var b=this.attributes.index.array,c=this.attributes.position.array,d=this.attributes.normal.array,e=this.attributes.uv.array,f=c.length/3;if(void 0===this.attributes.tangent){var g=4*f;this.attributes.tangent={itemSize:4,array:new Float32Array(g),numItems:g}}for(var h=this.attributes.tangent.array,i=[],j=[],g=0;g<f;g++)i[g]=new THREE.Vector3,
+j[g]=new THREE.Vector3;var l,n,m,r,u,p,q,w,v,z,y,t,D,C,k,f=new THREE.Vector3,g=new THREE.Vector3,I,J,B,P,A,G,E,F=this.offsets;B=0;for(P=F.length;B<P;++B){J=F[B].start;A=F[B].count;var s=F[B].index;I=J;for(J+=A;I<J;I+=3)A=s+b[I],G=s+b[I+1],E=s+b[I+2],l=c[3*A],n=c[3*A+1],m=c[3*A+2],r=c[3*G],u=c[3*G+1],p=c[3*G+2],q=c[3*E],w=c[3*E+1],v=c[3*E+2],z=e[2*A],y=e[2*A+1],t=e[2*G],D=e[2*G+1],C=e[2*E],k=e[2*E+1],r-=l,l=q-l,u-=n,n=w-n,p-=m,m=v-m,t-=z,z=C-z,D-=y,y=k-y,k=1/(t*y-z*D),f.set((y*r-D*l)*k,(y*u-D*n)*k,
+(y*p-D*m)*k),g.set((t*l-z*r)*k,(t*n-z*u)*k,(t*m-z*p)*k),i[A].add(f),i[G].add(f),i[E].add(f),j[A].add(g),j[G].add(g),j[E].add(g)}var H=new THREE.Vector3,O=new THREE.Vector3,K=new THREE.Vector3,x=new THREE.Vector3,N,R,$;B=0;for(P=F.length;B<P;++B){J=F[B].start;A=F[B].count;s=F[B].index;I=J;for(J+=A;I<J;I+=3)A=s+b[I],G=s+b[I+1],E=s+b[I+2],a(A),a(G),a(E)}this.tangentsNeedUpdate=this.hasTangents=!0}},dispose:function(){this.dispatchEvent({type:"dispose"})}};THREE.Camera=function(){THREE.Object3D.call(this);this.matrixWorldInverse=new THREE.Matrix4;this.projectionMatrix=new THREE.Matrix4;this.projectionMatrixInverse=new THREE.Matrix4};THREE.Camera.prototype=Object.create(THREE.Object3D.prototype);THREE.Camera.prototype.lookAt=function(){var a=new THREE.Matrix4;return function(b){a.lookAt(this.position,b,this.up);!0===this.useQuaternion?this.quaternion.setFromRotationMatrix(a):this.rotation.setEulerFromRotationMatrix(a,this.eulerOrder)}}();THREE.OrthographicCamera=function(a,b,c,d,e,f){THREE.Camera.call(this);this.left=a;this.right=b;this.top=c;this.bottom=d;this.near=void 0!==e?e:0.1;this.far=void 0!==f?f:2E3;this.updateProjectionMatrix()};THREE.OrthographicCamera.prototype=Object.create(THREE.Camera.prototype);THREE.OrthographicCamera.prototype.updateProjectionMatrix=function(){this.projectionMatrix.makeOrthographic(this.left,this.right,this.top,this.bottom,this.near,this.far)};THREE.PerspectiveCamera=function(a,b,c,d){THREE.Camera.call(this);this.fov=void 0!==a?a:50;this.aspect=void 0!==b?b:1;this.near=void 0!==c?c:0.1;this.far=void 0!==d?d:2E3;this.updateProjectionMatrix()};THREE.PerspectiveCamera.prototype=Object.create(THREE.Camera.prototype);THREE.PerspectiveCamera.prototype.setLens=function(a,b){void 0===b&&(b=24);this.fov=2*THREE.Math.radToDeg(Math.atan(b/(2*a)));this.updateProjectionMatrix()};
 THREE.PerspectiveCamera.prototype.setViewOffset=function(a,b,c,d,e,f){this.fullWidth=a;this.fullHeight=b;this.x=c;this.y=d;this.width=e;this.height=f;this.updateProjectionMatrix()};
 THREE.PerspectiveCamera.prototype.setViewOffset=function(a,b,c,d,e,f){this.fullWidth=a;this.fullHeight=b;this.x=c;this.y=d;this.width=e;this.height=f;this.updateProjectionMatrix()};
 THREE.PerspectiveCamera.prototype.updateProjectionMatrix=function(){if(this.fullWidth){var a=this.fullWidth/this.fullHeight,b=Math.tan(THREE.Math.degToRad(0.5*this.fov))*this.near,c=-b,d=a*c,a=Math.abs(a*b-d),c=Math.abs(b-c);this.projectionMatrix.makeFrustum(d+this.x*a/this.fullWidth,d+(this.x+this.width)*a/this.fullWidth,b-(this.y+this.height)*c/this.fullHeight,b-this.y*c/this.fullHeight,this.near,this.far)}else this.projectionMatrix.makePerspective(this.fov,this.aspect,this.near,this.far)};THREE.Light=function(a){THREE.Object3D.call(this);this.color=new THREE.Color(a)};THREE.Light.prototype=Object.create(THREE.Object3D.prototype);THREE.AmbientLight=function(a){THREE.Light.call(this,a)};THREE.AmbientLight.prototype=Object.create(THREE.Light.prototype);THREE.AreaLight=function(a,b){THREE.Light.call(this,a);this.normal=new THREE.Vector3(0,-1,0);this.right=new THREE.Vector3(1,0,0);this.intensity=void 0!==b?b:1;this.height=this.width=1;this.constantAttenuation=1.5;this.linearAttenuation=0.5;this.quadraticAttenuation=0.1};THREE.AreaLight.prototype=Object.create(THREE.Light.prototype);THREE.DirectionalLight=function(a,b){THREE.Light.call(this,a);this.position=new THREE.Vector3(0,1,0);this.target=new THREE.Object3D;this.intensity=void 0!==b?b:1;this.onlyShadow=this.castShadow=!1;this.shadowCameraNear=50;this.shadowCameraFar=5E3;this.shadowCameraLeft=-500;this.shadowCameraTop=this.shadowCameraRight=500;this.shadowCameraBottom=-500;this.shadowCameraVisible=!1;this.shadowBias=0;this.shadowDarkness=0.5;this.shadowMapHeight=this.shadowMapWidth=512;this.shadowCascade=!1;this.shadowCascadeOffset=
 THREE.PerspectiveCamera.prototype.updateProjectionMatrix=function(){if(this.fullWidth){var a=this.fullWidth/this.fullHeight,b=Math.tan(THREE.Math.degToRad(0.5*this.fov))*this.near,c=-b,d=a*c,a=Math.abs(a*b-d),c=Math.abs(b-c);this.projectionMatrix.makeFrustum(d+this.x*a/this.fullWidth,d+(this.x+this.width)*a/this.fullWidth,b-(this.y+this.height)*c/this.fullHeight,b-this.y*c/this.fullHeight,this.near,this.far)}else this.projectionMatrix.makePerspective(this.fov,this.aspect,this.near,this.far)};THREE.Light=function(a){THREE.Object3D.call(this);this.color=new THREE.Color(a)};THREE.Light.prototype=Object.create(THREE.Object3D.prototype);THREE.AmbientLight=function(a){THREE.Light.call(this,a)};THREE.AmbientLight.prototype=Object.create(THREE.Light.prototype);THREE.AreaLight=function(a,b){THREE.Light.call(this,a);this.normal=new THREE.Vector3(0,-1,0);this.right=new THREE.Vector3(1,0,0);this.intensity=void 0!==b?b:1;this.height=this.width=1;this.constantAttenuation=1.5;this.linearAttenuation=0.5;this.quadraticAttenuation=0.1};THREE.AreaLight.prototype=Object.create(THREE.Light.prototype);THREE.DirectionalLight=function(a,b){THREE.Light.call(this,a);this.position=new THREE.Vector3(0,1,0);this.target=new THREE.Object3D;this.intensity=void 0!==b?b:1;this.onlyShadow=this.castShadow=!1;this.shadowCameraNear=50;this.shadowCameraFar=5E3;this.shadowCameraLeft=-500;this.shadowCameraTop=this.shadowCameraRight=500;this.shadowCameraBottom=-500;this.shadowCameraVisible=!1;this.shadowBias=0;this.shadowDarkness=0.5;this.shadowMapHeight=this.shadowMapWidth=512;this.shadowCascade=!1;this.shadowCascadeOffset=
 new THREE.Vector3(0,0,-1E3);this.shadowCascadeCount=2;this.shadowCascadeBias=[0,0,0];this.shadowCascadeWidth=[512,512,512];this.shadowCascadeHeight=[512,512,512];this.shadowCascadeNearZ=[-1,0.99,0.998];this.shadowCascadeFarZ=[0.99,0.998,1];this.shadowCascadeArray=[];this.shadowMatrix=this.shadowCamera=this.shadowMapSize=this.shadowMap=null};THREE.DirectionalLight.prototype=Object.create(THREE.Light.prototype);THREE.HemisphereLight=function(a,b,c){THREE.Light.call(this,a);this.groundColor=new THREE.Color(b);this.position=new THREE.Vector3(0,100,0);this.intensity=void 0!==c?c:1};THREE.HemisphereLight.prototype=Object.create(THREE.Light.prototype);THREE.PointLight=function(a,b,c){THREE.Light.call(this,a);this.position=new THREE.Vector3(0,0,0);this.intensity=void 0!==b?b:1;this.distance=void 0!==c?c:0};THREE.PointLight.prototype=Object.create(THREE.Light.prototype);THREE.SpotLight=function(a,b,c,d,e){THREE.Light.call(this,a);this.position=new THREE.Vector3(0,1,0);this.target=new THREE.Object3D;this.intensity=void 0!==b?b:1;this.distance=void 0!==c?c:0;this.angle=void 0!==d?d:Math.PI/2;this.exponent=void 0!==e?e:10;this.onlyShadow=this.castShadow=!1;this.shadowCameraNear=50;this.shadowCameraFar=5E3;this.shadowCameraFov=50;this.shadowCameraVisible=!1;this.shadowBias=0;this.shadowDarkness=0.5;this.shadowMapHeight=this.shadowMapWidth=512;this.shadowMatrix=this.shadowCamera=
 new THREE.Vector3(0,0,-1E3);this.shadowCascadeCount=2;this.shadowCascadeBias=[0,0,0];this.shadowCascadeWidth=[512,512,512];this.shadowCascadeHeight=[512,512,512];this.shadowCascadeNearZ=[-1,0.99,0.998];this.shadowCascadeFarZ=[0.99,0.998,1];this.shadowCascadeArray=[];this.shadowMatrix=this.shadowCamera=this.shadowMapSize=this.shadowMap=null};THREE.DirectionalLight.prototype=Object.create(THREE.Light.prototype);THREE.HemisphereLight=function(a,b,c){THREE.Light.call(this,a);this.groundColor=new THREE.Color(b);this.position=new THREE.Vector3(0,100,0);this.intensity=void 0!==c?c:1};THREE.HemisphereLight.prototype=Object.create(THREE.Light.prototype);THREE.PointLight=function(a,b,c){THREE.Light.call(this,a);this.position=new THREE.Vector3(0,0,0);this.intensity=void 0!==b?b:1;this.distance=void 0!==c?c:0};THREE.PointLight.prototype=Object.create(THREE.Light.prototype);THREE.SpotLight=function(a,b,c,d,e){THREE.Light.call(this,a);this.position=new THREE.Vector3(0,1,0);this.target=new THREE.Object3D;this.intensity=void 0!==b?b:1;this.distance=void 0!==c?c:0;this.angle=void 0!==d?d:Math.PI/2;this.exponent=void 0!==e?e:10;this.onlyShadow=this.castShadow=!1;this.shadowCameraNear=50;this.shadowCameraFar=5E3;this.shadowCameraFov=50;this.shadowCameraVisible=!1;this.shadowBias=0;this.shadowDarkness=0.5;this.shadowMapHeight=this.shadowMapWidth=512;this.shadowMatrix=this.shadowCamera=
 this.shadowMapSize=this.shadowMap=null};THREE.SpotLight.prototype=Object.create(THREE.Light.prototype);THREE.Loader=function(a){this.statusDomElement=(this.showStatus=a)?THREE.Loader.prototype.addStatusElement():null;this.onLoadStart=function(){};this.onLoadProgress=function(){};this.onLoadComplete=function(){}};
 this.shadowMapSize=this.shadowMap=null};THREE.SpotLight.prototype=Object.create(THREE.Light.prototype);THREE.Loader=function(a){this.statusDomElement=(this.showStatus=a)?THREE.Loader.prototype.addStatusElement():null;this.onLoadStart=function(){};this.onLoadProgress=function(){};this.onLoadComplete=function(){}};
 THREE.Loader.prototype={constructor:THREE.Loader,crossOrigin:"anonymous",addStatusElement:function(){var a=document.createElement("div");a.style.position="absolute";a.style.right="0px";a.style.top="0px";a.style.fontSize="0.8em";a.style.textAlign="left";a.style.background="rgba(0,0,0,0.25)";a.style.color="#fff";a.style.width="120px";a.style.padding="0.5em 0.5em 0.5em 0.5em";a.style.zIndex=1E3;a.innerHTML="Loading ...";return a},updateProgress:function(a){var b="Loaded ",b=a.total?b+((100*a.loaded/
 THREE.Loader.prototype={constructor:THREE.Loader,crossOrigin:"anonymous",addStatusElement:function(){var a=document.createElement("div");a.style.position="absolute";a.style.right="0px";a.style.top="0px";a.style.fontSize="0.8em";a.style.textAlign="left";a.style.background="rgba(0,0,0,0.25)";a.style.color="#fff";a.style.width="120px";a.style.padding="0.5em 0.5em 0.5em 0.5em";a.style.zIndex=1E3;a.innerHTML="Loading ...";return a},updateProgress:function(a){var b="Loaded ",b=a.total?b+((100*a.loaded/
 a.total).toFixed(0)+"%"):b+((a.loaded/1E3).toFixed(2)+" KB");this.statusDomElement.innerHTML=b},extractUrlBase:function(a){a=a.split("/");a.pop();return(1>a.length?".":a.join("/"))+"/"},initMaterials:function(a,b){for(var c=[],d=0;d<a.length;++d)c[d]=THREE.Loader.prototype.createMaterial(a[d],b);return c},needsTangents:function(a){for(var b=0,c=a.length;b<c;b++)if(a[b]instanceof THREE.ShaderMaterial)return!0;return!1},createMaterial:function(a,b){function c(a){a=Math.log(a)/Math.LN2;return Math.floor(a)==
 a.total).toFixed(0)+"%"):b+((a.loaded/1E3).toFixed(2)+" KB");this.statusDomElement.innerHTML=b},extractUrlBase:function(a){a=a.split("/");a.pop();return(1>a.length?".":a.join("/"))+"/"},initMaterials:function(a,b){for(var c=[],d=0;d<a.length;++d)c[d]=THREE.Loader.prototype.createMaterial(a[d],b);return c},needsTangents:function(a){for(var b=0,c=a.length;b<c;b++)if(a[b]instanceof THREE.ShaderMaterial)return!0;return!1},createMaterial:function(a,b){function c(a){a=Math.log(a)/Math.LN2;return Math.floor(a)==
-a}function d(a){a=Math.log(a)/Math.LN2;return Math.pow(2,Math.round(a))}function e(a,e,f,h,i,k,q){var y=/\.dds$/i.test(f),v=b+"/"+f;if(y){var z=THREE.ImageUtils.loadCompressedTexture(v);a[e]=z}else z=document.createElement("canvas"),a[e]=new THREE.Texture(z);a[e].sourceFile=f;h&&(a[e].repeat.set(h[0],h[1]),1!==h[0]&&(a[e].wrapS=THREE.RepeatWrapping),1!==h[1]&&(a[e].wrapT=THREE.RepeatWrapping));i&&a[e].offset.set(i[0],i[1]);k&&(f={repeat:THREE.RepeatWrapping,mirror:THREE.MirroredRepeatWrapping},void 0!==
-f[k[0]]&&(a[e].wrapS=f[k[0]]),void 0!==f[k[1]]&&(a[e].wrapT=f[k[1]]));q&&(a[e].anisotropy=q);if(!y){var s=a[e],a=new Image;a.onload=function(){if(!c(this.width)||!c(this.height)){var a=d(this.width),b=d(this.height);s.image.width=a;s.image.height=b;s.image.getContext("2d").drawImage(this,0,0,a,b)}else s.image=this;s.needsUpdate=!0};a.crossOrigin=g.crossOrigin;a.src=v}}function f(a){return(255*a[0]<<16)+(255*a[1]<<8)+255*a[2]}var g=this,h="MeshLambertMaterial",i={color:15658734,opacity:1,map:null,
-lightMap:null,normalMap:null,bumpMap:null,wireframe:!1};if(a.shading){var k=a.shading.toLowerCase();"phong"===k?h="MeshPhongMaterial":"basic"===k&&(h="MeshBasicMaterial")}void 0!==a.blending&&void 0!==THREE[a.blending]&&(i.blending=THREE[a.blending]);if(void 0!==a.transparent||1>a.opacity)i.transparent=a.transparent;void 0!==a.depthTest&&(i.depthTest=a.depthTest);void 0!==a.depthWrite&&(i.depthWrite=a.depthWrite);void 0!==a.visible&&(i.visible=a.visible);void 0!==a.flipSided&&(i.side=THREE.BackSide);
+a}function d(a){a=Math.log(a)/Math.LN2;return Math.pow(2,Math.round(a))}function e(a,e,f,i,h,j,q){var w=/\.dds$/i.test(f),v=b+"/"+f;if(w){var z=THREE.ImageUtils.loadCompressedTexture(v);a[e]=z}else z=document.createElement("canvas"),a[e]=new THREE.Texture(z);a[e].sourceFile=f;i&&(a[e].repeat.set(i[0],i[1]),1!==i[0]&&(a[e].wrapS=THREE.RepeatWrapping),1!==i[1]&&(a[e].wrapT=THREE.RepeatWrapping));h&&a[e].offset.set(h[0],h[1]);j&&(f={repeat:THREE.RepeatWrapping,mirror:THREE.MirroredRepeatWrapping},void 0!==
+f[j[0]]&&(a[e].wrapS=f[j[0]]),void 0!==f[j[1]]&&(a[e].wrapT=f[j[1]]));q&&(a[e].anisotropy=q);if(!w){var y=a[e],a=new Image;a.onload=function(){if(!c(this.width)||!c(this.height)){var a=d(this.width),b=d(this.height);y.image.width=a;y.image.height=b;y.image.getContext("2d").drawImage(this,0,0,a,b)}else y.image=this;y.needsUpdate=!0};a.crossOrigin=g.crossOrigin;a.src=v}}function f(a){return(255*a[0]<<16)+(255*a[1]<<8)+255*a[2]}var g=this,h="MeshLambertMaterial",i={color:15658734,opacity:1,map:null,
+lightMap:null,normalMap:null,bumpMap:null,wireframe:!1};if(a.shading){var j=a.shading.toLowerCase();"phong"===j?h="MeshPhongMaterial":"basic"===j&&(h="MeshBasicMaterial")}void 0!==a.blending&&void 0!==THREE[a.blending]&&(i.blending=THREE[a.blending]);if(void 0!==a.transparent||1>a.opacity)i.transparent=a.transparent;void 0!==a.depthTest&&(i.depthTest=a.depthTest);void 0!==a.depthWrite&&(i.depthWrite=a.depthWrite);void 0!==a.visible&&(i.visible=a.visible);void 0!==a.flipSided&&(i.side=THREE.BackSide);
 void 0!==a.doubleSided&&(i.side=THREE.DoubleSide);void 0!==a.wireframe&&(i.wireframe=a.wireframe);void 0!==a.vertexColors&&("face"===a.vertexColors?i.vertexColors=THREE.FaceColors:a.vertexColors&&(i.vertexColors=THREE.VertexColors));a.colorDiffuse?i.color=f(a.colorDiffuse):a.DbgColor&&(i.color=a.DbgColor);a.colorSpecular&&(i.specular=f(a.colorSpecular));a.colorAmbient&&(i.ambient=f(a.colorAmbient));a.transparency&&(i.opacity=a.transparency);a.specularCoef&&(i.shininess=a.specularCoef);a.mapDiffuse&&
 void 0!==a.doubleSided&&(i.side=THREE.DoubleSide);void 0!==a.wireframe&&(i.wireframe=a.wireframe);void 0!==a.vertexColors&&("face"===a.vertexColors?i.vertexColors=THREE.FaceColors:a.vertexColors&&(i.vertexColors=THREE.VertexColors));a.colorDiffuse?i.color=f(a.colorDiffuse):a.DbgColor&&(i.color=a.DbgColor);a.colorSpecular&&(i.specular=f(a.colorSpecular));a.colorAmbient&&(i.ambient=f(a.colorAmbient));a.transparency&&(i.opacity=a.transparency);a.specularCoef&&(i.shininess=a.specularCoef);a.mapDiffuse&&
 b&&e(i,"map",a.mapDiffuse,a.mapDiffuseRepeat,a.mapDiffuseOffset,a.mapDiffuseWrap,a.mapDiffuseAnisotropy);a.mapLight&&b&&e(i,"lightMap",a.mapLight,a.mapLightRepeat,a.mapLightOffset,a.mapLightWrap,a.mapLightAnisotropy);a.mapBump&&b&&e(i,"bumpMap",a.mapBump,a.mapBumpRepeat,a.mapBumpOffset,a.mapBumpWrap,a.mapBumpAnisotropy);a.mapNormal&&b&&e(i,"normalMap",a.mapNormal,a.mapNormalRepeat,a.mapNormalOffset,a.mapNormalWrap,a.mapNormalAnisotropy);a.mapSpecular&&b&&e(i,"specularMap",a.mapSpecular,a.mapSpecularRepeat,
 b&&e(i,"map",a.mapDiffuse,a.mapDiffuseRepeat,a.mapDiffuseOffset,a.mapDiffuseWrap,a.mapDiffuseAnisotropy);a.mapLight&&b&&e(i,"lightMap",a.mapLight,a.mapLightRepeat,a.mapLightOffset,a.mapLightWrap,a.mapLightAnisotropy);a.mapBump&&b&&e(i,"bumpMap",a.mapBump,a.mapBumpRepeat,a.mapBumpOffset,a.mapBumpWrap,a.mapBumpAnisotropy);a.mapNormal&&b&&e(i,"normalMap",a.mapNormal,a.mapNormalRepeat,a.mapNormalOffset,a.mapNormalWrap,a.mapNormalAnisotropy);a.mapSpecular&&b&&e(i,"specularMap",a.mapSpecular,a.mapSpecularRepeat,
-a.mapSpecularOffset,a.mapSpecularWrap,a.mapSpecularAnisotropy);a.mapBumpScale&&(i.bumpScale=a.mapBumpScale);a.mapNormal?(h=THREE.ShaderLib.normalmap,k=THREE.UniformsUtils.clone(h.uniforms),k.tNormal.value=i.normalMap,a.mapNormalFactor&&k.uNormalScale.value.set(a.mapNormalFactor,a.mapNormalFactor),i.map&&(k.tDiffuse.value=i.map,k.enableDiffuse.value=!0),i.specularMap&&(k.tSpecular.value=i.specularMap,k.enableSpecular.value=!0),i.lightMap&&(k.tAO.value=i.lightMap,k.enableAO.value=!0),k.uDiffuseColor.value.setHex(i.color),
-k.uSpecularColor.value.setHex(i.specular),k.uAmbientColor.value.setHex(i.ambient),k.uShininess.value=i.shininess,void 0!==i.opacity&&(k.uOpacity.value=i.opacity),h=new THREE.ShaderMaterial({fragmentShader:h.fragmentShader,vertexShader:h.vertexShader,uniforms:k,lights:!0,fog:!0}),i.transparent&&(h.transparent=!0)):h=new THREE[h](i);void 0!==a.DbgName&&(h.name=a.DbgName);return h}};THREE.ImageLoader=function(){THREE.EventDispatcher.call(this);this.crossOrigin=null};THREE.ImageLoader.prototype={constructor:THREE.ImageLoader,load:function(a,b){var c=this;void 0===b&&(b=new Image);b.addEventListener("load",function(){c.dispatchEvent({type:"load",content:b})},!1);b.addEventListener("error",function(){c.dispatchEvent({type:"error",message:"Couldn't load URL ["+a+"]"})},!1);c.crossOrigin&&(b.crossOrigin=c.crossOrigin);b.src=a}};THREE.JSONLoader=function(a){THREE.Loader.call(this,a);this.withCredentials=!1};THREE.JSONLoader.prototype=Object.create(THREE.Loader.prototype);THREE.JSONLoader.prototype.load=function(a,b,c){c=c&&"string"===typeof c?c:this.extractUrlBase(a);this.onLoadStart();this.loadAjaxJSON(this,a,b,c)};
+a.mapSpecularOffset,a.mapSpecularWrap,a.mapSpecularAnisotropy);a.mapBumpScale&&(i.bumpScale=a.mapBumpScale);a.mapNormal?(h=THREE.ShaderLib.normalmap,j=THREE.UniformsUtils.clone(h.uniforms),j.tNormal.value=i.normalMap,a.mapNormalFactor&&j.uNormalScale.value.set(a.mapNormalFactor,a.mapNormalFactor),i.map&&(j.tDiffuse.value=i.map,j.enableDiffuse.value=!0),i.specularMap&&(j.tSpecular.value=i.specularMap,j.enableSpecular.value=!0),i.lightMap&&(j.tAO.value=i.lightMap,j.enableAO.value=!0),j.uDiffuseColor.value.setHex(i.color),
+j.uSpecularColor.value.setHex(i.specular),j.uAmbientColor.value.setHex(i.ambient),j.uShininess.value=i.shininess,void 0!==i.opacity&&(j.uOpacity.value=i.opacity),h=new THREE.ShaderMaterial({fragmentShader:h.fragmentShader,vertexShader:h.vertexShader,uniforms:j,lights:!0,fog:!0}),i.transparent&&(h.transparent=!0)):h=new THREE[h](i);void 0!==a.DbgName&&(h.name=a.DbgName);return h}};THREE.ImageLoader=function(){THREE.EventDispatcher.call(this);this.crossOrigin=null};THREE.ImageLoader.prototype={constructor:THREE.ImageLoader,load:function(a,b){var c=this;void 0===b&&(b=new Image);b.addEventListener("load",function(){c.dispatchEvent({type:"load",content:b})},!1);b.addEventListener("error",function(){c.dispatchEvent({type:"error",message:"Couldn't load URL ["+a+"]"})},!1);c.crossOrigin&&(b.crossOrigin=c.crossOrigin);b.src=a}};THREE.JSONLoader=function(a){THREE.Loader.call(this,a);this.withCredentials=!1};THREE.JSONLoader.prototype=Object.create(THREE.Loader.prototype);THREE.JSONLoader.prototype.load=function(a,b,c){c=c&&"string"===typeof c?c:this.extractUrlBase(a);this.onLoadStart();this.loadAjaxJSON(this,a,b,c)};
 THREE.JSONLoader.prototype.loadAjaxJSON=function(a,b,c,d,e){var f=new XMLHttpRequest,g=0;f.onreadystatechange=function(){if(f.readyState===f.DONE)if(200===f.status||0===f.status){if(f.responseText){var h=JSON.parse(f.responseText);a.createModel(h,c,d)}else console.warn("THREE.JSONLoader: ["+b+"] seems to be unreachable or file there is empty");a.onLoadComplete()}else console.error("THREE.JSONLoader: Couldn't load ["+b+"] ["+f.status+"]");else f.readyState===f.LOADING?e&&(0===g&&(g=f.getResponseHeader("Content-Length")),
 THREE.JSONLoader.prototype.loadAjaxJSON=function(a,b,c,d,e){var f=new XMLHttpRequest,g=0;f.onreadystatechange=function(){if(f.readyState===f.DONE)if(200===f.status||0===f.status){if(f.responseText){var h=JSON.parse(f.responseText);a.createModel(h,c,d)}else console.warn("THREE.JSONLoader: ["+b+"] seems to be unreachable or file there is empty");a.onLoadComplete()}else console.error("THREE.JSONLoader: Couldn't load ["+b+"] ["+f.status+"]");else f.readyState===f.LOADING?e&&(0===g&&(g=f.getResponseHeader("Content-Length")),
 e({total:g,loaded:f.responseText.length})):f.readyState===f.HEADERS_RECEIVED&&(g=f.getResponseHeader("Content-Length"))};f.open("GET",b,!0);f.withCredentials=this.withCredentials;f.send(null)};
 e({total:g,loaded:f.responseText.length})):f.readyState===f.HEADERS_RECEIVED&&(g=f.getResponseHeader("Content-Length"))};f.open("GET",b,!0);f.withCredentials=this.withCredentials;f.send(null)};
-THREE.JSONLoader.prototype.createModel=function(a,b,c){var d=new THREE.Geometry,e=void 0!==a.scale?1/a.scale:1,f,g,h,i,k,l,n,m,t,r,p,q,y,v,z,s=a.faces;r=a.vertices;var C=a.normals,H=a.colors,B=0;for(f=0;f<a.uvs.length;f++)a.uvs[f].length&&B++;for(f=0;f<B;f++)d.faceUvs[f]=[],d.faceVertexUvs[f]=[];i=0;for(k=r.length;i<k;)l=new THREE.Vector3,l.x=r[i++]*e,l.y=r[i++]*e,l.z=r[i++]*e,d.vertices.push(l);i=0;for(k=s.length;i<k;){r=s[i++];l=r&1;h=r&2;f=r&4;g=r&8;m=r&16;n=r&32;p=r&64;r&=128;l?(q=new THREE.Face4,
-q.a=s[i++],q.b=s[i++],q.c=s[i++],q.d=s[i++],l=4):(q=new THREE.Face3,q.a=s[i++],q.b=s[i++],q.c=s[i++],l=3);h&&(h=s[i++],q.materialIndex=h);h=d.faces.length;if(f)for(f=0;f<B;f++)y=a.uvs[f],t=s[i++],z=y[2*t],t=y[2*t+1],d.faceUvs[f][h]=new THREE.Vector2(z,t);if(g)for(f=0;f<B;f++){y=a.uvs[f];v=[];for(g=0;g<l;g++)t=s[i++],z=y[2*t],t=y[2*t+1],v[g]=new THREE.Vector2(z,t);d.faceVertexUvs[f][h]=v}m&&(m=3*s[i++],g=new THREE.Vector3,g.x=C[m++],g.y=C[m++],g.z=C[m],q.normal=g);if(n)for(f=0;f<l;f++)m=3*s[i++],g=
-new THREE.Vector3,g.x=C[m++],g.y=C[m++],g.z=C[m],q.vertexNormals.push(g);p&&(n=s[i++],n=new THREE.Color(H[n]),q.color=n);if(r)for(f=0;f<l;f++)n=s[i++],n=new THREE.Color(H[n]),q.vertexColors.push(n);d.faces.push(q)}if(a.skinWeights){i=0;for(k=a.skinWeights.length;i<k;i+=2)s=a.skinWeights[i],C=a.skinWeights[i+1],d.skinWeights.push(new THREE.Vector4(s,C,0,0))}if(a.skinIndices){i=0;for(k=a.skinIndices.length;i<k;i+=2)s=a.skinIndices[i],C=a.skinIndices[i+1],d.skinIndices.push(new THREE.Vector4(s,C,0,0))}d.bones=
-a.bones;d.animation=a.animation;if(void 0!==a.morphTargets){i=0;for(k=a.morphTargets.length;i<k;i++){d.morphTargets[i]={};d.morphTargets[i].name=a.morphTargets[i].name;d.morphTargets[i].vertices=[];H=d.morphTargets[i].vertices;B=a.morphTargets[i].vertices;s=0;for(C=B.length;s<C;s+=3)r=new THREE.Vector3,r.x=B[s]*e,r.y=B[s+1]*e,r.z=B[s+2]*e,H.push(r)}}if(void 0!==a.morphColors){i=0;for(k=a.morphColors.length;i<k;i++){d.morphColors[i]={};d.morphColors[i].name=a.morphColors[i].name;d.morphColors[i].colors=
-[];C=d.morphColors[i].colors;H=a.morphColors[i].colors;e=0;for(s=H.length;e<s;e+=3)B=new THREE.Color(16755200),B.setRGB(H[e],H[e+1],H[e+2]),C.push(B)}}d.computeCentroids();d.computeFaceNormals();a=this.initMaterials(a.materials,c);this.needsTangents(a)&&d.computeTangents();b(d,a)};THREE.LoadingMonitor=function(){THREE.EventDispatcher.call(this);var a=this,b=0,c=0,d=function(){b++;a.dispatchEvent({type:"progress",loaded:b,total:c});b===c&&a.dispatchEvent({type:"load"})};this.add=function(a){c++;a.addEventListener("load",d,!1)}};THREE.SceneLoader=function(){this.onLoadStart=function(){};this.onLoadProgress=function(){};this.onLoadComplete=function(){};this.callbackSync=function(){};this.callbackProgress=function(){};this.geometryHandlerMap={};this.hierarchyHandlerMap={};this.addGeometryHandler("ascii",THREE.JSONLoader)};THREE.SceneLoader.prototype.constructor=THREE.SceneLoader;
+THREE.JSONLoader.prototype.createModel=function(a,b,c){var d=new THREE.Geometry,e=void 0!==a.scale?1/a.scale:1,f,g,h,i,j,l,n,m,r,u,p,q,w,v,z,y=a.faces;u=a.vertices;var t=a.normals,D=a.colors,C=0;for(f=0;f<a.uvs.length;f++)a.uvs[f].length&&C++;for(f=0;f<C;f++)d.faceUvs[f]=[],d.faceVertexUvs[f]=[];i=0;for(j=u.length;i<j;)l=new THREE.Vector3,l.x=u[i++]*e,l.y=u[i++]*e,l.z=u[i++]*e,d.vertices.push(l);i=0;for(j=y.length;i<j;){u=y[i++];l=u&1;h=u&2;f=u&4;g=u&8;m=u&16;n=u&32;p=u&64;u&=128;l?(q=new THREE.Face4,
+q.a=y[i++],q.b=y[i++],q.c=y[i++],q.d=y[i++],l=4):(q=new THREE.Face3,q.a=y[i++],q.b=y[i++],q.c=y[i++],l=3);h&&(h=y[i++],q.materialIndex=h);h=d.faces.length;if(f)for(f=0;f<C;f++)w=a.uvs[f],r=y[i++],z=w[2*r],r=w[2*r+1],d.faceUvs[f][h]=new THREE.Vector2(z,r);if(g)for(f=0;f<C;f++){w=a.uvs[f];v=[];for(g=0;g<l;g++)r=y[i++],z=w[2*r],r=w[2*r+1],v[g]=new THREE.Vector2(z,r);d.faceVertexUvs[f][h]=v}m&&(m=3*y[i++],g=new THREE.Vector3,g.x=t[m++],g.y=t[m++],g.z=t[m],q.normal=g);if(n)for(f=0;f<l;f++)m=3*y[i++],g=
+new THREE.Vector3,g.x=t[m++],g.y=t[m++],g.z=t[m],q.vertexNormals.push(g);p&&(n=y[i++],n=new THREE.Color(D[n]),q.color=n);if(u)for(f=0;f<l;f++)n=y[i++],n=new THREE.Color(D[n]),q.vertexColors.push(n);d.faces.push(q)}if(a.skinWeights){i=0;for(j=a.skinWeights.length;i<j;i+=2)y=a.skinWeights[i],t=a.skinWeights[i+1],d.skinWeights.push(new THREE.Vector4(y,t,0,0))}if(a.skinIndices){i=0;for(j=a.skinIndices.length;i<j;i+=2)y=a.skinIndices[i],t=a.skinIndices[i+1],d.skinIndices.push(new THREE.Vector4(y,t,0,0))}d.bones=
+a.bones;d.animation=a.animation;if(void 0!==a.morphTargets){i=0;for(j=a.morphTargets.length;i<j;i++){d.morphTargets[i]={};d.morphTargets[i].name=a.morphTargets[i].name;d.morphTargets[i].vertices=[];D=d.morphTargets[i].vertices;C=a.morphTargets[i].vertices;y=0;for(t=C.length;y<t;y+=3)u=new THREE.Vector3,u.x=C[y]*e,u.y=C[y+1]*e,u.z=C[y+2]*e,D.push(u)}}if(void 0!==a.morphColors){i=0;for(j=a.morphColors.length;i<j;i++){d.morphColors[i]={};d.morphColors[i].name=a.morphColors[i].name;d.morphColors[i].colors=
+[];t=d.morphColors[i].colors;D=a.morphColors[i].colors;e=0;for(y=D.length;e<y;e+=3)C=new THREE.Color(16755200),C.setRGB(D[e],D[e+1],D[e+2]),t.push(C)}}d.computeCentroids();d.computeFaceNormals();a=this.initMaterials(a.materials,c);this.needsTangents(a)&&d.computeTangents();b(d,a)};THREE.LoadingMonitor=function(){THREE.EventDispatcher.call(this);var a=this,b=0,c=0,d=function(){b++;a.dispatchEvent({type:"progress",loaded:b,total:c});b===c&&a.dispatchEvent({type:"load"})};this.add=function(a){c++;a.addEventListener("load",d,!1)}};THREE.SceneLoader=function(){this.onLoadStart=function(){};this.onLoadProgress=function(){};this.onLoadComplete=function(){};this.callbackSync=function(){};this.callbackProgress=function(){};this.geometryHandlerMap={};this.hierarchyHandlerMap={};this.addGeometryHandler("ascii",THREE.JSONLoader)};THREE.SceneLoader.prototype.constructor=THREE.SceneLoader;
 THREE.SceneLoader.prototype.load=function(a,b){var c=this,d=new XMLHttpRequest;d.onreadystatechange=function(){if(4===d.readyState)if(200===d.status||0===d.status){var e=JSON.parse(d.responseText);c.parse(e,b,a)}else console.error("THREE.SceneLoader: Couldn't load ["+a+"] ["+d.status+"]")};d.open("GET",a,!0);d.send(null)};THREE.SceneLoader.prototype.addGeometryHandler=function(a,b){this.geometryHandlerMap[a]={loaderClass:b}};
 THREE.SceneLoader.prototype.load=function(a,b){var c=this,d=new XMLHttpRequest;d.onreadystatechange=function(){if(4===d.readyState)if(200===d.status||0===d.status){var e=JSON.parse(d.responseText);c.parse(e,b,a)}else console.error("THREE.SceneLoader: Couldn't load ["+a+"] ["+d.status+"]")};d.open("GET",a,!0);d.send(null)};THREE.SceneLoader.prototype.addGeometryHandler=function(a,b){this.geometryHandlerMap[a]={loaderClass:b}};
 THREE.SceneLoader.prototype.addHierarchyHandler=function(a,b){this.hierarchyHandlerMap[a]={loaderClass:b}};
 THREE.SceneLoader.prototype.addHierarchyHandler=function(a,b){this.hierarchyHandlerMap[a]={loaderClass:b}};
-THREE.SceneLoader.prototype.parse=function(a,b,c){function d(a,b){return"relativeToHTML"==b?a:n+"/"+a}function e(){f(w.scene,J.objects)}function f(a,b){var c,e,g,i,k,n,p;for(p in b)if(void 0===w.objects[p]){var q=b[p],s=null;if(q.type&&q.type in l.hierarchyHandlerMap){if(void 0===q.loading){e={type:1,url:1,material:1,position:1,rotation:1,scale:1,visible:1,children:1,properties:1,skin:1,morph:1,mirroredLoop:1,duration:1};g={};for(var A in q)A in e||(g[A]=q[A]);t=w.materials[q.material];q.loading=
-!0;e=l.hierarchyHandlerMap[q.type].loaderObject;e.options?e.load(d(q.url,J.urlBaseType),h(p,a,t,q)):e.load(d(q.url,J.urlBaseType),h(p,a,t,q),g)}}else if(void 0!==q.geometry){if(m=w.geometries[q.geometry]){s=!1;t=w.materials[q.material];s=t instanceof THREE.ShaderMaterial;g=q.position;i=q.rotation;k=q.scale;c=q.matrix;n=q.quaternion;q.material||(t=new THREE.MeshFaceMaterial(w.face_materials[q.geometry]));t instanceof THREE.MeshFaceMaterial&&0===t.materials.length&&(t=new THREE.MeshFaceMaterial(w.face_materials[q.geometry]));
-if(t instanceof THREE.MeshFaceMaterial)for(e=0;e<t.materials.length;e++)s=s||t.materials[e]instanceof THREE.ShaderMaterial;s&&m.computeTangents();q.skin?s=new THREE.SkinnedMesh(m,t):q.morph?(s=new THREE.MorphAnimMesh(m,t),void 0!==q.duration&&(s.duration=q.duration),void 0!==q.time&&(s.time=q.time),void 0!==q.mirroredLoop&&(s.mirroredLoop=q.mirroredLoop),t.morphNormals&&m.computeMorphNormals()):s=new THREE.Mesh(m,t);s.name=p;c?(s.matrixAutoUpdate=!1,s.matrix.set(c[0],c[1],c[2],c[3],c[4],c[5],c[6],
-c[7],c[8],c[9],c[10],c[11],c[12],c[13],c[14],c[15])):(s.position.set(g[0],g[1],g[2]),n?(s.quaternion.set(n[0],n[1],n[2],n[3]),s.useQuaternion=!0):s.rotation.set(i[0],i[1],i[2]),s.scale.set(k[0],k[1],k[2]));s.visible=q.visible;s.castShadow=q.castShadow;s.receiveShadow=q.receiveShadow;a.add(s);w.objects[p]=s}}else"DirectionalLight"===q.type||"PointLight"===q.type||"AmbientLight"===q.type?(v=void 0!==q.color?q.color:16777215,z=void 0!==q.intensity?q.intensity:1,"DirectionalLight"===q.type?(g=q.direction,
-y=new THREE.DirectionalLight(v,z),y.position.set(g[0],g[1],g[2]),q.target&&(I.push({object:y,targetName:q.target}),y.target=null)):"PointLight"===q.type?(g=q.position,e=q.distance,y=new THREE.PointLight(v,z,e),y.position.set(g[0],g[1],g[2])):"AmbientLight"===q.type&&(y=new THREE.AmbientLight(v)),a.add(y),y.name=p,w.lights[p]=y,w.objects[p]=y):"PerspectiveCamera"===q.type||"OrthographicCamera"===q.type?("PerspectiveCamera"===q.type?r=new THREE.PerspectiveCamera(q.fov,q.aspect,q.near,q.far):"OrthographicCamera"===
-q.type&&(r=new THREE.OrthographicCamera(q.left,q.right,q.top,q.bottom,q.near,q.far)),g=q.position,r.position.set(g[0],g[1],g[2]),a.add(r),r.name=p,w.cameras[p]=r,w.objects[p]=r):(g=q.position,i=q.rotation,k=q.scale,n=q.quaternion,s=new THREE.Object3D,s.name=p,s.position.set(g[0],g[1],g[2]),n?(s.quaternion.set(n[0],n[1],n[2],n[3]),s.useQuaternion=!0):s.rotation.set(i[0],i[1],i[2]),s.scale.set(k[0],k[1],k[2]),s.visible=void 0!==q.visible?q.visible:!1,a.add(s),w.objects[p]=s,w.empties[p]=s);if(s){if(void 0!==
-q.properties)for(var B in q.properties)s.properties[B]=q.properties[B];if(void 0!==q.groups)for(e=0;e<q.groups.length;e++)g=q.groups[e],void 0===w.groups[g]&&(w.groups[g]=[]),w.groups[g].push(p);void 0!==q.children&&f(s,q.children)}}}function g(a){return function(b,c){w.geometries[a]=b;w.face_materials[a]=c;e();s-=1;l.onLoadComplete();k()}}function h(a,b,c,d){return function(f){var f=f.content?f.content:f.dae?f.scene:f,g=d.position,h=d.rotation,i=d.quaternion,m=d.scale;f.position.set(g[0],g[1],g[2]);
-i?(f.quaternion.set(i[0],i[1],i[2],i[3]),f.useQuaternion=!0):f.rotation.set(h[0],h[1],h[2]);f.scale.set(m[0],m[1],m[2]);c&&f.traverse(function(a){a.material=c});var n=void 0!==d.visible?d.visible:!0;f.traverse(function(a){a.visible=n});b.add(f);f.name=a;w.objects[a]=f;e();s-=1;l.onLoadComplete();k()}}function i(a){return function(b,c){w.geometries[a]=b;w.face_materials[a]=c}}function k(){l.callbackProgress({totalModels:H,totalTextures:B,loadedModels:H-s,loadedTextures:B-C},w);l.onLoadProgress();if(0===
-s&&0===C){for(var a=0;a<I.length;a++){var c=I[a],d=w.objects[c.targetName];d?c.object.target=d:(c.object.target=new THREE.Object3D,w.scene.add(c.object.target));c.object.target.properties.targetInverse=c.object}b(w)}}var l=this,n=THREE.Loader.prototype.extractUrlBase(c),m,t,r,p,q,y,v,z,s,C,H,B,w,I=[],J=a,E;for(E in this.geometryHandlerMap)a=this.geometryHandlerMap[E].loaderClass,this.geometryHandlerMap[E].loaderObject=new a;for(E in this.hierarchyHandlerMap)a=this.hierarchyHandlerMap[E].loaderClass,
-this.hierarchyHandlerMap[E].loaderObject=new a;C=s=0;w={scene:new THREE.Scene,geometries:{},face_materials:{},materials:{},textures:{},objects:{},cameras:{},lights:{},fogs:{},empties:{},groups:{}};if(J.transform&&(E=J.transform.position,a=J.transform.rotation,c=J.transform.scale,E&&w.scene.position.set(E[0],E[1],E[2]),a&&w.scene.rotation.set(a[0],a[1],a[2]),c&&w.scene.scale.set(c[0],c[1],c[2]),E||a||c))w.scene.updateMatrix(),w.scene.updateMatrixWorld();E=function(a){return function(){C-=a;k();l.onLoadComplete()}};
-for(var Z in J.fogs)a=J.fogs[Z],"linear"===a.type?p=new THREE.Fog(0,a.near,a.far):"exp2"===a.type&&(p=new THREE.FogExp2(0,a.density)),a=a.color,p.color.setRGB(a[0],a[1],a[2]),w.fogs[Z]=p;for(var A in J.geometries)p=J.geometries[A],p.type in this.geometryHandlerMap&&(s+=1,l.onLoadStart());for(var U in J.objects)p=J.objects[U],p.type&&p.type in this.hierarchyHandlerMap&&(s+=1,l.onLoadStart());H=s;for(A in J.geometries)if(p=J.geometries[A],"cube"===p.type)m=new THREE.CubeGeometry(p.width,p.height,p.depth,
-p.widthSegments,p.heightSegments,p.depthSegments),w.geometries[A]=m;else if("plane"===p.type)m=new THREE.PlaneGeometry(p.width,p.height,p.widthSegments,p.heightSegments),w.geometries[A]=m;else if("sphere"===p.type)m=new THREE.SphereGeometry(p.radius,p.widthSegments,p.heightSegments),w.geometries[A]=m;else if("cylinder"===p.type)m=new THREE.CylinderGeometry(p.topRad,p.botRad,p.height,p.radSegs,p.heightSegs),w.geometries[A]=m;else if("torus"===p.type)m=new THREE.TorusGeometry(p.radius,p.tube,p.segmentsR,
-p.segmentsT),w.geometries[A]=m;else if("icosahedron"===p.type)m=new THREE.IcosahedronGeometry(p.radius,p.subdivisions),w.geometries[A]=m;else if(p.type in this.geometryHandlerMap){U={};for(q in p)"type"!==q&&"url"!==q&&(U[q]=p[q]);this.geometryHandlerMap[p.type].loaderObject.load(d(p.url,J.urlBaseType),g(A),U)}else"embedded"===p.type&&(U=J.embeds[p.id],U.metadata=J.metadata,U&&this.geometryHandlerMap.ascii.loaderObject.createModel(U,i(A),""));for(var F in J.textures)if(A=J.textures[F],A.url instanceof
-Array){C+=A.url.length;for(q=0;q<A.url.length;q++)l.onLoadStart()}else C+=1,l.onLoadStart();B=C;for(F in J.textures){A=J.textures[F];void 0!==A.mapping&&void 0!==THREE[A.mapping]&&(A.mapping=new THREE[A.mapping]);if(A.url instanceof Array){U=A.url.length;p=[];for(q=0;q<U;q++)p[q]=d(A.url[q],J.urlBaseType);q=(q=/\.dds$/i.test(p[0]))?THREE.ImageUtils.loadCompressedTextureCube(p,A.mapping,E(U)):THREE.ImageUtils.loadTextureCube(p,A.mapping,E(U))}else q=/\.dds$/i.test(A.url),U=d(A.url,J.urlBaseType),p=
-E(1),q=q?THREE.ImageUtils.loadCompressedTexture(U,A.mapping,p):THREE.ImageUtils.loadTexture(U,A.mapping,p),void 0!==THREE[A.minFilter]&&(q.minFilter=THREE[A.minFilter]),void 0!==THREE[A.magFilter]&&(q.magFilter=THREE[A.magFilter]),A.anisotropy&&(q.anisotropy=A.anisotropy),A.repeat&&(q.repeat.set(A.repeat[0],A.repeat[1]),1!==A.repeat[0]&&(q.wrapS=THREE.RepeatWrapping),1!==A.repeat[1]&&(q.wrapT=THREE.RepeatWrapping)),A.offset&&q.offset.set(A.offset[0],A.offset[1]),A.wrap&&(U={repeat:THREE.RepeatWrapping,
-mirror:THREE.MirroredRepeatWrapping},void 0!==U[A.wrap[0]]&&(q.wrapS=U[A.wrap[0]]),void 0!==U[A.wrap[1]]&&(q.wrapT=U[A.wrap[1]]));w.textures[F]=q}var G,K;for(G in J.materials){F=J.materials[G];for(K in F.parameters)"envMap"===K||"map"===K||"lightMap"===K||"bumpMap"===K?F.parameters[K]=w.textures[F.parameters[K]]:"shading"===K?F.parameters[K]="flat"===F.parameters[K]?THREE.FlatShading:THREE.SmoothShading:"side"===K?F.parameters[K]="double"==F.parameters[K]?THREE.DoubleSide:"back"==F.parameters[K]?
-THREE.BackSide:THREE.FrontSide:"blending"===K?F.parameters[K]=F.parameters[K]in THREE?THREE[F.parameters[K]]:THREE.NormalBlending:"combine"===K?F.parameters[K]=F.parameters[K]in THREE?THREE[F.parameters[K]]:THREE.MultiplyOperation:"vertexColors"===K?"face"==F.parameters[K]?F.parameters[K]=THREE.FaceColors:F.parameters[K]&&(F.parameters[K]=THREE.VertexColors):"wrapRGB"===K&&(E=F.parameters[K],F.parameters[K]=new THREE.Vector3(E[0],E[1],E[2]));void 0!==F.parameters.opacity&&1>F.parameters.opacity&&
-(F.parameters.transparent=!0);F.parameters.normalMap?(E=THREE.ShaderLib.normalmap,A=THREE.UniformsUtils.clone(E.uniforms),q=F.parameters.color,U=F.parameters.specular,p=F.parameters.ambient,Z=F.parameters.shininess,A.tNormal.value=w.textures[F.parameters.normalMap],F.parameters.normalScale&&A.uNormalScale.value.set(F.parameters.normalScale[0],F.parameters.normalScale[1]),F.parameters.map&&(A.tDiffuse.value=F.parameters.map,A.enableDiffuse.value=!0),F.parameters.envMap&&(A.tCube.value=F.parameters.envMap,
-A.enableReflection.value=!0,A.uReflectivity.value=F.parameters.reflectivity),F.parameters.lightMap&&(A.tAO.value=F.parameters.lightMap,A.enableAO.value=!0),F.parameters.specularMap&&(A.tSpecular.value=w.textures[F.parameters.specularMap],A.enableSpecular.value=!0),F.parameters.displacementMap&&(A.tDisplacement.value=w.textures[F.parameters.displacementMap],A.enableDisplacement.value=!0,A.uDisplacementBias.value=F.parameters.displacementBias,A.uDisplacementScale.value=F.parameters.displacementScale),
-A.uDiffuseColor.value.setHex(q),A.uSpecularColor.value.setHex(U),A.uAmbientColor.value.setHex(p),A.uShininess.value=Z,F.parameters.opacity&&(A.uOpacity.value=F.parameters.opacity),t=new THREE.ShaderMaterial({fragmentShader:E.fragmentShader,vertexShader:E.vertexShader,uniforms:A,lights:!0,fog:!0})):t=new THREE[F.type](F.parameters);w.materials[G]=t}for(G in J.materials)if(F=J.materials[G],F.parameters.materials){K=[];for(q=0;q<F.parameters.materials.length;q++)K.push(w.materials[F.parameters.materials[q]]);
-w.materials[G].materials=K}e();w.cameras&&J.defaults.camera&&(w.currentCamera=w.cameras[J.defaults.camera]);w.fogs&&J.defaults.fog&&(w.scene.fog=w.fogs[J.defaults.fog]);l.callbackSync(w);k()};THREE.TextureLoader=function(){THREE.EventDispatcher.call(this);this.crossOrigin=null};THREE.TextureLoader.prototype={constructor:THREE.TextureLoader,load:function(a){var b=this,c=new Image;c.addEventListener("load",function(){var a=new THREE.Texture(c);a.needsUpdate=!0;b.dispatchEvent({type:"load",content:a})},!1);c.addEventListener("error",function(){b.dispatchEvent({type:"error",message:"Couldn't load URL ["+a+"]"})},!1);b.crossOrigin&&(c.crossOrigin=b.crossOrigin);c.src=a}};THREE.Material=function(){THREE.EventDispatcher.call(this);this.id=THREE.MaterialIdCount++;this.name="";this.side=THREE.FrontSide;this.opacity=1;this.transparent=!1;this.blending=THREE.NormalBlending;this.blendSrc=THREE.SrcAlphaFactor;this.blendDst=THREE.OneMinusSrcAlphaFactor;this.blendEquation=THREE.AddEquation;this.depthWrite=this.depthTest=!0;this.polygonOffset=!1;this.alphaTest=this.polygonOffsetUnits=this.polygonOffsetFactor=0;this.overdraw=!1;this.needsUpdate=this.visible=!0};
+THREE.SceneLoader.prototype.parse=function(a,b,c){function d(a,b){return"relativeToHTML"==b?a:n+"/"+a}function e(){f(k.scene,J.objects)}function f(a,b){var c,e,g,i,j,n,p;for(p in b)if(void 0===k.objects[p]){var M=b[p],q=null;if(M.type&&M.type in l.hierarchyHandlerMap){if(void 0===M.loading){e={type:1,url:1,material:1,position:1,rotation:1,scale:1,visible:1,children:1,properties:1,skin:1,morph:1,mirroredLoop:1,duration:1};g={};for(var s in M)s in e||(g[s]=M[s]);r=k.materials[M.material];M.loading=
+!0;e=l.hierarchyHandlerMap[M.type].loaderObject;e.options?e.load(d(M.url,J.urlBaseType),h(p,a,r,M)):e.load(d(M.url,J.urlBaseType),h(p,a,r,M),g)}}else if(void 0!==M.geometry){if(m=k.geometries[M.geometry]){q=!1;r=k.materials[M.material];q=r instanceof THREE.ShaderMaterial;g=M.position;i=M.rotation;j=M.scale;c=M.matrix;n=M.quaternion;M.material||(r=new THREE.MeshFaceMaterial(k.face_materials[M.geometry]));r instanceof THREE.MeshFaceMaterial&&0===r.materials.length&&(r=new THREE.MeshFaceMaterial(k.face_materials[M.geometry]));
+if(r instanceof THREE.MeshFaceMaterial)for(e=0;e<r.materials.length;e++)q=q||r.materials[e]instanceof THREE.ShaderMaterial;q&&m.computeTangents();M.skin?q=new THREE.SkinnedMesh(m,r):M.morph?(q=new THREE.MorphAnimMesh(m,r),void 0!==M.duration&&(q.duration=M.duration),void 0!==M.time&&(q.time=M.time),void 0!==M.mirroredLoop&&(q.mirroredLoop=M.mirroredLoop),r.morphNormals&&m.computeMorphNormals()):q=new THREE.Mesh(m,r);q.name=p;c?(q.matrixAutoUpdate=!1,q.matrix.set(c[0],c[1],c[2],c[3],c[4],c[5],c[6],
+c[7],c[8],c[9],c[10],c[11],c[12],c[13],c[14],c[15])):(q.position.set(g[0],g[1],g[2]),n?(q.quaternion.set(n[0],n[1],n[2],n[3]),q.useQuaternion=!0):q.rotation.set(i[0],i[1],i[2]),q.scale.set(j[0],j[1],j[2]));q.visible=M.visible;q.castShadow=M.castShadow;q.receiveShadow=M.receiveShadow;a.add(q);k.objects[p]=q}}else"DirectionalLight"===M.type||"PointLight"===M.type||"AmbientLight"===M.type?(v=void 0!==M.color?M.color:16777215,z=void 0!==M.intensity?M.intensity:1,"DirectionalLight"===M.type?(g=M.direction,
+w=new THREE.DirectionalLight(v,z),w.position.set(g[0],g[1],g[2]),M.target&&(I.push({object:w,targetName:M.target}),w.target=null)):"PointLight"===M.type?(g=M.position,e=M.distance,w=new THREE.PointLight(v,z,e),w.position.set(g[0],g[1],g[2])):"AmbientLight"===M.type&&(w=new THREE.AmbientLight(v)),a.add(w),w.name=p,k.lights[p]=w,k.objects[p]=w):"PerspectiveCamera"===M.type||"OrthographicCamera"===M.type?("PerspectiveCamera"===M.type?u=new THREE.PerspectiveCamera(M.fov,M.aspect,M.near,M.far):"OrthographicCamera"===
+M.type&&(u=new THREE.OrthographicCamera(M.left,M.right,M.top,M.bottom,M.near,M.far)),g=M.position,u.position.set(g[0],g[1],g[2]),a.add(u),u.name=p,k.cameras[p]=u,k.objects[p]=u):(g=M.position,i=M.rotation,j=M.scale,n=M.quaternion,q=new THREE.Object3D,q.name=p,q.position.set(g[0],g[1],g[2]),n?(q.quaternion.set(n[0],n[1],n[2],n[3]),q.useQuaternion=!0):q.rotation.set(i[0],i[1],i[2]),q.scale.set(j[0],j[1],j[2]),q.visible=void 0!==M.visible?M.visible:!1,a.add(q),k.objects[p]=q,k.empties[p]=q);if(q){if(void 0!==
+M.properties)for(var t in M.properties)q.properties[t]=M.properties[t];if(void 0!==M.groups)for(e=0;e<M.groups.length;e++)g=M.groups[e],void 0===k.groups[g]&&(k.groups[g]=[]),k.groups[g].push(p);void 0!==M.children&&f(q,M.children)}}}function g(a){return function(b,c){k.geometries[a]=b;k.face_materials[a]=c;e();y-=1;l.onLoadComplete();j()}}function h(a,b,c,d){return function(f){var f=f.content?f.content:f.dae?f.scene:f,g=d.position,i=d.rotation,h=d.quaternion,m=d.scale;f.position.set(g[0],g[1],g[2]);
+h?(f.quaternion.set(h[0],h[1],h[2],h[3]),f.useQuaternion=!0):f.rotation.set(i[0],i[1],i[2]);f.scale.set(m[0],m[1],m[2]);c&&f.traverse(function(a){a.material=c});var n=void 0!==d.visible?d.visible:!0;f.traverse(function(a){a.visible=n});b.add(f);f.name=a;k.objects[a]=f;e();y-=1;l.onLoadComplete();j()}}function i(a){return function(b,c){k.geometries[a]=b;k.face_materials[a]=c}}function j(){l.callbackProgress({totalModels:D,totalTextures:C,loadedModels:D-y,loadedTextures:C-t},k);l.onLoadProgress();if(0===
+y&&0===t){for(var a=0;a<I.length;a++){var c=I[a],d=k.objects[c.targetName];d?c.object.target=d:(c.object.target=new THREE.Object3D,k.scene.add(c.object.target));c.object.target.properties.targetInverse=c.object}b(k)}}var l=this,n=THREE.Loader.prototype.extractUrlBase(c),m,r,u,p,q,w,v,z,y,t,D,C,k,I=[],J=a,B;for(B in this.geometryHandlerMap)a=this.geometryHandlerMap[B].loaderClass,this.geometryHandlerMap[B].loaderObject=new a;for(B in this.hierarchyHandlerMap)a=this.hierarchyHandlerMap[B].loaderClass,
+this.hierarchyHandlerMap[B].loaderObject=new a;t=y=0;k={scene:new THREE.Scene,geometries:{},face_materials:{},materials:{},textures:{},objects:{},cameras:{},lights:{},fogs:{},empties:{},groups:{}};if(J.transform&&(B=J.transform.position,a=J.transform.rotation,c=J.transform.scale,B&&k.scene.position.set(B[0],B[1],B[2]),a&&k.scene.rotation.set(a[0],a[1],a[2]),c&&k.scene.scale.set(c[0],c[1],c[2]),B||a||c))k.scene.updateMatrix(),k.scene.updateMatrixWorld();B=function(a){return function(){t-=a;j();l.onLoadComplete()}};
+for(var P in J.fogs)a=J.fogs[P],"linear"===a.type?p=new THREE.Fog(0,a.near,a.far):"exp2"===a.type&&(p=new THREE.FogExp2(0,a.density)),a=a.color,p.color.setRGB(a[0],a[1],a[2]),k.fogs[P]=p;for(var A in J.geometries)p=J.geometries[A],p.type in this.geometryHandlerMap&&(y+=1,l.onLoadStart());for(var G in J.objects)p=J.objects[G],p.type&&p.type in this.hierarchyHandlerMap&&(y+=1,l.onLoadStart());D=y;for(A in J.geometries)if(p=J.geometries[A],"cube"===p.type)m=new THREE.CubeGeometry(p.width,p.height,p.depth,
+p.widthSegments,p.heightSegments,p.depthSegments),k.geometries[A]=m;else if("plane"===p.type)m=new THREE.PlaneGeometry(p.width,p.height,p.widthSegments,p.heightSegments),k.geometries[A]=m;else if("sphere"===p.type)m=new THREE.SphereGeometry(p.radius,p.widthSegments,p.heightSegments),k.geometries[A]=m;else if("cylinder"===p.type)m=new THREE.CylinderGeometry(p.topRad,p.botRad,p.height,p.radSegs,p.heightSegs),k.geometries[A]=m;else if("torus"===p.type)m=new THREE.TorusGeometry(p.radius,p.tube,p.segmentsR,
+p.segmentsT),k.geometries[A]=m;else if("icosahedron"===p.type)m=new THREE.IcosahedronGeometry(p.radius,p.subdivisions),k.geometries[A]=m;else if(p.type in this.geometryHandlerMap){G={};for(q in p)"type"!==q&&"url"!==q&&(G[q]=p[q]);this.geometryHandlerMap[p.type].loaderObject.load(d(p.url,J.urlBaseType),g(A),G)}else"embedded"===p.type&&(G=J.embeds[p.id],G.metadata=J.metadata,G&&this.geometryHandlerMap.ascii.loaderObject.createModel(G,i(A),""));for(var E in J.textures)if(A=J.textures[E],A.url instanceof
+Array){t+=A.url.length;for(q=0;q<A.url.length;q++)l.onLoadStart()}else t+=1,l.onLoadStart();C=t;for(E in J.textures){A=J.textures[E];void 0!==A.mapping&&void 0!==THREE[A.mapping]&&(A.mapping=new THREE[A.mapping]);if(A.url instanceof Array){G=A.url.length;p=[];for(q=0;q<G;q++)p[q]=d(A.url[q],J.urlBaseType);q=(q=/\.dds$/i.test(p[0]))?THREE.ImageUtils.loadCompressedTextureCube(p,A.mapping,B(G)):THREE.ImageUtils.loadTextureCube(p,A.mapping,B(G))}else q=/\.dds$/i.test(A.url),G=d(A.url,J.urlBaseType),p=
+B(1),q=q?THREE.ImageUtils.loadCompressedTexture(G,A.mapping,p):THREE.ImageUtils.loadTexture(G,A.mapping,p),void 0!==THREE[A.minFilter]&&(q.minFilter=THREE[A.minFilter]),void 0!==THREE[A.magFilter]&&(q.magFilter=THREE[A.magFilter]),A.anisotropy&&(q.anisotropy=A.anisotropy),A.repeat&&(q.repeat.set(A.repeat[0],A.repeat[1]),1!==A.repeat[0]&&(q.wrapS=THREE.RepeatWrapping),1!==A.repeat[1]&&(q.wrapT=THREE.RepeatWrapping)),A.offset&&q.offset.set(A.offset[0],A.offset[1]),A.wrap&&(G={repeat:THREE.RepeatWrapping,
+mirror:THREE.MirroredRepeatWrapping},void 0!==G[A.wrap[0]]&&(q.wrapS=G[A.wrap[0]]),void 0!==G[A.wrap[1]]&&(q.wrapT=G[A.wrap[1]]));k.textures[E]=q}var F,s;for(F in J.materials){E=J.materials[F];for(s in E.parameters)"envMap"===s||"map"===s||"lightMap"===s||"bumpMap"===s?E.parameters[s]=k.textures[E.parameters[s]]:"shading"===s?E.parameters[s]="flat"===E.parameters[s]?THREE.FlatShading:THREE.SmoothShading:"side"===s?E.parameters[s]="double"==E.parameters[s]?THREE.DoubleSide:"back"==E.parameters[s]?
+THREE.BackSide:THREE.FrontSide:"blending"===s?E.parameters[s]=E.parameters[s]in THREE?THREE[E.parameters[s]]:THREE.NormalBlending:"combine"===s?E.parameters[s]=E.parameters[s]in THREE?THREE[E.parameters[s]]:THREE.MultiplyOperation:"vertexColors"===s?"face"==E.parameters[s]?E.parameters[s]=THREE.FaceColors:E.parameters[s]&&(E.parameters[s]=THREE.VertexColors):"wrapRGB"===s&&(B=E.parameters[s],E.parameters[s]=new THREE.Vector3(B[0],B[1],B[2]));void 0!==E.parameters.opacity&&1>E.parameters.opacity&&
+(E.parameters.transparent=!0);E.parameters.normalMap?(B=THREE.ShaderLib.normalmap,A=THREE.UniformsUtils.clone(B.uniforms),q=E.parameters.color,G=E.parameters.specular,p=E.parameters.ambient,P=E.parameters.shininess,A.tNormal.value=k.textures[E.parameters.normalMap],E.parameters.normalScale&&A.uNormalScale.value.set(E.parameters.normalScale[0],E.parameters.normalScale[1]),E.parameters.map&&(A.tDiffuse.value=E.parameters.map,A.enableDiffuse.value=!0),E.parameters.envMap&&(A.tCube.value=E.parameters.envMap,
+A.enableReflection.value=!0,A.uReflectivity.value=E.parameters.reflectivity),E.parameters.lightMap&&(A.tAO.value=E.parameters.lightMap,A.enableAO.value=!0),E.parameters.specularMap&&(A.tSpecular.value=k.textures[E.parameters.specularMap],A.enableSpecular.value=!0),E.parameters.displacementMap&&(A.tDisplacement.value=k.textures[E.parameters.displacementMap],A.enableDisplacement.value=!0,A.uDisplacementBias.value=E.parameters.displacementBias,A.uDisplacementScale.value=E.parameters.displacementScale),
+A.uDiffuseColor.value.setHex(q),A.uSpecularColor.value.setHex(G),A.uAmbientColor.value.setHex(p),A.uShininess.value=P,E.parameters.opacity&&(A.uOpacity.value=E.parameters.opacity),r=new THREE.ShaderMaterial({fragmentShader:B.fragmentShader,vertexShader:B.vertexShader,uniforms:A,lights:!0,fog:!0})):r=new THREE[E.type](E.parameters);k.materials[F]=r}for(F in J.materials)if(E=J.materials[F],E.parameters.materials){s=[];for(q=0;q<E.parameters.materials.length;q++)s.push(k.materials[E.parameters.materials[q]]);
+k.materials[F].materials=s}e();k.cameras&&J.defaults.camera&&(k.currentCamera=k.cameras[J.defaults.camera]);k.fogs&&J.defaults.fog&&(k.scene.fog=k.fogs[J.defaults.fog]);l.callbackSync(k);j()};THREE.TextureLoader=function(){THREE.EventDispatcher.call(this);this.crossOrigin=null};THREE.TextureLoader.prototype={constructor:THREE.TextureLoader,load:function(a){var b=this,c=new Image;c.addEventListener("load",function(){var a=new THREE.Texture(c);a.needsUpdate=!0;b.dispatchEvent({type:"load",content:a})},!1);c.addEventListener("error",function(){b.dispatchEvent({type:"error",message:"Couldn't load URL ["+a+"]"})},!1);b.crossOrigin&&(c.crossOrigin=b.crossOrigin);c.src=a}};THREE.Material=function(){THREE.EventDispatcher.call(this);this.id=THREE.MaterialIdCount++;this.name="";this.side=THREE.FrontSide;this.opacity=1;this.transparent=!1;this.blending=THREE.NormalBlending;this.blendSrc=THREE.SrcAlphaFactor;this.blendDst=THREE.OneMinusSrcAlphaFactor;this.blendEquation=THREE.AddEquation;this.depthWrite=this.depthTest=!0;this.polygonOffset=!1;this.alphaTest=this.polygonOffsetUnits=this.polygonOffsetFactor=0;this.overdraw=!1;this.needsUpdate=this.visible=!0};
 THREE.Material.prototype.setValues=function(a){if(void 0!==a)for(var b in a){var c=a[b];if(void 0===c)console.warn("THREE.Material: '"+b+"' parameter is undefined.");else if(b in this){var d=this[b];d instanceof THREE.Color&&c instanceof THREE.Color?d.copy(c):d instanceof THREE.Color?d.set(c):d instanceof THREE.Vector3&&c instanceof THREE.Vector3?d.copy(c):this[b]=c}}};
 THREE.Material.prototype.setValues=function(a){if(void 0!==a)for(var b in a){var c=a[b];if(void 0===c)console.warn("THREE.Material: '"+b+"' parameter is undefined.");else if(b in this){var d=this[b];d instanceof THREE.Color&&c instanceof THREE.Color?d.copy(c):d instanceof THREE.Color?d.set(c):d instanceof THREE.Vector3&&c instanceof THREE.Vector3?d.copy(c):this[b]=c}}};
 THREE.Material.prototype.clone=function(a){void 0===a&&(a=new THREE.Material);a.name=this.name;a.side=this.side;a.opacity=this.opacity;a.transparent=this.transparent;a.blending=this.blending;a.blendSrc=this.blendSrc;a.blendDst=this.blendDst;a.blendEquation=this.blendEquation;a.depthTest=this.depthTest;a.depthWrite=this.depthWrite;a.polygonOffset=this.polygonOffset;a.polygonOffsetFactor=this.polygonOffsetFactor;a.polygonOffsetUnits=this.polygonOffsetUnits;a.alphaTest=this.alphaTest;a.overdraw=this.overdraw;
 THREE.Material.prototype.clone=function(a){void 0===a&&(a=new THREE.Material);a.name=this.name;a.side=this.side;a.opacity=this.opacity;a.transparent=this.transparent;a.blending=this.blending;a.blendSrc=this.blendSrc;a.blendDst=this.blendDst;a.blendEquation=this.blendEquation;a.depthTest=this.depthTest;a.depthWrite=this.depthWrite;a.polygonOffset=this.polygonOffset;a.polygonOffsetFactor=this.polygonOffsetFactor;a.polygonOffsetUnits=this.polygonOffsetUnits;a.alphaTest=this.alphaTest;a.overdraw=this.overdraw;
 a.visible=this.visible;return a};THREE.Material.prototype.dispose=function(){this.dispatchEvent({type:"dispose"})};THREE.MaterialIdCount=0;THREE.LineBasicMaterial=function(a){THREE.Material.call(this);this.color=new THREE.Color(16777215);this.linewidth=1;this.linejoin=this.linecap="round";this.vertexColors=!1;this.fog=!0;this.setValues(a)};THREE.LineBasicMaterial.prototype=Object.create(THREE.Material.prototype);
 a.visible=this.visible;return a};THREE.Material.prototype.dispose=function(){this.dispatchEvent({type:"dispose"})};THREE.MaterialIdCount=0;THREE.LineBasicMaterial=function(a){THREE.Material.call(this);this.color=new THREE.Color(16777215);this.linewidth=1;this.linejoin=this.linecap="round";this.vertexColors=!1;this.fog=!0;this.setValues(a)};THREE.LineBasicMaterial.prototype=Object.create(THREE.Material.prototype);
@@ -245,7 +242,7 @@ THREE.SpriteMaterial.prototype.clone=function(){var a=new THREE.SpriteMaterial;T
 THREE.SpriteAlignment.topCenter=new THREE.Vector2(0,-1);THREE.SpriteAlignment.topRight=new THREE.Vector2(-1,-1);THREE.SpriteAlignment.centerLeft=new THREE.Vector2(1,0);THREE.SpriteAlignment.center=new THREE.Vector2(0,0);THREE.SpriteAlignment.centerRight=new THREE.Vector2(-1,0);THREE.SpriteAlignment.bottomLeft=new THREE.Vector2(1,1);THREE.SpriteAlignment.bottomCenter=new THREE.Vector2(0,1);THREE.SpriteAlignment.bottomRight=new THREE.Vector2(-1,1);THREE.Texture=function(a,b,c,d,e,f,g,h,i){THREE.EventDispatcher.call(this);this.id=THREE.TextureIdCount++;this.name="";this.image=a;this.mipmaps=[];this.mapping=void 0!==b?b:new THREE.UVMapping;this.wrapS=void 0!==c?c:THREE.ClampToEdgeWrapping;this.wrapT=void 0!==d?d:THREE.ClampToEdgeWrapping;this.magFilter=void 0!==e?e:THREE.LinearFilter;this.minFilter=void 0!==f?f:THREE.LinearMipMapLinearFilter;this.anisotropy=void 0!==i?i:1;this.format=void 0!==g?g:THREE.RGBAFormat;this.type=void 0!==h?h:THREE.UnsignedByteType;
 THREE.SpriteAlignment.topCenter=new THREE.Vector2(0,-1);THREE.SpriteAlignment.topRight=new THREE.Vector2(-1,-1);THREE.SpriteAlignment.centerLeft=new THREE.Vector2(1,0);THREE.SpriteAlignment.center=new THREE.Vector2(0,0);THREE.SpriteAlignment.centerRight=new THREE.Vector2(-1,0);THREE.SpriteAlignment.bottomLeft=new THREE.Vector2(1,1);THREE.SpriteAlignment.bottomCenter=new THREE.Vector2(0,1);THREE.SpriteAlignment.bottomRight=new THREE.Vector2(-1,1);THREE.Texture=function(a,b,c,d,e,f,g,h,i){THREE.EventDispatcher.call(this);this.id=THREE.TextureIdCount++;this.name="";this.image=a;this.mipmaps=[];this.mapping=void 0!==b?b:new THREE.UVMapping;this.wrapS=void 0!==c?c:THREE.ClampToEdgeWrapping;this.wrapT=void 0!==d?d:THREE.ClampToEdgeWrapping;this.magFilter=void 0!==e?e:THREE.LinearFilter;this.minFilter=void 0!==f?f:THREE.LinearMipMapLinearFilter;this.anisotropy=void 0!==i?i:1;this.format=void 0!==g?g:THREE.RGBAFormat;this.type=void 0!==h?h:THREE.UnsignedByteType;
 this.offset=new THREE.Vector2(0,0);this.repeat=new THREE.Vector2(1,1);this.generateMipmaps=!0;this.premultiplyAlpha=!1;this.flipY=!0;this.unpackAlignment=4;this.needsUpdate=!1;this.onUpdate=null};
 this.offset=new THREE.Vector2(0,0);this.repeat=new THREE.Vector2(1,1);this.generateMipmaps=!0;this.premultiplyAlpha=!1;this.flipY=!0;this.unpackAlignment=4;this.needsUpdate=!1;this.onUpdate=null};
 THREE.Texture.prototype={constructor:THREE.Texture,clone:function(a){void 0===a&&(a=new THREE.Texture);a.image=this.image;a.mipmaps=this.mipmaps.slice(0);a.mapping=this.mapping;a.wrapS=this.wrapS;a.wrapT=this.wrapT;a.magFilter=this.magFilter;a.minFilter=this.minFilter;a.anisotropy=this.anisotropy;a.format=this.format;a.type=this.type;a.offset.copy(this.offset);a.repeat.copy(this.repeat);a.generateMipmaps=this.generateMipmaps;a.premultiplyAlpha=this.premultiplyAlpha;a.flipY=this.flipY;a.unpackAlignment=
 THREE.Texture.prototype={constructor:THREE.Texture,clone:function(a){void 0===a&&(a=new THREE.Texture);a.image=this.image;a.mipmaps=this.mipmaps.slice(0);a.mapping=this.mapping;a.wrapS=this.wrapS;a.wrapT=this.wrapT;a.magFilter=this.magFilter;a.minFilter=this.minFilter;a.anisotropy=this.anisotropy;a.format=this.format;a.type=this.type;a.offset.copy(this.offset);a.repeat.copy(this.repeat);a.generateMipmaps=this.generateMipmaps;a.premultiplyAlpha=this.premultiplyAlpha;a.flipY=this.flipY;a.unpackAlignment=
-this.unpackAlignment;return a},dispose:function(){this.dispatchEvent({type:"dispose"})}};THREE.TextureIdCount=0;THREE.CompressedTexture=function(a,b,c,d,e,f,g,h,i,k,l){THREE.Texture.call(this,null,f,g,h,i,k,d,e,l);this.image={width:b,height:c};this.mipmaps=a;this.generateMipmaps=!1};THREE.CompressedTexture.prototype=Object.create(THREE.Texture.prototype);THREE.CompressedTexture.prototype.clone=function(){var a=new THREE.CompressedTexture;THREE.Texture.prototype.clone.call(this,a);return a};THREE.DataTexture=function(a,b,c,d,e,f,g,h,i,k,l){THREE.Texture.call(this,null,f,g,h,i,k,d,e,l);this.image={data:a,width:b,height:c}};THREE.DataTexture.prototype=Object.create(THREE.Texture.prototype);THREE.DataTexture.prototype.clone=function(){var a=new THREE.DataTexture;THREE.Texture.prototype.clone.call(this,a);return a};THREE.Particle=function(a){THREE.Object3D.call(this);this.material=a};THREE.Particle.prototype=Object.create(THREE.Object3D.prototype);THREE.Particle.prototype.clone=function(a){void 0===a&&(a=new THREE.Particle(this.material));THREE.Object3D.prototype.clone.call(this,a);return a};THREE.ParticleSystem=function(a,b){THREE.Object3D.call(this);this.geometry=a;this.material=void 0!==b?b:new THREE.ParticleBasicMaterial({color:16777215*Math.random()});this.sortParticles=!1;this.geometry&&null===this.geometry.boundingSphere&&this.geometry.computeBoundingSphere();this.frustumCulled=!1};THREE.ParticleSystem.prototype=Object.create(THREE.Object3D.prototype);
+this.unpackAlignment;return a},dispose:function(){this.dispatchEvent({type:"dispose"})}};THREE.TextureIdCount=0;THREE.CompressedTexture=function(a,b,c,d,e,f,g,h,i,j,l){THREE.Texture.call(this,null,f,g,h,i,j,d,e,l);this.image={width:b,height:c};this.mipmaps=a;this.generateMipmaps=!1};THREE.CompressedTexture.prototype=Object.create(THREE.Texture.prototype);THREE.CompressedTexture.prototype.clone=function(){var a=new THREE.CompressedTexture;THREE.Texture.prototype.clone.call(this,a);return a};THREE.DataTexture=function(a,b,c,d,e,f,g,h,i,j,l){THREE.Texture.call(this,null,f,g,h,i,j,d,e,l);this.image={data:a,width:b,height:c}};THREE.DataTexture.prototype=Object.create(THREE.Texture.prototype);THREE.DataTexture.prototype.clone=function(){var a=new THREE.DataTexture;THREE.Texture.prototype.clone.call(this,a);return a};THREE.Particle=function(a){THREE.Object3D.call(this);this.material=a};THREE.Particle.prototype=Object.create(THREE.Object3D.prototype);THREE.Particle.prototype.clone=function(a){void 0===a&&(a=new THREE.Particle(this.material));THREE.Object3D.prototype.clone.call(this,a);return a};THREE.ParticleSystem=function(a,b){THREE.Object3D.call(this);this.geometry=a;this.material=void 0!==b?b:new THREE.ParticleBasicMaterial({color:16777215*Math.random()});this.sortParticles=!1;this.geometry&&null===this.geometry.boundingSphere&&this.geometry.computeBoundingSphere();this.frustumCulled=!1};THREE.ParticleSystem.prototype=Object.create(THREE.Object3D.prototype);
 THREE.ParticleSystem.prototype.clone=function(a){void 0===a&&(a=new THREE.ParticleSystem(this.geometry,this.material));a.sortParticles=this.sortParticles;THREE.Object3D.prototype.clone.call(this,a);return a};THREE.Line=function(a,b,c){THREE.Object3D.call(this);this.geometry=a;this.material=void 0!==b?b:new THREE.LineBasicMaterial({color:16777215*Math.random()});this.type=void 0!==c?c:THREE.LineStrip;this.geometry&&(this.geometry.boundingSphere||this.geometry.computeBoundingSphere())};THREE.LineStrip=0;THREE.LinePieces=1;THREE.Line.prototype=Object.create(THREE.Object3D.prototype);
 THREE.ParticleSystem.prototype.clone=function(a){void 0===a&&(a=new THREE.ParticleSystem(this.geometry,this.material));a.sortParticles=this.sortParticles;THREE.Object3D.prototype.clone.call(this,a);return a};THREE.Line=function(a,b,c){THREE.Object3D.call(this);this.geometry=a;this.material=void 0!==b?b:new THREE.LineBasicMaterial({color:16777215*Math.random()});this.type=void 0!==c?c:THREE.LineStrip;this.geometry&&(this.geometry.boundingSphere||this.geometry.computeBoundingSphere())};THREE.LineStrip=0;THREE.LinePieces=1;THREE.Line.prototype=Object.create(THREE.Object3D.prototype);
 THREE.Line.prototype.clone=function(a){void 0===a&&(a=new THREE.Line(this.geometry,this.material,this.type));THREE.Object3D.prototype.clone.call(this,a);return a};THREE.Mesh=function(a,b){THREE.Object3D.call(this);this.geometry=a;this.material=void 0!==b?b:new THREE.MeshBasicMaterial({color:16777215*Math.random(),wireframe:!0});void 0!==this.geometry&&(null===this.geometry.boundingSphere&&this.geometry.computeBoundingSphere(),this.updateMorphTargets())};THREE.Mesh.prototype=Object.create(THREE.Object3D.prototype);
 THREE.Line.prototype.clone=function(a){void 0===a&&(a=new THREE.Line(this.geometry,this.material,this.type));THREE.Object3D.prototype.clone.call(this,a);return a};THREE.Mesh=function(a,b){THREE.Object3D.call(this);this.geometry=a;this.material=void 0!==b?b:new THREE.MeshBasicMaterial({color:16777215*Math.random(),wireframe:!0});void 0!==this.geometry&&(null===this.geometry.boundingSphere&&this.geometry.computeBoundingSphere(),this.updateMorphTargets())};THREE.Mesh.prototype=Object.create(THREE.Object3D.prototype);
 THREE.Mesh.prototype.updateMorphTargets=function(){if(0<this.geometry.morphTargets.length){this.morphTargetBase=-1;this.morphTargetForcedOrder=[];this.morphTargetInfluences=[];this.morphTargetDictionary={};for(var a=0,b=this.geometry.morphTargets.length;a<b;a++)this.morphTargetInfluences.push(0),this.morphTargetDictionary[this.geometry.morphTargets[a].name]=a}};
 THREE.Mesh.prototype.updateMorphTargets=function(){if(0<this.geometry.morphTargets.length){this.morphTargetBase=-1;this.morphTargetForcedOrder=[];this.morphTargetInfluences=[];this.morphTargetDictionary={};for(var a=0,b=this.geometry.morphTargets.length;a<b;a++)this.morphTargetInfluences.push(0),this.morphTargetDictionary[this.geometry.morphTargets[a].name]=a}};
@@ -265,36 +262,36 @@ THREE.LOD.prototype.update=function(a){if(1<this.LODs.length){a.matrixWorldInver
 !1}};THREE.LOD.prototype.clone=function(){};THREE.Sprite=function(a){THREE.Object3D.call(this);this.material=void 0!==a?a:new THREE.SpriteMaterial;this.rotation3d=this.rotation;this.rotation=0};THREE.Sprite.prototype=Object.create(THREE.Object3D.prototype);THREE.Sprite.prototype.updateMatrix=function(){this.matrix.setPosition(this.position);this.rotation3d.set(0,0,this.rotation);this.matrix.setRotationFromEuler(this.rotation3d);(1!==this.scale.x||1!==this.scale.y)&&this.matrix.scale(this.scale);this.matrixWorldNeedsUpdate=!0};
 !1}};THREE.LOD.prototype.clone=function(){};THREE.Sprite=function(a){THREE.Object3D.call(this);this.material=void 0!==a?a:new THREE.SpriteMaterial;this.rotation3d=this.rotation;this.rotation=0};THREE.Sprite.prototype=Object.create(THREE.Object3D.prototype);THREE.Sprite.prototype.updateMatrix=function(){this.matrix.setPosition(this.position);this.rotation3d.set(0,0,this.rotation);this.matrix.setRotationFromEuler(this.rotation3d);(1!==this.scale.x||1!==this.scale.y)&&this.matrix.scale(this.scale);this.matrixWorldNeedsUpdate=!0};
 THREE.Sprite.prototype.clone=function(a){void 0===a&&(a=new THREE.Sprite(this.material));THREE.Object3D.prototype.clone.call(this,a);return a};THREE.Scene=function(){THREE.Object3D.call(this);this.overrideMaterial=this.fog=null;this.matrixAutoUpdate=!1;this.__objects=[];this.__lights=[];this.__objectsAdded=[];this.__objectsRemoved=[]};THREE.Scene.prototype=Object.create(THREE.Object3D.prototype);
 THREE.Sprite.prototype.clone=function(a){void 0===a&&(a=new THREE.Sprite(this.material));THREE.Object3D.prototype.clone.call(this,a);return a};THREE.Scene=function(){THREE.Object3D.call(this);this.overrideMaterial=this.fog=null;this.matrixAutoUpdate=!1;this.__objects=[];this.__lights=[];this.__objectsAdded=[];this.__objectsRemoved=[]};THREE.Scene.prototype=Object.create(THREE.Object3D.prototype);
 THREE.Scene.prototype.__addObject=function(a){if(a instanceof THREE.Light)-1===this.__lights.indexOf(a)&&this.__lights.push(a),a.target&&void 0===a.target.parent&&this.add(a.target);else if(!(a instanceof THREE.Camera||a instanceof THREE.Bone)&&-1===this.__objects.indexOf(a)){this.__objects.push(a);this.__objectsAdded.push(a);var b=this.__objectsRemoved.indexOf(a);-1!==b&&this.__objectsRemoved.splice(b,1)}for(b=0;b<a.children.length;b++)this.__addObject(a.children[b])};
 THREE.Scene.prototype.__addObject=function(a){if(a instanceof THREE.Light)-1===this.__lights.indexOf(a)&&this.__lights.push(a),a.target&&void 0===a.target.parent&&this.add(a.target);else if(!(a instanceof THREE.Camera||a instanceof THREE.Bone)&&-1===this.__objects.indexOf(a)){this.__objects.push(a);this.__objectsAdded.push(a);var b=this.__objectsRemoved.indexOf(a);-1!==b&&this.__objectsRemoved.splice(b,1)}for(b=0;b<a.children.length;b++)this.__addObject(a.children[b])};
-THREE.Scene.prototype.__removeObject=function(a){if(a instanceof THREE.Light){var b=this.__lights.indexOf(a);-1!==b&&this.__lights.splice(b,1)}else a instanceof THREE.Camera||(b=this.__objects.indexOf(a),-1!==b&&(this.__objects.splice(b,1),this.__objectsRemoved.push(a),b=this.__objectsAdded.indexOf(a),-1!==b&&this.__objectsAdded.splice(b,1)));for(b=0;b<a.children.length;b++)this.__removeObject(a.children[b])};THREE.Fog=function(a,b,c){this.name="";this.color=new THREE.Color(a);this.near=void 0!==b?b:1;this.far=void 0!==c?c:1E3};THREE.Fog.prototype.clone=function(){return new THREE.Fog(this.color.getHex(),this.near,this.far)};THREE.FogExp2=function(a,b){this.name="";this.color=new THREE.Color(a);this.density=void 0!==b?b:2.5E-4};THREE.FogExp2.prototype.clone=function(){return new THREE.FogExp2(this.color.getHex(),this.density)};THREE.CanvasRenderer=function(a){function b(a){B!==a&&(B=s.globalAlpha=a)}function c(a){w!==a&&(a===THREE.NormalBlending?s.globalCompositeOperation="source-over":a===THREE.AdditiveBlending?s.globalCompositeOperation="lighter":a===THREE.SubtractiveBlending&&(s.globalCompositeOperation="darker"),w=a)}function d(a){E!==a&&(E=s.lineWidth=a)}function e(a){Z!==a&&(Z=s.lineCap=a)}function f(a){A!==a&&(A=s.lineJoin=a)}function g(a){I!==a&&(I=s.strokeStyle=a)}function h(a){J!==a&&(J=s.fillStyle=a)}function i(a,
-b){if(U!==a||F!==b)s.setLineDash([a,b]),U=a,F=b}console.log("THREE.CanvasRenderer",THREE.REVISION);var k=THREE.Math.smoothstep,a=a||{},l=this,n,m,t,r=new THREE.Projector,p=void 0!==a.canvas?a.canvas:document.createElement("canvas"),q,y,v,z,s=p.getContext("2d"),C=new THREE.Color(0),H=0,B=1,w=0,I=null,J=null,E=null,Z=null,A=null,U=null,F=0,G,K,N,fa,ma=new THREE.RenderableVertex,eb=new THREE.RenderableVertex,M,T,ja,L,ca,ra,kb,$a,lb,db,La,Oa,ea=new THREE.Color,ha=new THREE.Color,V=new THREE.Color,$=new THREE.Color,
-Y=new THREE.Color,ia=new THREE.Color,sa=new THREE.Color,na=new THREE.Color,Pa={},Ba={},fb,jb,Sa,ob,Gb,Mb,wb,Nb,Ob,xb,Hb=new THREE.Box2,Qa=new THREE.Box2,Va=new THREE.Box2,wa=new THREE.Color,xa=new THREE.Color,yb=new THREE.Color,pb=new THREE.Vector3,j,mb,vb,Wa,Ga,zb,Ib=16;j=document.createElement("canvas");j.width=j.height=2;mb=j.getContext("2d");mb.fillStyle="rgba(0,0,0,1)";mb.fillRect(0,0,2,2);vb=mb.getImageData(0,0,2,2);Wa=vb.data;Ga=document.createElement("canvas");Ga.width=Ga.height=Ib;zb=Ga.getContext("2d");
-zb.translate(-Ib/2,-Ib/2);zb.scale(Ib,Ib);Ib--;void 0===s.setLineDash&&(s.setLineDash=void 0!==s.mozDash?function(a){s.mozDash=null!==a[0]?a:null}:function(){});this.domElement=p;this.devicePixelRatio=void 0!==a.devicePixelRatio?a.devicePixelRatio:void 0!==window.devicePixelRatio?window.devicePixelRatio:1;this.sortElements=this.sortObjects=this.autoClear=!0;this.info={render:{vertices:0,faces:0}};this.supportsVertexTextures=function(){};this.setFaceCulling=function(){};this.setSize=function(a,b){q=
-a*this.devicePixelRatio;y=b*this.devicePixelRatio;v=Math.floor(q/2);z=Math.floor(y/2);p.width=q;p.height=y;p.style.width=a+"px";p.style.height=b+"px";Hb.set(new THREE.Vector2(-v,-z),new THREE.Vector2(v,z));Qa.set(new THREE.Vector2(-v,-z),new THREE.Vector2(v,z));B=1;w=0;A=Z=E=J=I=null};this.setClearColor=function(a,b){C.copy(a);H=void 0!==b?b:1;Qa.set(new THREE.Vector2(-v,-z),new THREE.Vector2(v,z))};this.setClearColorHex=function(a,b){C.setHex(a);H=void 0!==b?b:1;Qa.set(new THREE.Vector2(-v,-z),new THREE.Vector2(v,
-z))};this.getMaxAnisotropy=function(){return 0};this.clear=function(){s.setTransform(1,0,0,-1,v,z);!1===Qa.empty()&&(Qa.intersect(Hb),Qa.expandByScalar(2),1>H&&s.clearRect(Qa.min.x|0,Qa.min.y|0,Qa.max.x-Qa.min.x|0,Qa.max.y-Qa.min.y|0),0<H&&(c(THREE.NormalBlending),b(1),h("rgba("+Math.floor(255*C.r)+","+Math.floor(255*C.g)+","+Math.floor(255*C.b)+","+H+")"),s.fillRect(Qa.min.x|0,Qa.min.y|0,Qa.max.x-Qa.min.x|0,Qa.max.y-Qa.min.y|0)),Qa.makeEmpty())};this.render=function(a,p){function q(a,b,c){for(var d=
-0,e=t.length;d<e;d++){var f=t[d];na.copy(f.color);if(f instanceof THREE.DirectionalLight){var g=pb.getPositionFromMatrix(f.matrixWorld).normalize(),h=b.dot(g);0>=h||(h*=f.intensity,c.add(na.multiplyScalar(h)))}else f instanceof THREE.PointLight&&(g=pb.getPositionFromMatrix(f.matrixWorld),h=b.dot(pb.subVectors(g,a).normalize()),0>=h||(h*=0==f.distance?1:1-Math.min(a.distanceTo(g)/f.distance,1),0!=h&&(h*=f.intensity,c.add(na.multiplyScalar(h)))))}}function w(a,d,e,f,g,h,i,j){l.info.render.vertices+=
-3;l.info.render.faces++;b(j.opacity);c(j.blending);M=a.positionScreen.x;T=a.positionScreen.y;ja=d.positionScreen.x;L=d.positionScreen.y;ca=e.positionScreen.x;ra=e.positionScreen.y;y(M,T,ja,L,ca,ra);(j instanceof THREE.MeshLambertMaterial||j instanceof THREE.MeshPhongMaterial)&&null===j.map?(ia.copy(j.color),sa.copy(j.emissive),j.vertexColors===THREE.FaceColors&&ia.multiply(i.color),!1===j.wireframe&&j.shading==THREE.SmoothShading&&3==i.vertexNormalsLength?(ha.copy(wa),V.copy(wa),$.copy(wa),q(i.v1.positionWorld,
-i.vertexNormalsModel[0],ha),q(i.v2.positionWorld,i.vertexNormalsModel[1],V),q(i.v3.positionWorld,i.vertexNormalsModel[2],$),ha.multiply(ia).add(sa),V.multiply(ia).add(sa),$.multiply(ia).add(sa),Y.addColors(V,$).multiplyScalar(0.5),Sa=Dc(ha,V,$,Y),ab(M,T,ja,L,ca,ra,0,0,1,0,0,1,Sa)):(ea.copy(wa),q(i.centroidModel,i.normalModel,ea),ea.multiply(ia).add(sa),!0===j.wireframe?B(ea,j.wireframeLinewidth,j.wireframeLinecap,j.wireframeLinejoin):C(ea))):j instanceof THREE.MeshBasicMaterial||j instanceof THREE.MeshLambertMaterial||
-j instanceof THREE.MeshPhongMaterial?null!==j.map?j.map.mapping instanceof THREE.UVMapping&&(ob=i.uvs[0],F(M,T,ja,L,ca,ra,ob[f].x,ob[f].y,ob[g].x,ob[g].y,ob[h].x,ob[h].y,j.map)):null!==j.envMap?j.envMap.mapping instanceof THREE.SphericalReflectionMapping&&(pb.copy(i.vertexNormalsModelView[f]),Gb=0.5*pb.x+0.5,Mb=0.5*pb.y+0.5,pb.copy(i.vertexNormalsModelView[g]),wb=0.5*pb.x+0.5,Nb=0.5*pb.y+0.5,pb.copy(i.vertexNormalsModelView[h]),Ob=0.5*pb.x+0.5,xb=0.5*pb.y+0.5,F(M,T,ja,L,ca,ra,Gb,Mb,wb,Nb,Ob,xb,j.envMap)):
-(ea.copy(j.color),j.vertexColors===THREE.FaceColors&&ea.multiply(i.color),!0===j.wireframe?B(ea,j.wireframeLinewidth,j.wireframeLinecap,j.wireframeLinejoin):C(ea)):j instanceof THREE.MeshDepthMaterial?(fb=p.near,jb=p.far,ha.r=ha.g=ha.b=1-k(a.positionScreen.z*a.positionScreen.w,fb,jb),V.r=V.g=V.b=1-k(d.positionScreen.z*d.positionScreen.w,fb,jb),$.r=$.g=$.b=1-k(e.positionScreen.z*e.positionScreen.w,fb,jb),Y.addColors(V,$).multiplyScalar(0.5),Sa=Dc(ha,V,$,Y),ab(M,T,ja,L,ca,ra,0,0,1,0,0,1,Sa)):j instanceof
-THREE.MeshNormalMaterial&&(j.shading==THREE.FlatShading?(a=i.normalModelView,ea.setRGB(a.x,a.y,a.z).multiplyScalar(0.5).addScalar(0.5),!0===j.wireframe?B(ea,j.wireframeLinewidth,j.wireframeLinecap,j.wireframeLinejoin):C(ea)):j.shading==THREE.SmoothShading&&(a=i.vertexNormalsModelView[f],ha.setRGB(a.x,a.y,a.z).multiplyScalar(0.5).addScalar(0.5),a=i.vertexNormalsModelView[g],V.setRGB(a.x,a.y,a.z).multiplyScalar(0.5).addScalar(0.5),a=i.vertexNormalsModelView[h],$.setRGB(a.x,a.y,a.z).multiplyScalar(0.5).addScalar(0.5),
-Y.addColors(V,$).multiplyScalar(0.5),Sa=Dc(ha,V,$,Y),ab(M,T,ja,L,ca,ra,0,0,1,0,0,1,Sa)))}function y(a,b,c,d,e,f){s.beginPath();s.moveTo(a,b);s.lineTo(c,d);s.lineTo(e,f);s.closePath()}function A(a,b,c,d,e,f,g,h){s.beginPath();s.moveTo(a,b);s.lineTo(c,d);s.lineTo(e,f);s.lineTo(g,h);s.closePath()}function B(a,b,c,h){d(b);e(c);f(h);g(a.getStyle());s.stroke();Va.expandByScalar(2*b)}function C(a){h(a.getStyle());s.fill()}function F(a,b,c,d,e,f,g,j,i,k,ab,l,m){if(!(m instanceof THREE.DataTexture||void 0===
-m.image||0==m.image.width)){if(!0===m.needsUpdate){var n=m.wrapS==THREE.RepeatWrapping,p=m.wrapT==THREE.RepeatWrapping;Pa[m.id]=s.createPattern(m.image,!0===n&&!0===p?"repeat":!0===n&&!1===p?"repeat-x":!1===n&&!0===p?"repeat-y":"no-repeat");m.needsUpdate=!1}void 0===Pa[m.id]?h("rgba(0,0,0,1)"):h(Pa[m.id]);var n=m.offset.x/m.repeat.x,p=m.offset.y/m.repeat.y,Jb=m.image.width*m.repeat.x,q=m.image.height*m.repeat.y,g=(g+n)*Jb,j=(1-j+p)*q,c=c-a,d=d-b,e=e-a,f=f-b,i=(i+n)*Jb-g,k=(1-k+p)*q-j,ab=(ab+n)*Jb-
-g,l=(1-l+p)*q-j,n=i*l-ab*k;0===n?(void 0===Ba[m.id]&&(b=document.createElement("canvas"),b.width=m.image.width,b.height=m.image.height,b=b.getContext("2d"),b.drawImage(m.image,0,0),Ba[m.id]=b.getImageData(0,0,m.image.width,m.image.height).data),b=Ba[m.id],g=4*(Math.floor(g)+Math.floor(j)*m.image.width),ea.setRGB(b[g]/255,b[g+1]/255,b[g+2]/255),C(ea)):(n=1/n,m=(l*c-k*e)*n,k=(l*d-k*f)*n,c=(i*e-ab*c)*n,d=(i*f-ab*d)*n,a=a-m*g-c*j,g=b-k*g-d*j,s.save(),s.transform(m,k,c,d,a,g),s.fill(),s.restore())}}function ab(a,
-b,c,d,e,f,g,h,j,i,k,ab,m){var l,n;l=m.width-1;n=m.height-1;g*=l;h*=n;c-=a;d-=b;e-=a;f-=b;j=j*l-g;i=i*n-h;k=k*l-g;ab=ab*n-h;n=1/(j*ab-k*i);l=(ab*c-i*e)*n;i=(ab*d-i*f)*n;c=(j*e-k*c)*n;d=(j*f-k*d)*n;a=a-l*g-c*h;b=b-i*g-d*h;s.save();s.transform(l,i,c,d,a,b);s.clip();s.drawImage(m,0,0);s.restore()}function Dc(a,b,c,d){Wa[0]=255*a.r|0;Wa[1]=255*a.g|0;Wa[2]=255*a.b|0;Wa[4]=255*b.r|0;Wa[5]=255*b.g|0;Wa[6]=255*b.b|0;Wa[8]=255*c.r|0;Wa[9]=255*c.g|0;Wa[10]=255*c.b|0;Wa[12]=255*d.r|0;Wa[13]=255*d.g|0;Wa[14]=
-255*d.b|0;mb.putImageData(vb,0,0);zb.drawImage(j,0,0);return Ga}function Jb(a,b){var c=b.x-a.x,d=b.y-a.y,e=c*c+d*d;0!==e&&(e=1/Math.sqrt(e),c*=e,d*=e,b.x+=c,b.y+=d,a.x-=c,a.y-=d)}if(!1===p instanceof THREE.Camera)console.error("THREE.CanvasRenderer.render: camera is not an instance of THREE.Camera.");else{!0===this.autoClear&&this.clear();s.setTransform(1,0,0,-1,v,z);l.info.render.vertices=0;l.info.render.faces=0;n=r.projectScene(a,p,this.sortObjects,this.sortElements);m=n.elements;t=n.lights;wa.setRGB(0,
-0,0);xa.setRGB(0,0,0);yb.setRGB(0,0,0);for(var wc=0,qd=t.length;wc<qd;wc++){var W=t[wc],ga=W.color;W instanceof THREE.AmbientLight?wa.add(ga):W instanceof THREE.DirectionalLight?xa.add(ga):W instanceof THREE.PointLight&&yb.add(ga)}wc=0;for(qd=m.length;wc<qd;wc++){var oa=m[wc],W=oa.material;if(!(void 0===W||!1===W.visible)){Va.makeEmpty();if(oa instanceof THREE.RenderableParticle){G=oa;G.x*=v;G.y*=z;var ga=G,gb=oa;b(W.opacity);c(W.blending);var Ab=void 0,E=void 0,Bb=void 0,H=void 0,I=oa=void 0,J=void 0;
-W instanceof THREE.ParticleBasicMaterial?null===W.map?(Bb=gb.object.scale.x,H=gb.object.scale.y,Bb*=gb.scale.x*v,H*=gb.scale.y*z,Va.min.set(ga.x-Bb,ga.y-H),Va.max.set(ga.x+Bb,ga.y+H),!1!==Hb.isIntersectionBox(Va)&&(h(W.color.getStyle()),s.save(),s.translate(ga.x,ga.y),s.rotate(-gb.rotation),s.scale(Bb,H),s.fillRect(-1,-1,2,2),s.restore())):(oa=W.map.image,I=oa.width>>1,J=oa.height>>1,Bb=gb.scale.x*v,H=gb.scale.y*z,Ab=Bb*I,E=H*J,Va.min.set(ga.x-Ab,ga.y-E),Va.max.set(ga.x+Ab,ga.y+E),!1!==Hb.isIntersectionBox(Va)&&
-(s.save(),s.translate(ga.x,ga.y),s.rotate(-gb.rotation),s.scale(Bb,-H),s.translate(-I,-J),s.drawImage(oa,0,0),s.restore())):W instanceof THREE.ParticleCanvasMaterial&&(Ab=gb.scale.x*v,E=gb.scale.y*z,Va.min.set(ga.x-Ab,ga.y-E),Va.max.set(ga.x+Ab,ga.y+E),!1!==Hb.isIntersectionBox(Va)&&(g(W.color.getStyle()),h(W.color.getStyle()),s.save(),s.translate(ga.x,ga.y),s.rotate(-gb.rotation),s.scale(Ab,E),W.program(s),s.restore()))}else if(oa instanceof THREE.RenderableLine)G=oa.v1,K=oa.v2,G.positionScreen.x*=
-v,G.positionScreen.y*=z,K.positionScreen.x*=v,K.positionScreen.y*=z,Va.setFromPoints([G.positionScreen,K.positionScreen]),!0===Hb.isIntersectionBox(Va)&&(ga=G,gb=K,b(W.opacity),c(W.blending),s.beginPath(),s.moveTo(ga.positionScreen.x,ga.positionScreen.y),s.lineTo(gb.positionScreen.x,gb.positionScreen.y),W instanceof THREE.LineBasicMaterial?(d(W.linewidth),e(W.linecap),f(W.linejoin),g(W.color.getStyle()),s.stroke(),Va.expandByScalar(2*W.linewidth)):W instanceof THREE.LineDashedMaterial&&(d(W.linewidth),
-e(W.linecap),f(W.linejoin),g(W.color.getStyle()),i(W.dashSize,W.gapSize),s.stroke(),Va.expandByScalar(2*W.linewidth),i(null,null)));else if(oa instanceof THREE.RenderableFace3){G=oa.v1;K=oa.v2;N=oa.v3;if(-1>G.positionScreen.z||1<G.positionScreen.z)continue;if(-1>K.positionScreen.z||1<K.positionScreen.z)continue;if(-1>N.positionScreen.z||1<N.positionScreen.z)continue;G.positionScreen.x*=v;G.positionScreen.y*=z;K.positionScreen.x*=v;K.positionScreen.y*=z;N.positionScreen.x*=v;N.positionScreen.y*=z;
-!0===W.overdraw&&(Jb(G.positionScreen,K.positionScreen),Jb(K.positionScreen,N.positionScreen),Jb(N.positionScreen,G.positionScreen));Va.setFromPoints([G.positionScreen,K.positionScreen,N.positionScreen]);w(G,K,N,0,1,2,oa,W)}else if(oa instanceof THREE.RenderableFace4){G=oa.v1;K=oa.v2;N=oa.v3;fa=oa.v4;if(-1>G.positionScreen.z||1<G.positionScreen.z)continue;if(-1>K.positionScreen.z||1<K.positionScreen.z)continue;if(-1>N.positionScreen.z||1<N.positionScreen.z)continue;if(-1>fa.positionScreen.z||1<fa.positionScreen.z)continue;
-G.positionScreen.x*=v;G.positionScreen.y*=z;K.positionScreen.x*=v;K.positionScreen.y*=z;N.positionScreen.x*=v;N.positionScreen.y*=z;fa.positionScreen.x*=v;fa.positionScreen.y*=z;ma.positionScreen.copy(K.positionScreen);eb.positionScreen.copy(fa.positionScreen);!0===W.overdraw&&(Jb(G.positionScreen,K.positionScreen),Jb(K.positionScreen,fa.positionScreen),Jb(fa.positionScreen,G.positionScreen),Jb(N.positionScreen,ma.positionScreen),Jb(N.positionScreen,eb.positionScreen));Va.setFromPoints([G.positionScreen,
-K.positionScreen,N.positionScreen,fa.positionScreen]);ga=G;gb=K;Ab=N;E=fa;Bb=ma;H=eb;l.info.render.vertices+=4;l.info.render.faces++;b(W.opacity);c(W.blending);void 0!==W.map&&null!==W.map||void 0!==W.envMap&&null!==W.envMap?(w(ga,gb,E,0,1,3,oa,W),w(Bb,Ab,H,1,2,3,oa,W)):(M=ga.positionScreen.x,T=ga.positionScreen.y,ja=gb.positionScreen.x,L=gb.positionScreen.y,ca=Ab.positionScreen.x,ra=Ab.positionScreen.y,kb=E.positionScreen.x,$a=E.positionScreen.y,lb=Bb.positionScreen.x,db=Bb.positionScreen.y,La=H.positionScreen.x,
-Oa=H.positionScreen.y,W instanceof THREE.MeshLambertMaterial||W instanceof THREE.MeshPhongMaterial?(ia.copy(W.color),sa.copy(W.emissive),W.vertexColors===THREE.FaceColors&&ia.multiply(oa.color),!1===W.wireframe&&W.shading==THREE.SmoothShading&&4==oa.vertexNormalsLength?(ha.copy(wa),V.copy(wa),$.copy(wa),Y.copy(wa),q(oa.v1.positionWorld,oa.vertexNormalsModel[0],ha),q(oa.v2.positionWorld,oa.vertexNormalsModel[1],V),q(oa.v4.positionWorld,oa.vertexNormalsModel[3],$),q(oa.v3.positionWorld,oa.vertexNormalsModel[2],
-Y),ha.multiply(ia).add(sa),V.multiply(ia).add(sa),$.multiply(ia).add(sa),Y.multiply(ia).add(sa),Sa=Dc(ha,V,$,Y),y(M,T,ja,L,kb,$a),ab(M,T,ja,L,kb,$a,0,0,1,0,0,1,Sa),y(lb,db,ca,ra,La,Oa),ab(lb,db,ca,ra,La,Oa,1,0,1,1,0,1,Sa)):(ea.copy(wa),q(oa.centroidModel,oa.normalModel,ea),ea.multiply(ia).add(sa),A(M,T,ja,L,ca,ra,kb,$a),!0===W.wireframe?B(ea,W.wireframeLinewidth,W.wireframeLinecap,W.wireframeLinejoin):C(ea))):W instanceof THREE.MeshBasicMaterial?(ea.copy(W.color),W.vertexColors===THREE.FaceColors&&
-ea.multiply(oa.color),A(M,T,ja,L,ca,ra,kb,$a),!0===W.wireframe?B(ea,W.wireframeLinewidth,W.wireframeLinecap,W.wireframeLinejoin):C(ea)):W instanceof THREE.MeshNormalMaterial?(ga=void 0,W.shading==THREE.FlatShading?(ga=oa.normalModelView,ea.setRGB(ga.x,ga.y,ga.z).multiplyScalar(0.5).addScalar(0.5),A(M,T,ja,L,ca,ra,kb,$a),!0===W.wireframe?B(ea,W.wireframeLinewidth,W.wireframeLinecap,W.wireframeLinejoin):C(ea)):W.shading==THREE.SmoothShading&&(ga=oa.vertexNormalsModelView[0],ha.setRGB(ga.x,ga.y,ga.z).multiplyScalar(0.5).addScalar(0.5),
-ga=oa.vertexNormalsModelView[1],V.setRGB(ga.x,ga.y,ga.z).multiplyScalar(0.5).addScalar(0.5),ga=oa.vertexNormalsModelView[3],$.setRGB(ga.x,ga.y,ga.z).multiplyScalar(0.5).addScalar(0.5),ga=oa.vertexNormalsModelView[2],Y.setRGB(ga.x,ga.y,ga.z).multiplyScalar(0.5).addScalar(0.5),Sa=Dc(ha,V,$,Y),y(M,T,ja,L,kb,$a),ab(M,T,ja,L,kb,$a,0,0,1,0,0,1,Sa),y(lb,db,ca,ra,La,Oa),ab(lb,db,ca,ra,La,Oa,1,0,1,1,0,1,Sa))):W instanceof THREE.MeshDepthMaterial&&(fb=p.near,jb=p.far,ha.r=ha.g=ha.b=1-k(ga.positionScreen.z*
-ga.positionScreen.w,fb,jb),V.r=V.g=V.b=1-k(gb.positionScreen.z*gb.positionScreen.w,fb,jb),$.r=$.g=$.b=1-k(E.positionScreen.z*E.positionScreen.w,fb,jb),Y.r=Y.g=Y.b=1-k(Ab.positionScreen.z*Ab.positionScreen.w,fb,jb),Sa=Dc(ha,V,$,Y),y(M,T,ja,L,kb,$a),ab(M,T,ja,L,kb,$a,0,0,1,0,0,1,Sa),y(lb,db,ca,ra,La,Oa),ab(lb,db,ca,ra,La,Oa,1,0,1,1,0,1,Sa)))}Qa.union(Va)}}s.setTransform(1,0,0,1,0,0)}}};THREE.ShaderChunk={fog_pars_fragment:"#ifdef USE_FOG\nuniform vec3 fogColor;\n#ifdef FOG_EXP2\nuniform float fogDensity;\n#else\nuniform float fogNear;\nuniform float fogFar;\n#endif\n#endif",fog_fragment:"#ifdef USE_FOG\nfloat depth = gl_FragCoord.z / gl_FragCoord.w;\n#ifdef FOG_EXP2\nconst float LOG2 = 1.442695;\nfloat fogFactor = exp2( - fogDensity * fogDensity * depth * depth * LOG2 );\nfogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 );\n#else\nfloat fogFactor = smoothstep( fogNear, fogFar, depth );\n#endif\ngl_FragColor = mix( gl_FragColor, vec4( fogColor, gl_FragColor.w ), fogFactor );\n#endif",
+THREE.Scene.prototype.__removeObject=function(a){if(a instanceof THREE.Light){var b=this.__lights.indexOf(a);-1!==b&&this.__lights.splice(b,1)}else a instanceof THREE.Camera||(b=this.__objects.indexOf(a),-1!==b&&(this.__objects.splice(b,1),this.__objectsRemoved.push(a),b=this.__objectsAdded.indexOf(a),-1!==b&&this.__objectsAdded.splice(b,1)));for(b=0;b<a.children.length;b++)this.__removeObject(a.children[b])};THREE.Fog=function(a,b,c){this.name="";this.color=new THREE.Color(a);this.near=void 0!==b?b:1;this.far=void 0!==c?c:1E3};THREE.Fog.prototype.clone=function(){return new THREE.Fog(this.color.getHex(),this.near,this.far)};THREE.FogExp2=function(a,b){this.name="";this.color=new THREE.Color(a);this.density=void 0!==b?b:2.5E-4};THREE.FogExp2.prototype.clone=function(){return new THREE.FogExp2(this.color.getHex(),this.density)};THREE.CanvasRenderer=function(a){function b(a){C!==a&&(C=y.globalAlpha=a)}function c(a){k!==a&&(a===THREE.NormalBlending?y.globalCompositeOperation="source-over":a===THREE.AdditiveBlending?y.globalCompositeOperation="lighter":a===THREE.SubtractiveBlending&&(y.globalCompositeOperation="darker"),k=a)}function d(a){B!==a&&(B=y.lineWidth=a)}function e(a){P!==a&&(P=y.lineCap=a)}function f(a){A!==a&&(A=y.lineJoin=a)}function g(a){I!==a&&(I=y.strokeStyle=a)}function h(a){J!==a&&(J=y.fillStyle=a)}function i(a,
+b){if(G!==a||E!==b)y.setLineDash([a,b]),G=a,E=b}console.log("THREE.CanvasRenderer",THREE.REVISION);var j=THREE.Math.smoothstep,a=a||{},l=this,n,m,r,u=new THREE.Projector,p=void 0!==a.canvas?a.canvas:document.createElement("canvas"),q,w,v,z,y=p.getContext("2d"),t=new THREE.Color(0),D=0,C=1,k=0,I=null,J=null,B=null,P=null,A=null,G=null,E=0,F,s,H,O,K=new THREE.RenderableVertex,x=new THREE.RenderableVertex,N,R,$,Y,W,M,la,na,qa,X,S,Z,T=new THREE.Color,aa=new THREE.Color,L=new THREE.Color,U=new THREE.Color,
+ba=new THREE.Color,ca=new THREE.Color,da=new THREE.Color,pa=new THREE.Color,Aa={},ea={},ra,wa,ka,ya,Ga,Ja,Ka,La,Ma,Na,Fa=new THREE.Box2,ia=new THREE.Box2,fa=new THREE.Box2,oa=new THREE.Color,Da=new THREE.Color,Ba=new THREE.Color,ga=new THREE.Vector3,xa,Ca,Ea,ma,za,ha,Q=16;xa=document.createElement("canvas");xa.width=xa.height=2;Ca=xa.getContext("2d");Ca.fillStyle="rgba(0,0,0,1)";Ca.fillRect(0,0,2,2);Ea=Ca.getImageData(0,0,2,2);ma=Ea.data;za=document.createElement("canvas");za.width=za.height=Q;ha=
+za.getContext("2d");ha.translate(-Q/2,-Q/2);ha.scale(Q,Q);Q--;void 0===y.setLineDash&&(y.setLineDash=void 0!==y.mozDash?function(a){y.mozDash=null!==a[0]?a:null}:function(){});this.domElement=p;this.devicePixelRatio=void 0!==a.devicePixelRatio?a.devicePixelRatio:void 0!==window.devicePixelRatio?window.devicePixelRatio:1;this.sortElements=this.sortObjects=this.autoClear=!0;this.info={render:{vertices:0,faces:0}};this.supportsVertexTextures=function(){};this.setFaceCulling=function(){};this.setSize=
+function(a,b){q=a*this.devicePixelRatio;w=b*this.devicePixelRatio;v=Math.floor(q/2);z=Math.floor(w/2);p.width=q;p.height=w;p.style.width=a+"px";p.style.height=b+"px";Fa.set(new THREE.Vector2(-v,-z),new THREE.Vector2(v,z));ia.set(new THREE.Vector2(-v,-z),new THREE.Vector2(v,z));C=1;k=0;A=P=B=J=I=null};this.setClearColor=function(a,b){t.copy(a);D=void 0!==b?b:1;ia.set(new THREE.Vector2(-v,-z),new THREE.Vector2(v,z))};this.setClearColorHex=function(a,b){t.setHex(a);D=void 0!==b?b:1;ia.set(new THREE.Vector2(-v,
+-z),new THREE.Vector2(v,z))};this.getMaxAnisotropy=function(){return 0};this.clear=function(){y.setTransform(1,0,0,-1,v,z);!1===ia.empty()&&(ia.intersect(Fa),ia.expandByScalar(2),1>D&&y.clearRect(ia.min.x|0,ia.min.y|0,ia.max.x-ia.min.x|0,ia.max.y-ia.min.y|0),0<D&&(c(THREE.NormalBlending),b(1),h("rgba("+Math.floor(255*t.r)+","+Math.floor(255*t.g)+","+Math.floor(255*t.b)+","+D+")"),y.fillRect(ia.min.x|0,ia.min.y|0,ia.max.x-ia.min.x|0,ia.max.y-ia.min.y|0)),ia.makeEmpty())};this.render=function(a,k){function p(a,
+b,c){for(var d=0,e=r.length;d<e;d++){var f=r[d];pa.copy(f.color);if(f instanceof THREE.DirectionalLight){var g=ga.getPositionFromMatrix(f.matrixWorld).normalize(),i=b.dot(g);0>=i||(i*=f.intensity,c.add(pa.multiplyScalar(i)))}else f instanceof THREE.PointLight&&(g=ga.getPositionFromMatrix(f.matrixWorld),i=b.dot(ga.subVectors(g,a).normalize()),0>=i||(i*=0==f.distance?1:1-Math.min(a.distanceTo(g)/f.distance,1),0!=i&&(i*=f.intensity,c.add(pa.multiplyScalar(i)))))}}function q(a,d,e,f,g,i,h,m){l.info.render.vertices+=
+3;l.info.render.faces++;b(m.opacity);c(m.blending);N=a.positionScreen.x;R=a.positionScreen.y;$=d.positionScreen.x;Y=d.positionScreen.y;W=e.positionScreen.x;M=e.positionScreen.y;t(N,R,$,Y,W,M);(m instanceof THREE.MeshLambertMaterial||m instanceof THREE.MeshPhongMaterial)&&null===m.map?(ca.copy(m.color),da.copy(m.emissive),m.vertexColors===THREE.FaceColors&&ca.multiply(h.color),!1===m.wireframe&&m.shading==THREE.SmoothShading&&3==h.vertexNormalsLength?(aa.copy(oa),L.copy(oa),U.copy(oa),p(h.v1.positionWorld,
+h.vertexNormalsModel[0],aa),p(h.v2.positionWorld,h.vertexNormalsModel[1],L),p(h.v3.positionWorld,h.vertexNormalsModel[2],U),aa.multiply(ca).add(da),L.multiply(ca).add(da),U.multiply(ca).add(da),ba.addColors(L,U).multiplyScalar(0.5),ka=E(aa,L,U,ba),D(N,R,$,Y,W,M,0,0,1,0,0,1,ka)):(T.copy(oa),p(h.centroidModel,h.normalModel,T),T.multiply(ca).add(da),!0===m.wireframe?A(T,m.wireframeLinewidth,m.wireframeLinecap,m.wireframeLinejoin):B(T))):m instanceof THREE.MeshBasicMaterial||m instanceof THREE.MeshLambertMaterial||
+m instanceof THREE.MeshPhongMaterial?null!==m.map?m.map.mapping instanceof THREE.UVMapping&&(ya=h.uvs[0],C(N,R,$,Y,W,M,ya[f].x,ya[f].y,ya[g].x,ya[g].y,ya[i].x,ya[i].y,m.map)):null!==m.envMap?m.envMap.mapping instanceof THREE.SphericalReflectionMapping&&(ga.copy(h.vertexNormalsModelView[f]),Ga=0.5*ga.x+0.5,Ja=0.5*ga.y+0.5,ga.copy(h.vertexNormalsModelView[g]),Ka=0.5*ga.x+0.5,La=0.5*ga.y+0.5,ga.copy(h.vertexNormalsModelView[i]),Ma=0.5*ga.x+0.5,Na=0.5*ga.y+0.5,C(N,R,$,Y,W,M,Ga,Ja,Ka,La,Ma,Na,m.envMap)):
+(T.copy(m.color),m.vertexColors===THREE.FaceColors&&T.multiply(h.color),!0===m.wireframe?A(T,m.wireframeLinewidth,m.wireframeLinecap,m.wireframeLinejoin):B(T)):m instanceof THREE.MeshDepthMaterial?(ra=k.near,wa=k.far,aa.r=aa.g=aa.b=1-j(a.positionScreen.z*a.positionScreen.w,ra,wa),L.r=L.g=L.b=1-j(d.positionScreen.z*d.positionScreen.w,ra,wa),U.r=U.g=U.b=1-j(e.positionScreen.z*e.positionScreen.w,ra,wa),ba.addColors(L,U).multiplyScalar(0.5),ka=E(aa,L,U,ba),D(N,R,$,Y,W,M,0,0,1,0,0,1,ka)):m instanceof THREE.MeshNormalMaterial&&
+(m.shading==THREE.FlatShading?(a=h.normalModelView,T.setRGB(a.x,a.y,a.z).multiplyScalar(0.5).addScalar(0.5),!0===m.wireframe?A(T,m.wireframeLinewidth,m.wireframeLinecap,m.wireframeLinejoin):B(T)):m.shading==THREE.SmoothShading&&(a=h.vertexNormalsModelView[f],aa.setRGB(a.x,a.y,a.z).multiplyScalar(0.5).addScalar(0.5),a=h.vertexNormalsModelView[g],L.setRGB(a.x,a.y,a.z).multiplyScalar(0.5).addScalar(0.5),a=h.vertexNormalsModelView[i],U.setRGB(a.x,a.y,a.z).multiplyScalar(0.5).addScalar(0.5),ba.addColors(L,
+U).multiplyScalar(0.5),ka=E(aa,L,U,ba),D(N,R,$,Y,W,M,0,0,1,0,0,1,ka)))}function t(a,b,c,d,e,f){y.beginPath();y.moveTo(a,b);y.lineTo(c,d);y.lineTo(e,f);y.closePath()}function w(a,b,c,d,e,f,g,i){y.beginPath();y.moveTo(a,b);y.lineTo(c,d);y.lineTo(e,f);y.lineTo(g,i);y.closePath()}function A(a,b,c,i){d(b);e(c);f(i);g(a.getStyle());y.stroke();fa.expandByScalar(2*b)}function B(a){h(a.getStyle());y.fill()}function C(a,b,c,d,e,f,g,i,j,k,l,m,L){if(!(L instanceof THREE.DataTexture||void 0===L.image||0==L.image.width)){if(!0===
+L.needsUpdate){var n=L.wrapS==THREE.RepeatWrapping,p=L.wrapT==THREE.RepeatWrapping;Aa[L.id]=y.createPattern(L.image,!0===n&&!0===p?"repeat":!0===n&&!1===p?"repeat-x":!1===n&&!0===p?"repeat-y":"no-repeat");L.needsUpdate=!1}void 0===Aa[L.id]?h("rgba(0,0,0,1)"):h(Aa[L.id]);var n=L.offset.x/L.repeat.x,p=L.offset.y/L.repeat.y,r=L.image.width*L.repeat.x,q=L.image.height*L.repeat.y,g=(g+n)*r,i=(1-i+p)*q,c=c-a,d=d-b,e=e-a,f=f-b,j=(j+n)*r-g,k=(1-k+p)*q-i,l=(l+n)*r-g,m=(1-m+p)*q-i,n=j*m-l*k;0===n?(void 0===
+ea[L.id]&&(b=document.createElement("canvas"),b.width=L.image.width,b.height=L.image.height,b=b.getContext("2d"),b.drawImage(L.image,0,0),ea[L.id]=b.getImageData(0,0,L.image.width,L.image.height).data),b=ea[L.id],g=4*(Math.floor(g)+Math.floor(i)*L.image.width),T.setRGB(b[g]/255,b[g+1]/255,b[g+2]/255),B(T)):(n=1/n,L=(m*c-k*e)*n,k=(m*d-k*f)*n,c=(j*e-l*c)*n,d=(j*f-l*d)*n,a=a-L*g-c*i,g=b-k*g-d*i,y.save(),y.transform(L,k,c,d,a,g),y.fill(),y.restore())}}function D(a,b,c,d,e,f,g,i,h,j,k,l,m){var L,n;L=m.width-
+1;n=m.height-1;g*=L;i*=n;c-=a;d-=b;e-=a;f-=b;h=h*L-g;j=j*n-i;k=k*L-g;l=l*n-i;n=1/(h*l-k*j);L=(l*c-j*e)*n;j=(l*d-j*f)*n;c=(h*e-k*c)*n;d=(h*f-k*d)*n;a=a-L*g-c*i;b=b-j*g-d*i;y.save();y.transform(L,j,c,d,a,b);y.clip();y.drawImage(m,0,0);y.restore()}function E(a,b,c,d){ma[0]=255*a.r|0;ma[1]=255*a.g|0;ma[2]=255*a.b|0;ma[4]=255*b.r|0;ma[5]=255*b.g|0;ma[6]=255*b.b|0;ma[8]=255*c.r|0;ma[9]=255*c.g|0;ma[10]=255*c.b|0;ma[12]=255*d.r|0;ma[13]=255*d.g|0;ma[14]=255*d.b|0;Ca.putImageData(Ea,0,0);ha.drawImage(xa,
+0,0);return za}function I(a,b){var c=b.x-a.x,d=b.y-a.y,e=c*c+d*d;0!==e&&(e=1/Math.sqrt(e),c*=e,d*=e,b.x+=c,b.y+=d,a.x-=c,a.y-=d)}if(!1===k instanceof THREE.Camera)console.error("THREE.CanvasRenderer.render: camera is not an instance of THREE.Camera.");else{!0===this.autoClear&&this.clear();y.setTransform(1,0,0,-1,v,z);l.info.render.vertices=0;l.info.render.faces=0;n=u.projectScene(a,k,this.sortObjects,this.sortElements);m=n.elements;r=n.lights;oa.setRGB(0,0,0);Da.setRGB(0,0,0);Ba.setRGB(0,0,0);for(var J=
+0,P=r.length;J<P;J++){var G=r[J],V=G.color;G instanceof THREE.AmbientLight?oa.add(V):G instanceof THREE.DirectionalLight?Da.add(V):G instanceof THREE.PointLight&&Ba.add(V)}J=0;for(P=m.length;J<P;J++){var Q=m[J],G=Q.material;if(!(void 0===G||!1===G.visible)){fa.makeEmpty();if(Q instanceof THREE.RenderableParticle){F=Q;F.x*=v;F.y*=z;var V=F,ja=Q;b(G.opacity);c(G.blending);var sa=void 0,ta=void 0,ua=void 0,va=void 0,Ha=Q=void 0,Ia=void 0;G instanceof THREE.ParticleBasicMaterial?null===G.map?(ua=ja.object.scale.x,
+va=ja.object.scale.y,ua*=ja.scale.x*v,va*=ja.scale.y*z,fa.min.set(V.x-ua,V.y-va),fa.max.set(V.x+ua,V.y+va),!1!==Fa.isIntersectionBox(fa)&&(h(G.color.getStyle()),y.save(),y.translate(V.x,V.y),y.rotate(-ja.rotation),y.scale(ua,va),y.fillRect(-1,-1,2,2),y.restore())):(Q=G.map.image,Ha=Q.width>>1,Ia=Q.height>>1,ua=ja.scale.x*v,va=ja.scale.y*z,sa=ua*Ha,ta=va*Ia,fa.min.set(V.x-sa,V.y-ta),fa.max.set(V.x+sa,V.y+ta),!1!==Fa.isIntersectionBox(fa)&&(y.save(),y.translate(V.x,V.y),y.rotate(-ja.rotation),y.scale(ua,
+-va),y.translate(-Ha,-Ia),y.drawImage(Q,0,0),y.restore())):G instanceof THREE.ParticleCanvasMaterial&&(sa=ja.scale.x*v,ta=ja.scale.y*z,fa.min.set(V.x-sa,V.y-ta),fa.max.set(V.x+sa,V.y+ta),!1!==Fa.isIntersectionBox(fa)&&(g(G.color.getStyle()),h(G.color.getStyle()),y.save(),y.translate(V.x,V.y),y.rotate(-ja.rotation),y.scale(sa,ta),G.program(y),y.restore()))}else if(Q instanceof THREE.RenderableLine)F=Q.v1,s=Q.v2,F.positionScreen.x*=v,F.positionScreen.y*=z,s.positionScreen.x*=v,s.positionScreen.y*=z,
+fa.setFromPoints([F.positionScreen,s.positionScreen]),!0===Fa.isIntersectionBox(fa)&&(V=F,ja=s,b(G.opacity),c(G.blending),y.beginPath(),y.moveTo(V.positionScreen.x,V.positionScreen.y),y.lineTo(ja.positionScreen.x,ja.positionScreen.y),G instanceof THREE.LineBasicMaterial?(d(G.linewidth),e(G.linecap),f(G.linejoin),g(G.color.getStyle()),y.stroke(),fa.expandByScalar(2*G.linewidth)):G instanceof THREE.LineDashedMaterial&&(d(G.linewidth),e(G.linecap),f(G.linejoin),g(G.color.getStyle()),i(G.dashSize,G.gapSize),
+y.stroke(),fa.expandByScalar(2*G.linewidth),i(null,null)));else if(Q instanceof THREE.RenderableFace3){F=Q.v1;s=Q.v2;H=Q.v3;if(-1>F.positionScreen.z||1<F.positionScreen.z)continue;if(-1>s.positionScreen.z||1<s.positionScreen.z)continue;if(-1>H.positionScreen.z||1<H.positionScreen.z)continue;F.positionScreen.x*=v;F.positionScreen.y*=z;s.positionScreen.x*=v;s.positionScreen.y*=z;H.positionScreen.x*=v;H.positionScreen.y*=z;!0===G.overdraw&&(I(F.positionScreen,s.positionScreen),I(s.positionScreen,H.positionScreen),
+I(H.positionScreen,F.positionScreen));fa.setFromPoints([F.positionScreen,s.positionScreen,H.positionScreen]);q(F,s,H,0,1,2,Q,G)}else if(Q instanceof THREE.RenderableFace4){F=Q.v1;s=Q.v2;H=Q.v3;O=Q.v4;if(-1>F.positionScreen.z||1<F.positionScreen.z)continue;if(-1>s.positionScreen.z||1<s.positionScreen.z)continue;if(-1>H.positionScreen.z||1<H.positionScreen.z)continue;if(-1>O.positionScreen.z||1<O.positionScreen.z)continue;F.positionScreen.x*=v;F.positionScreen.y*=z;s.positionScreen.x*=v;s.positionScreen.y*=
+z;H.positionScreen.x*=v;H.positionScreen.y*=z;O.positionScreen.x*=v;O.positionScreen.y*=z;K.positionScreen.copy(s.positionScreen);x.positionScreen.copy(O.positionScreen);!0===G.overdraw&&(I(F.positionScreen,s.positionScreen),I(s.positionScreen,O.positionScreen),I(O.positionScreen,F.positionScreen),I(H.positionScreen,K.positionScreen),I(H.positionScreen,x.positionScreen));fa.setFromPoints([F.positionScreen,s.positionScreen,H.positionScreen,O.positionScreen]);V=F;ja=s;sa=H;ta=O;ua=K;va=x;l.info.render.vertices+=
+4;l.info.render.faces++;b(G.opacity);c(G.blending);void 0!==G.map&&null!==G.map||void 0!==G.envMap&&null!==G.envMap?(q(V,ja,ta,0,1,3,Q,G),q(ua,sa,va,1,2,3,Q,G)):(N=V.positionScreen.x,R=V.positionScreen.y,$=ja.positionScreen.x,Y=ja.positionScreen.y,W=sa.positionScreen.x,M=sa.positionScreen.y,la=ta.positionScreen.x,na=ta.positionScreen.y,qa=ua.positionScreen.x,X=ua.positionScreen.y,S=va.positionScreen.x,Z=va.positionScreen.y,G instanceof THREE.MeshLambertMaterial||G instanceof THREE.MeshPhongMaterial?
+(ca.copy(G.color),da.copy(G.emissive),G.vertexColors===THREE.FaceColors&&ca.multiply(Q.color),!1===G.wireframe&&G.shading==THREE.SmoothShading&&4==Q.vertexNormalsLength?(aa.copy(oa),L.copy(oa),U.copy(oa),ba.copy(oa),p(Q.v1.positionWorld,Q.vertexNormalsModel[0],aa),p(Q.v2.positionWorld,Q.vertexNormalsModel[1],L),p(Q.v4.positionWorld,Q.vertexNormalsModel[3],U),p(Q.v3.positionWorld,Q.vertexNormalsModel[2],ba),aa.multiply(ca).add(da),L.multiply(ca).add(da),U.multiply(ca).add(da),ba.multiply(ca).add(da),
+ka=E(aa,L,U,ba),t(N,R,$,Y,la,na),D(N,R,$,Y,la,na,0,0,1,0,0,1,ka),t(qa,X,W,M,S,Z),D(qa,X,W,M,S,Z,1,0,1,1,0,1,ka)):(T.copy(oa),p(Q.centroidModel,Q.normalModel,T),T.multiply(ca).add(da),w(N,R,$,Y,W,M,la,na),!0===G.wireframe?A(T,G.wireframeLinewidth,G.wireframeLinecap,G.wireframeLinejoin):B(T))):G instanceof THREE.MeshBasicMaterial?(T.copy(G.color),G.vertexColors===THREE.FaceColors&&T.multiply(Q.color),w(N,R,$,Y,W,M,la,na),!0===G.wireframe?A(T,G.wireframeLinewidth,G.wireframeLinecap,G.wireframeLinejoin):
+B(T)):G instanceof THREE.MeshNormalMaterial?(V=void 0,G.shading==THREE.FlatShading?(V=Q.normalModelView,T.setRGB(V.x,V.y,V.z).multiplyScalar(0.5).addScalar(0.5),w(N,R,$,Y,W,M,la,na),!0===G.wireframe?A(T,G.wireframeLinewidth,G.wireframeLinecap,G.wireframeLinejoin):B(T)):G.shading==THREE.SmoothShading&&(V=Q.vertexNormalsModelView[0],aa.setRGB(V.x,V.y,V.z).multiplyScalar(0.5).addScalar(0.5),V=Q.vertexNormalsModelView[1],L.setRGB(V.x,V.y,V.z).multiplyScalar(0.5).addScalar(0.5),V=Q.vertexNormalsModelView[3],
+U.setRGB(V.x,V.y,V.z).multiplyScalar(0.5).addScalar(0.5),V=Q.vertexNormalsModelView[2],ba.setRGB(V.x,V.y,V.z).multiplyScalar(0.5).addScalar(0.5),ka=E(aa,L,U,ba),t(N,R,$,Y,la,na),D(N,R,$,Y,la,na,0,0,1,0,0,1,ka),t(qa,X,W,M,S,Z),D(qa,X,W,M,S,Z,1,0,1,1,0,1,ka))):G instanceof THREE.MeshDepthMaterial&&(ra=k.near,wa=k.far,aa.r=aa.g=aa.b=1-j(V.positionScreen.z*V.positionScreen.w,ra,wa),L.r=L.g=L.b=1-j(ja.positionScreen.z*ja.positionScreen.w,ra,wa),U.r=U.g=U.b=1-j(ta.positionScreen.z*ta.positionScreen.w,ra,
+wa),ba.r=ba.g=ba.b=1-j(sa.positionScreen.z*sa.positionScreen.w,ra,wa),ka=E(aa,L,U,ba),t(N,R,$,Y,la,na),D(N,R,$,Y,la,na,0,0,1,0,0,1,ka),t(qa,X,W,M,S,Z),D(qa,X,W,M,S,Z,1,0,1,1,0,1,ka)))}ia.union(fa)}}y.setTransform(1,0,0,1,0,0)}}};THREE.ShaderChunk={fog_pars_fragment:"#ifdef USE_FOG\nuniform vec3 fogColor;\n#ifdef FOG_EXP2\nuniform float fogDensity;\n#else\nuniform float fogNear;\nuniform float fogFar;\n#endif\n#endif",fog_fragment:"#ifdef USE_FOG\nfloat depth = gl_FragCoord.z / gl_FragCoord.w;\n#ifdef FOG_EXP2\nconst float LOG2 = 1.442695;\nfloat fogFactor = exp2( - fogDensity * fogDensity * depth * depth * LOG2 );\nfogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 );\n#else\nfloat fogFactor = smoothstep( fogNear, fogFar, depth );\n#endif\ngl_FragColor = mix( gl_FragColor, vec4( fogColor, gl_FragColor.w ), fogFactor );\n#endif",
 envmap_pars_fragment:"#ifdef USE_ENVMAP\nuniform float reflectivity;\nuniform samplerCube envMap;\nuniform float flipEnvMap;\nuniform int combine;\n#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\nuniform bool useRefract;\nuniform float refractionRatio;\n#else\nvarying vec3 vReflect;\n#endif\n#endif",envmap_fragment:"#ifdef USE_ENVMAP\nvec3 reflectVec;\n#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\nvec3 cameraToVertex = normalize( vWorldPosition - cameraPosition );\nif ( useRefract ) {\nreflectVec = refract( cameraToVertex, normal, refractionRatio );\n} else { \nreflectVec = reflect( cameraToVertex, normal );\n}\n#else\nreflectVec = vReflect;\n#endif\n#ifdef DOUBLE_SIDED\nfloat flipNormal = ( -1.0 + 2.0 * float( gl_FrontFacing ) );\nvec4 cubeColor = textureCube( envMap, flipNormal * vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n#else\nvec4 cubeColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n#endif\n#ifdef GAMMA_INPUT\ncubeColor.xyz *= cubeColor.xyz;\n#endif\nif ( combine == 1 ) {\ngl_FragColor.xyz = mix( gl_FragColor.xyz, cubeColor.xyz, specularStrength * reflectivity );\n} else if ( combine == 2 ) {\ngl_FragColor.xyz += cubeColor.xyz * specularStrength * reflectivity;\n} else {\ngl_FragColor.xyz = mix( gl_FragColor.xyz, gl_FragColor.xyz * cubeColor.xyz, specularStrength * reflectivity );\n}\n#endif",
 envmap_pars_fragment:"#ifdef USE_ENVMAP\nuniform float reflectivity;\nuniform samplerCube envMap;\nuniform float flipEnvMap;\nuniform int combine;\n#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\nuniform bool useRefract;\nuniform float refractionRatio;\n#else\nvarying vec3 vReflect;\n#endif\n#endif",envmap_fragment:"#ifdef USE_ENVMAP\nvec3 reflectVec;\n#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\nvec3 cameraToVertex = normalize( vWorldPosition - cameraPosition );\nif ( useRefract ) {\nreflectVec = refract( cameraToVertex, normal, refractionRatio );\n} else { \nreflectVec = reflect( cameraToVertex, normal );\n}\n#else\nreflectVec = vReflect;\n#endif\n#ifdef DOUBLE_SIDED\nfloat flipNormal = ( -1.0 + 2.0 * float( gl_FrontFacing ) );\nvec4 cubeColor = textureCube( envMap, flipNormal * vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n#else\nvec4 cubeColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n#endif\n#ifdef GAMMA_INPUT\ncubeColor.xyz *= cubeColor.xyz;\n#endif\nif ( combine == 1 ) {\ngl_FragColor.xyz = mix( gl_FragColor.xyz, cubeColor.xyz, specularStrength * reflectivity );\n} else if ( combine == 2 ) {\ngl_FragColor.xyz += cubeColor.xyz * specularStrength * reflectivity;\n} else {\ngl_FragColor.xyz = mix( gl_FragColor.xyz, gl_FragColor.xyz * cubeColor.xyz, specularStrength * reflectivity );\n}\n#endif",
 envmap_pars_vertex:"#if defined( USE_ENVMAP ) && ! defined( USE_BUMPMAP ) && ! defined( USE_NORMALMAP )\nvarying vec3 vReflect;\nuniform float refractionRatio;\nuniform bool useRefract;\n#endif",worldpos_vertex:"#if defined( USE_ENVMAP ) || defined( PHONG ) || defined( LAMBERT ) || defined ( USE_SHADOWMAP )\n#ifdef USE_SKINNING\nvec4 worldPosition = modelMatrix * skinned;\n#endif\n#if defined( USE_MORPHTARGETS ) && ! defined( USE_SKINNING )\nvec4 worldPosition = modelMatrix * vec4( morphed, 1.0 );\n#endif\n#if ! defined( USE_MORPHTARGETS ) && ! defined( USE_SKINNING )\nvec4 worldPosition = modelMatrix * vec4( position, 1.0 );\n#endif\n#endif",
 envmap_pars_vertex:"#if defined( USE_ENVMAP ) && ! defined( USE_BUMPMAP ) && ! defined( USE_NORMALMAP )\nvarying vec3 vReflect;\nuniform float refractionRatio;\nuniform bool useRefract;\n#endif",worldpos_vertex:"#if defined( USE_ENVMAP ) || defined( PHONG ) || defined( LAMBERT ) || defined ( USE_SHADOWMAP )\n#ifdef USE_SKINNING\nvec4 worldPosition = modelMatrix * skinned;\n#endif\n#if defined( USE_MORPHTARGETS ) && ! defined( USE_SKINNING )\nvec4 worldPosition = modelMatrix * vec4( morphed, 1.0 );\n#endif\n#if ! defined( USE_MORPHTARGETS ) && ! defined( USE_SKINNING )\nvec4 worldPosition = modelMatrix * vec4( position, 1.0 );\n#endif\n#endif",
 envmap_vertex:"#if defined( USE_ENVMAP ) && ! defined( USE_BUMPMAP ) && ! defined( USE_NORMALMAP )\nvec3 worldNormal = mat3( modelMatrix[ 0 ].xyz, modelMatrix[ 1 ].xyz, modelMatrix[ 2 ].xyz ) * objectNormal;\nworldNormal = normalize( worldNormal );\nvec3 cameraToVertex = normalize( worldPosition.xyz - cameraPosition );\nif ( useRefract ) {\nvReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n} else {\nvReflect = reflect( cameraToVertex, worldNormal );\n}\n#endif",map_particle_pars_fragment:"#ifdef USE_MAP\nuniform sampler2D map;\n#endif",
 envmap_vertex:"#if defined( USE_ENVMAP ) && ! defined( USE_BUMPMAP ) && ! defined( USE_NORMALMAP )\nvec3 worldNormal = mat3( modelMatrix[ 0 ].xyz, modelMatrix[ 1 ].xyz, modelMatrix[ 2 ].xyz ) * objectNormal;\nworldNormal = normalize( worldNormal );\nvec3 cameraToVertex = normalize( worldPosition.xyz - cameraPosition );\nif ( useRefract ) {\nvReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n} else {\nvReflect = reflect( cameraToVertex, worldNormal );\n}\n#endif",map_particle_pars_fragment:"#ifdef USE_MAP\nuniform sampler2D map;\n#endif",
@@ -344,183 +341,186 @@ THREE.ShaderChunk.shadowmap_pars_fragment,THREE.ShaderChunk.fog_pars_fragment,"v
 THREE.ShaderChunk.shadowmap_fragment,THREE.ShaderChunk.linear_to_gamma_fragment,THREE.ShaderChunk.fog_fragment,"}"].join("\n"),vertexShader:["attribute vec4 tangent;\nuniform vec2 uOffset;\nuniform vec2 uRepeat;\nuniform bool enableDisplacement;\n#ifdef VERTEX_TEXTURES\nuniform sampler2D tDisplacement;\nuniform float uDisplacementScale;\nuniform float uDisplacementBias;\n#endif\nvarying vec3 vTangent;\nvarying vec3 vBinormal;\nvarying vec3 vNormal;\nvarying vec2 vUv;\nvarying vec3 vWorldPosition;\nvarying vec3 vViewPosition;",
 THREE.ShaderChunk.shadowmap_fragment,THREE.ShaderChunk.linear_to_gamma_fragment,THREE.ShaderChunk.fog_fragment,"}"].join("\n"),vertexShader:["attribute vec4 tangent;\nuniform vec2 uOffset;\nuniform vec2 uRepeat;\nuniform bool enableDisplacement;\n#ifdef VERTEX_TEXTURES\nuniform sampler2D tDisplacement;\nuniform float uDisplacementScale;\nuniform float uDisplacementBias;\n#endif\nvarying vec3 vTangent;\nvarying vec3 vBinormal;\nvarying vec3 vNormal;\nvarying vec2 vUv;\nvarying vec3 vWorldPosition;\nvarying vec3 vViewPosition;",
 THREE.ShaderChunk.skinning_pars_vertex,THREE.ShaderChunk.shadowmap_pars_vertex,"void main() {",THREE.ShaderChunk.skinbase_vertex,THREE.ShaderChunk.skinnormal_vertex,"#ifdef USE_SKINNING\nvNormal = normalize( normalMatrix * skinnedNormal.xyz );\nvec4 skinnedTangent = skinMatrix * vec4( tangent.xyz, 0.0 );\nvTangent = normalize( normalMatrix * skinnedTangent.xyz );\n#else\nvNormal = normalize( normalMatrix * normal );\nvTangent = normalize( normalMatrix * tangent.xyz );\n#endif\nvBinormal = normalize( cross( vNormal, vTangent ) * tangent.w );\nvUv = uv * uRepeat + uOffset;\nvec3 displacedPosition;\n#ifdef VERTEX_TEXTURES\nif ( enableDisplacement ) {\nvec3 dv = texture2D( tDisplacement, uv ).xyz;\nfloat df = uDisplacementScale * dv.x + uDisplacementBias;\ndisplacedPosition = position + normalize( normal ) * df;\n} else {\n#ifdef USE_SKINNING\nvec4 skinVertex = vec4( position, 1.0 );\nvec4 skinned  = boneMatX * skinVertex * skinWeight.x;\nskinned \t  += boneMatY * skinVertex * skinWeight.y;\ndisplacedPosition  = skinned.xyz;\n#else\ndisplacedPosition = position;\n#endif\n}\n#else\n#ifdef USE_SKINNING\nvec4 skinVertex = vec4( position, 1.0 );\nvec4 skinned  = boneMatX * skinVertex * skinWeight.x;\nskinned \t  += boneMatY * skinVertex * skinWeight.y;\ndisplacedPosition  = skinned.xyz;\n#else\ndisplacedPosition = position;\n#endif\n#endif\nvec4 mvPosition = modelViewMatrix * vec4( displacedPosition, 1.0 );\nvec4 worldPosition = modelMatrix * vec4( displacedPosition, 1.0 );\ngl_Position = projectionMatrix * mvPosition;\nvWorldPosition = worldPosition.xyz;\nvViewPosition = -mvPosition.xyz;\n#ifdef USE_SHADOWMAP\nfor( int i = 0; i < MAX_SHADOWS; i ++ ) {\nvShadowCoord[ i ] = shadowMatrix[ i ] * worldPosition;\n}\n#endif\n}"].join("\n")},
 THREE.ShaderChunk.skinning_pars_vertex,THREE.ShaderChunk.shadowmap_pars_vertex,"void main() {",THREE.ShaderChunk.skinbase_vertex,THREE.ShaderChunk.skinnormal_vertex,"#ifdef USE_SKINNING\nvNormal = normalize( normalMatrix * skinnedNormal.xyz );\nvec4 skinnedTangent = skinMatrix * vec4( tangent.xyz, 0.0 );\nvTangent = normalize( normalMatrix * skinnedTangent.xyz );\n#else\nvNormal = normalize( normalMatrix * normal );\nvTangent = normalize( normalMatrix * tangent.xyz );\n#endif\nvBinormal = normalize( cross( vNormal, vTangent ) * tangent.w );\nvUv = uv * uRepeat + uOffset;\nvec3 displacedPosition;\n#ifdef VERTEX_TEXTURES\nif ( enableDisplacement ) {\nvec3 dv = texture2D( tDisplacement, uv ).xyz;\nfloat df = uDisplacementScale * dv.x + uDisplacementBias;\ndisplacedPosition = position + normalize( normal ) * df;\n} else {\n#ifdef USE_SKINNING\nvec4 skinVertex = vec4( position, 1.0 );\nvec4 skinned  = boneMatX * skinVertex * skinWeight.x;\nskinned \t  += boneMatY * skinVertex * skinWeight.y;\ndisplacedPosition  = skinned.xyz;\n#else\ndisplacedPosition = position;\n#endif\n}\n#else\n#ifdef USE_SKINNING\nvec4 skinVertex = vec4( position, 1.0 );\nvec4 skinned  = boneMatX * skinVertex * skinWeight.x;\nskinned \t  += boneMatY * skinVertex * skinWeight.y;\ndisplacedPosition  = skinned.xyz;\n#else\ndisplacedPosition = position;\n#endif\n#endif\nvec4 mvPosition = modelViewMatrix * vec4( displacedPosition, 1.0 );\nvec4 worldPosition = modelMatrix * vec4( displacedPosition, 1.0 );\ngl_Position = projectionMatrix * mvPosition;\nvWorldPosition = worldPosition.xyz;\nvViewPosition = -mvPosition.xyz;\n#ifdef USE_SHADOWMAP\nfor( int i = 0; i < MAX_SHADOWS; i ++ ) {\nvShadowCoord[ i ] = shadowMatrix[ i ] * worldPosition;\n}\n#endif\n}"].join("\n")},
 cube:{uniforms:{tCube:{type:"t",value:null},tFlip:{type:"f",value:-1}},vertexShader:"varying vec3 vWorldPosition;\nvoid main() {\nvec4 worldPosition = modelMatrix * vec4( position, 1.0 );\nvWorldPosition = worldPosition.xyz;\ngl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}",fragmentShader:"uniform samplerCube tCube;\nuniform float tFlip;\nvarying vec3 vWorldPosition;\nvoid main() {\ngl_FragColor = textureCube( tCube, vec3( tFlip * vWorldPosition.x, vWorldPosition.yz ) );\n}"},
 cube:{uniforms:{tCube:{type:"t",value:null},tFlip:{type:"f",value:-1}},vertexShader:"varying vec3 vWorldPosition;\nvoid main() {\nvec4 worldPosition = modelMatrix * vec4( position, 1.0 );\nvWorldPosition = worldPosition.xyz;\ngl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}",fragmentShader:"uniform samplerCube tCube;\nuniform float tFlip;\nvarying vec3 vWorldPosition;\nvoid main() {\ngl_FragColor = textureCube( tCube, vec3( tFlip * vWorldPosition.x, vWorldPosition.yz ) );\n}"},
-depthRGBA:{uniforms:{},vertexShader:[THREE.ShaderChunk.morphtarget_pars_vertex,THREE.ShaderChunk.skinning_pars_vertex,"void main() {",THREE.ShaderChunk.skinbase_vertex,THREE.ShaderChunk.morphtarget_vertex,THREE.ShaderChunk.skinning_vertex,THREE.ShaderChunk.default_vertex,"}"].join("\n"),fragmentShader:"vec4 pack_depth( const in float depth ) {\nconst vec4 bit_shift = vec4( 256.0 * 256.0 * 256.0, 256.0 * 256.0, 256.0, 1.0 );\nconst vec4 bit_mask  = vec4( 0.0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0 );\nvec4 res = fract( depth * bit_shift );\nres -= res.xxyz * bit_mask;\nreturn res;\n}\nvoid main() {\ngl_FragData[ 0 ] = pack_depth( gl_FragCoord.z );\n}"}};THREE.WebGLRenderer=function(a){function b(a){if(a.__webglCustomAttributesList)for(var b in a.__webglCustomAttributesList)j.deleteBuffer(a.__webglCustomAttributesList[b].buffer)}function c(a,b){var c=a.vertices.length,d=b.material;if(d.attributes){void 0===a.__webglCustomAttributesList&&(a.__webglCustomAttributesList=[]);for(var e in d.attributes){var f=d.attributes[e];if(!f.__webglInitialized||f.createUniqueBuffers){f.__webglInitialized=!0;var g=1;"v2"===f.type?g=2:"v3"===f.type?g=3:"v4"===f.type?
-g=4:"c"===f.type&&(g=3);f.size=g;f.array=new Float32Array(c*g);f.buffer=j.createBuffer();f.buffer.belongsToAttribute=e;f.needsUpdate=!0}a.__webglCustomAttributesList.push(f)}}}function d(a,b){var c=b.geometry,d=a.faces3,h=a.faces4,i=3*d.length+4*h.length,k=1*d.length+2*h.length,h=3*d.length+4*h.length,d=e(b,a),m=g(d),l=f(d),n=d.vertexColors?d.vertexColors:!1;a.__vertexArray=new Float32Array(3*i);l&&(a.__normalArray=new Float32Array(3*i));c.hasTangents&&(a.__tangentArray=new Float32Array(4*i));n&&
-(a.__colorArray=new Float32Array(3*i));if(m){if(0<c.faceUvs.length||0<c.faceVertexUvs.length)a.__uvArray=new Float32Array(2*i);if(1<c.faceUvs.length||1<c.faceVertexUvs.length)a.__uv2Array=new Float32Array(2*i)}b.geometry.skinWeights.length&&b.geometry.skinIndices.length&&(a.__skinIndexArray=new Float32Array(4*i),a.__skinWeightArray=new Float32Array(4*i));a.__faceArray=new Uint16Array(3*k);a.__lineArray=new Uint16Array(2*h);if(a.numMorphTargets){a.__morphTargetsArrays=[];c=0;for(m=a.numMorphTargets;c<
-m;c++)a.__morphTargetsArrays.push(new Float32Array(3*i))}if(a.numMorphNormals){a.__morphNormalsArrays=[];c=0;for(m=a.numMorphNormals;c<m;c++)a.__morphNormalsArrays.push(new Float32Array(3*i))}a.__webglFaceCount=3*k;a.__webglLineCount=2*h;if(d.attributes){void 0===a.__webglCustomAttributesList&&(a.__webglCustomAttributesList=[]);for(var p in d.attributes){var k=d.attributes[p],c={},q;for(q in k)c[q]=k[q];if(!c.__webglInitialized||c.createUniqueBuffers)c.__webglInitialized=!0,h=1,"v2"===c.type?h=2:
-"v3"===c.type?h=3:"v4"===c.type?h=4:"c"===c.type&&(h=3),c.size=h,c.array=new Float32Array(i*h),c.buffer=j.createBuffer(),c.buffer.belongsToAttribute=p,k.needsUpdate=!0,c.__original=k;a.__webglCustomAttributesList.push(c)}}a.__inittedArrays=!0}function e(a,b){return a.material instanceof THREE.MeshFaceMaterial?a.material.materials[b.materialIndex]:a.material}function f(a){return a instanceof THREE.MeshBasicMaterial&&!a.envMap||a instanceof THREE.MeshDepthMaterial?!1:a&&void 0!==a.shading&&a.shading===
-THREE.SmoothShading?THREE.SmoothShading:THREE.FlatShading}function g(a){return a.map||a.lightMap||a.bumpMap||a.normalMap||a.specularMap||a instanceof THREE.ShaderMaterial?!0:!1}function h(a){xb[a]||(j.enableVertexAttribArray(a),xb[a]=!0)}function i(){for(var a in xb)xb[a]&&(j.disableVertexAttribArray(a),xb[a]=!1)}function k(a,b){return a.z!==b.z?b.z-a.z:b.id-a.id}function l(a,b){return b[0]-a[0]}function n(a,b,c){if(a.length)for(var d=0,e=a.length;d<e;d++)La=kb=null,lb=db=V=ha=Pa=na=$=-1,yb=!0,a[d].render(b,
-c,Nb,Ob),La=kb=null,lb=db=V=ha=Pa=na=$=-1,yb=!0}function m(a,b,c,d,e,f,g,h){var j,i,k,m;b?(i=a.length-1,m=b=-1):(i=0,b=a.length,m=1);for(var l=i;l!==b;l+=m)if(j=a[l],j.render){i=j.object;k=j.buffer;if(h)j=h;else{j=j[c];if(!j)continue;g&&L.setBlending(j.blending,j.blendEquation,j.blendSrc,j.blendDst);L.setDepthTest(j.depthTest);L.setDepthWrite(j.depthWrite);I(j.polygonOffset,j.polygonOffsetFactor,j.polygonOffsetUnits)}L.setMaterialFaces(j);k instanceof THREE.BufferGeometry?L.renderBufferDirect(d,e,
-f,j,k,i):L.renderBuffer(d,e,f,j,k,i)}}function t(a,b,c,d,e,f,g){for(var h,j,i=0,k=a.length;i<k;i++)if(h=a[i],j=h.object,j.visible){if(g)h=g;else{h=h[b];if(!h)continue;f&&L.setBlending(h.blending,h.blendEquation,h.blendSrc,h.blendDst);L.setDepthTest(h.depthTest);L.setDepthWrite(h.depthWrite);I(h.polygonOffset,h.polygonOffsetFactor,h.polygonOffsetUnits)}L.renderImmediateObject(c,d,e,h,j)}}function r(a,b,c){a.push({buffer:b,object:c,opaque:null,transparent:null})}function p(a){for(var b in a.attributes)if(a.attributes[b].needsUpdate)return!0;
-return!1}function q(a){for(var b in a.attributes)a.attributes[b].needsUpdate=!1}function y(a,b){for(var c=a.length-1;0<=c;c--)a[c].object===b&&a.splice(c,1)}function v(a,b){for(var c=a.length-1;0<=c;c--)a[c]===b&&a.splice(c,1)}function z(a,b,c,d,e){ea=0;d.needsUpdate&&(d.program&&Yc(d),L.initMaterial(d,b,c,e),d.needsUpdate=!1);d.morphTargets&&!e.__webglMorphTargetInfluences&&(e.__webglMorphTargetInfluences=new Float32Array(L.maxMorphTargets));var f=!1,g=d.program,h=g.uniforms,i=d.uniforms;g!==kb&&
-(j.useProgram(g),kb=g,f=!0);d.id!==lb&&(lb=d.id,f=!0);if(f||a!==La)j.uniformMatrix4fv(h.projectionMatrix,!1,a.projectionMatrix.elements),a!==La&&(La=a);if(d.skinning)if(Cc&&e.useVertexTexture){if(null!==h.boneTexture){var k=s();j.uniform1i(h.boneTexture,k);L.setTexture(e.boneTexture,k)}}else null!==h.boneGlobalMatrices&&j.uniformMatrix4fv(h.boneGlobalMatrices,!1,e.boneMatrices);if(f){c&&d.fog&&(i.fogColor.value=c.color,c instanceof THREE.Fog?(i.fogNear.value=c.near,i.fogFar.value=c.far):c instanceof
-THREE.FogExp2&&(i.fogDensity.value=c.density));if(d instanceof THREE.MeshPhongMaterial||d instanceof THREE.MeshLambertMaterial||d.lights){if(yb){for(var m,l=k=0,n=0,p,q,t,r=pb,v=r.directional.colors,y=r.directional.positions,w=r.point.colors,z=r.point.positions,A=r.point.distances,C=r.spot.colors,E=r.spot.positions,I=r.spot.distances,J=r.spot.directions,K=r.spot.anglesCos,M=r.spot.exponents,V=r.hemi.skyColors,N=r.hemi.groundColors,U=r.hemi.positions,ra=0,T=0,$=0,ha=0,fa=0,Oa=0,ia=0,$a=0,ca=m=0,c=
-t=ca=0,f=b.length;c<f;c++)m=b[c],m.onlyShadow||(p=m.color,q=m.intensity,t=m.distance,m instanceof THREE.AmbientLight?m.visible&&(L.gammaInput?(k+=p.r*p.r,l+=p.g*p.g,n+=p.b*p.b):(k+=p.r,l+=p.g,n+=p.b)):m instanceof THREE.DirectionalLight?(fa+=1,m.visible&&(xa.getPositionFromMatrix(m.matrixWorld),wa.getPositionFromMatrix(m.target.matrixWorld),xa.sub(wa),xa.normalize(),0===xa.x&&0===xa.y&&0===xa.z||(m=3*ra,y[m]=xa.x,y[m+1]=xa.y,y[m+2]=xa.z,L.gammaInput?H(v,m,p,q*q):B(v,m,p,q),ra+=1))):m instanceof THREE.PointLight?
-(Oa+=1,m.visible&&(ca=3*T,L.gammaInput?H(w,ca,p,q*q):B(w,ca,p,q),wa.getPositionFromMatrix(m.matrixWorld),z[ca]=wa.x,z[ca+1]=wa.y,z[ca+2]=wa.z,A[T]=t,T+=1)):m instanceof THREE.SpotLight?(ia+=1,m.visible&&(ca=3*$,L.gammaInput?H(C,ca,p,q*q):B(C,ca,p,q),wa.getPositionFromMatrix(m.matrixWorld),E[ca]=wa.x,E[ca+1]=wa.y,E[ca+2]=wa.z,I[$]=t,xa.copy(wa),wa.getPositionFromMatrix(m.target.matrixWorld),xa.sub(wa),xa.normalize(),J[ca]=xa.x,J[ca+1]=xa.y,J[ca+2]=xa.z,K[$]=Math.cos(m.angle),M[$]=m.exponent,$+=1)):
-m instanceof THREE.HemisphereLight&&($a+=1,m.visible&&(xa.getPositionFromMatrix(m.matrixWorld),xa.normalize(),0===xa.x&&0===xa.y&&0===xa.z||(t=3*ha,U[t]=xa.x,U[t+1]=xa.y,U[t+2]=xa.z,p=m.color,m=m.groundColor,L.gammaInput?(q*=q,H(V,t,p,q),H(N,t,m,q)):(B(V,t,p,q),B(N,t,m,q)),ha+=1))));c=3*ra;for(f=Math.max(v.length,3*fa);c<f;c++)v[c]=0;c=3*T;for(f=Math.max(w.length,3*Oa);c<f;c++)w[c]=0;c=3*$;for(f=Math.max(C.length,3*ia);c<f;c++)C[c]=0;c=3*ha;for(f=Math.max(V.length,3*$a);c<f;c++)V[c]=0;c=3*ha;for(f=
-Math.max(N.length,3*$a);c<f;c++)N[c]=0;r.directional.length=ra;r.point.length=T;r.spot.length=$;r.hemi.length=ha;r.ambient[0]=k;r.ambient[1]=l;r.ambient[2]=n;yb=!1}c=pb;i.ambientLightColor.value=c.ambient;i.directionalLightColor.value=c.directional.colors;i.directionalLightDirection.value=c.directional.positions;i.pointLightColor.value=c.point.colors;i.pointLightPosition.value=c.point.positions;i.pointLightDistance.value=c.point.distances;i.spotLightColor.value=c.spot.colors;i.spotLightPosition.value=
-c.spot.positions;i.spotLightDistance.value=c.spot.distances;i.spotLightDirection.value=c.spot.directions;i.spotLightAngleCos.value=c.spot.anglesCos;i.spotLightExponent.value=c.spot.exponents;i.hemisphereLightSkyColor.value=c.hemi.skyColors;i.hemisphereLightGroundColor.value=c.hemi.groundColors;i.hemisphereLightDirection.value=c.hemi.positions}if(d instanceof THREE.MeshBasicMaterial||d instanceof THREE.MeshLambertMaterial||d instanceof THREE.MeshPhongMaterial){i.opacity.value=d.opacity;L.gammaInput?
-i.diffuse.value.copyGammaToLinear(d.color):i.diffuse.value=d.color;i.map.value=d.map;i.lightMap.value=d.lightMap;i.specularMap.value=d.specularMap;d.bumpMap&&(i.bumpMap.value=d.bumpMap,i.bumpScale.value=d.bumpScale);d.normalMap&&(i.normalMap.value=d.normalMap,i.normalScale.value.copy(d.normalScale));var Y;d.map?Y=d.map:d.specularMap?Y=d.specularMap:d.normalMap?Y=d.normalMap:d.bumpMap&&(Y=d.bumpMap);void 0!==Y&&(c=Y.offset,Y=Y.repeat,i.offsetRepeat.value.set(c.x,c.y,Y.x,Y.y));i.envMap.value=d.envMap;
-i.flipEnvMap.value=d.envMap instanceof THREE.WebGLRenderTargetCube?1:-1;i.reflectivity.value=d.reflectivity;i.refractionRatio.value=d.refractionRatio;i.combine.value=d.combine;i.useRefract.value=d.envMap&&d.envMap.mapping instanceof THREE.CubeRefractionMapping}d instanceof THREE.LineBasicMaterial?(i.diffuse.value=d.color,i.opacity.value=d.opacity):d instanceof THREE.LineDashedMaterial?(i.diffuse.value=d.color,i.opacity.value=d.opacity,i.dashSize.value=d.dashSize,i.totalSize.value=d.dashSize+d.gapSize,
-i.scale.value=d.scale):d instanceof THREE.ParticleBasicMaterial?(i.psColor.value=d.color,i.opacity.value=d.opacity,i.size.value=d.size,i.scale.value=G.height/2,i.map.value=d.map):d instanceof THREE.MeshPhongMaterial?(i.shininess.value=d.shininess,L.gammaInput?(i.ambient.value.copyGammaToLinear(d.ambient),i.emissive.value.copyGammaToLinear(d.emissive),i.specular.value.copyGammaToLinear(d.specular)):(i.ambient.value=d.ambient,i.emissive.value=d.emissive,i.specular.value=d.specular),d.wrapAround&&i.wrapRGB.value.copy(d.wrapRGB)):
-d instanceof THREE.MeshLambertMaterial?(L.gammaInput?(i.ambient.value.copyGammaToLinear(d.ambient),i.emissive.value.copyGammaToLinear(d.emissive)):(i.ambient.value=d.ambient,i.emissive.value=d.emissive),d.wrapAround&&i.wrapRGB.value.copy(d.wrapRGB)):d instanceof THREE.MeshDepthMaterial?(i.mNear.value=a.near,i.mFar.value=a.far,i.opacity.value=d.opacity):d instanceof THREE.MeshNormalMaterial&&(i.opacity.value=d.opacity);if(e.receiveShadow&&!d._shadowPass&&i.shadowMatrix){c=Y=0;for(f=b.length;c<f;c++)if(k=
-b[c],k.castShadow&&(k instanceof THREE.SpotLight||k instanceof THREE.DirectionalLight&&!k.shadowCascade))i.shadowMap.value[Y]=k.shadowMap,i.shadowMapSize.value[Y]=k.shadowMapSize,i.shadowMatrix.value[Y]=k.shadowMatrix,i.shadowDarkness.value[Y]=k.shadowDarkness,i.shadowBias.value[Y]=k.shadowBias,Y++}b=d.uniformsList;i=0;for(Y=b.length;i<Y;i++)if(f=g.uniforms[b[i][1]])if(c=b[i][0],l=c.type,k=c.value,"i"===l)j.uniform1i(f,k);else if("f"===l)j.uniform1f(f,k);else if("v2"===l)j.uniform2f(f,k.x,k.y);else if("v3"===
-l)j.uniform3f(f,k.x,k.y,k.z);else if("v4"===l)j.uniform4f(f,k.x,k.y,k.z,k.w);else if("c"===l)j.uniform3f(f,k.r,k.g,k.b);else if("iv1"===l)j.uniform1iv(f,k);else if("iv"===l)j.uniform3iv(f,k);else if("fv1"===l)j.uniform1fv(f,k);else if("fv"===l)j.uniform3fv(f,k);else if("v2v"===l){void 0===c._array&&(c._array=new Float32Array(2*k.length));l=0;for(n=k.length;l<n;l++)r=2*l,c._array[r]=k[l].x,c._array[r+1]=k[l].y;j.uniform2fv(f,c._array)}else if("v3v"===l){void 0===c._array&&(c._array=new Float32Array(3*
-k.length));l=0;for(n=k.length;l<n;l++)r=3*l,c._array[r]=k[l].x,c._array[r+1]=k[l].y,c._array[r+2]=k[l].z;j.uniform3fv(f,c._array)}else if("v4v"===l){void 0===c._array&&(c._array=new Float32Array(4*k.length));l=0;for(n=k.length;l<n;l++)r=4*l,c._array[r]=k[l].x,c._array[r+1]=k[l].y,c._array[r+2]=k[l].z,c._array[r+3]=k[l].w;j.uniform4fv(f,c._array)}else if("m4"===l)void 0===c._array&&(c._array=new Float32Array(16)),k.flattenToArray(c._array),j.uniformMatrix4fv(f,!1,c._array);else if("m4v"===l){void 0===
-c._array&&(c._array=new Float32Array(16*k.length));l=0;for(n=k.length;l<n;l++)k[l].flattenToArrayOffset(c._array,16*l);j.uniformMatrix4fv(f,!1,c._array)}else if("t"===l){if(r=k,k=s(),j.uniform1i(f,k),r)if(r.image instanceof Array&&6===r.image.length){if(c=r,f=k,6===c.image.length)if(c.needsUpdate){c.image.__webglTextureCube||(c.image.__webglTextureCube=j.createTexture(),L.info.memory.textures++);j.activeTexture(j.TEXTURE0+f);j.bindTexture(j.TEXTURE_CUBE_MAP,c.image.__webglTextureCube);j.pixelStorei(j.UNPACK_FLIP_Y_WEBGL,
-c.flipY);f=c instanceof THREE.CompressedTexture;k=[];for(l=0;6>l;l++)L.autoScaleCubemaps&&!f?(n=k,r=l,v=c.image[l],w=pd,v.width<=w&&v.height<=w||(z=Math.max(v.width,v.height),y=Math.floor(v.width*w/z),w=Math.floor(v.height*w/z),z=document.createElement("canvas"),z.width=y,z.height=w,z.getContext("2d").drawImage(v,0,0,v.width,v.height,0,0,y,w),v=z),n[r]=v):k[l]=c.image[l];l=k[0];n=0===(l.width&l.width-1)&&0===(l.height&l.height-1);r=F(c.format);v=F(c.type);Z(j.TEXTURE_CUBE_MAP,c,n);for(l=0;6>l;l++)if(f){w=
-k[l].mipmaps;z=0;for(A=w.length;z<A;z++)y=w[z],j.compressedTexImage2D(j.TEXTURE_CUBE_MAP_POSITIVE_X+l,z,r,y.width,y.height,0,y.data)}else j.texImage2D(j.TEXTURE_CUBE_MAP_POSITIVE_X+l,0,r,r,v,k[l]);c.generateMipmaps&&n&&j.generateMipmap(j.TEXTURE_CUBE_MAP);c.needsUpdate=!1;if(c.onUpdate)c.onUpdate()}else j.activeTexture(j.TEXTURE0+f),j.bindTexture(j.TEXTURE_CUBE_MAP,c.image.__webglTextureCube)}else r instanceof THREE.WebGLRenderTargetCube?(c=r,j.activeTexture(j.TEXTURE0+k),j.bindTexture(j.TEXTURE_CUBE_MAP,
-c.__webglTexture)):L.setTexture(r,k)}else if("tv"===l){void 0===c._array&&(c._array=[]);l=0;for(n=c.value.length;l<n;l++)c._array[l]=s();j.uniform1iv(f,c._array);l=0;for(n=c.value.length;l<n;l++)r=c.value[l],k=c._array[l],r&&L.setTexture(r,k)}if((d instanceof THREE.ShaderMaterial||d instanceof THREE.MeshPhongMaterial||d.envMap)&&null!==h.cameraPosition)wa.getPositionFromMatrix(a.matrixWorld),j.uniform3f(h.cameraPosition,wa.x,wa.y,wa.z);(d instanceof THREE.MeshPhongMaterial||d instanceof THREE.MeshLambertMaterial||
-d instanceof THREE.ShaderMaterial||d.skinning)&&null!==h.viewMatrix&&j.uniformMatrix4fv(h.viewMatrix,!1,a.matrixWorldInverse.elements)}j.uniformMatrix4fv(h.modelViewMatrix,!1,e._modelViewMatrix.elements);h.normalMatrix&&j.uniformMatrix3fv(h.normalMatrix,!1,e._normalMatrix.elements);null!==h.modelMatrix&&j.uniformMatrix4fv(h.modelMatrix,!1,e.matrixWorld.elements);return g}function s(){var a=ea;a>=Ib&&console.warn("WebGLRenderer: trying to use "+a+" texture units while this GPU supports only "+Ib);
-ea+=1;return a}function C(a,b){a._modelViewMatrix.multiplyMatrices(b.matrixWorldInverse,a.matrixWorld);a._normalMatrix.getInverse(a._modelViewMatrix);a._normalMatrix.transpose()}function H(a,b,c,d){a[b]=c.r*c.r*d;a[b+1]=c.g*c.g*d;a[b+2]=c.b*c.b*d}function B(a,b,c,d){a[b]=c.r*d;a[b+1]=c.g*d;a[b+2]=c.b*d}function w(a){a!==Sa&&(j.lineWidth(a),Sa=a)}function I(a,b,c){Ba!==a&&(a?j.enable(j.POLYGON_OFFSET_FILL):j.disable(j.POLYGON_OFFSET_FILL),Ba=a);if(a&&(fb!==b||jb!==c))j.polygonOffset(b,c),fb=b,jb=c}
-function J(a){for(var a=a.split("\n"),b=0,c=a.length;b<c;b++)a[b]=b+1+": "+a[b];return a.join("\n")}function E(a,b){var c;"fragment"===a?c=j.createShader(j.FRAGMENT_SHADER):"vertex"===a&&(c=j.createShader(j.VERTEX_SHADER));j.shaderSource(c,b);j.compileShader(c);return!j.getShaderParameter(c,j.COMPILE_STATUS)?(console.error(j.getShaderInfoLog(c)),console.error(J(b)),null):c}function Z(a,b,c){c?(j.texParameteri(a,j.TEXTURE_WRAP_S,F(b.wrapS)),j.texParameteri(a,j.TEXTURE_WRAP_T,F(b.wrapT)),j.texParameteri(a,
-j.TEXTURE_MAG_FILTER,F(b.magFilter)),j.texParameteri(a,j.TEXTURE_MIN_FILTER,F(b.minFilter))):(j.texParameteri(a,j.TEXTURE_WRAP_S,j.CLAMP_TO_EDGE),j.texParameteri(a,j.TEXTURE_WRAP_T,j.CLAMP_TO_EDGE),j.texParameteri(a,j.TEXTURE_MAG_FILTER,U(b.magFilter)),j.texParameteri(a,j.TEXTURE_MIN_FILTER,U(b.minFilter)));if(Wa&&b.type!==THREE.FloatType&&(1<b.anisotropy||b.__oldAnisotropy))j.texParameterf(a,Wa.TEXTURE_MAX_ANISOTROPY_EXT,Math.min(b.anisotropy,Wc)),b.__oldAnisotropy=b.anisotropy}function A(a,b){j.bindRenderbuffer(j.RENDERBUFFER,
-a);b.depthBuffer&&!b.stencilBuffer?(j.renderbufferStorage(j.RENDERBUFFER,j.DEPTH_COMPONENT16,b.width,b.height),j.framebufferRenderbuffer(j.FRAMEBUFFER,j.DEPTH_ATTACHMENT,j.RENDERBUFFER,a)):b.depthBuffer&&b.stencilBuffer?(j.renderbufferStorage(j.RENDERBUFFER,j.DEPTH_STENCIL,b.width,b.height),j.framebufferRenderbuffer(j.FRAMEBUFFER,j.DEPTH_STENCIL_ATTACHMENT,j.RENDERBUFFER,a)):j.renderbufferStorage(j.RENDERBUFFER,j.RGBA4,b.width,b.height)}function U(a){return a===THREE.NearestFilter||a===THREE.NearestMipMapNearestFilter||
-a===THREE.NearestMipMapLinearFilter?j.NEAREST:j.LINEAR}function F(a){if(a===THREE.RepeatWrapping)return j.REPEAT;if(a===THREE.ClampToEdgeWrapping)return j.CLAMP_TO_EDGE;if(a===THREE.MirroredRepeatWrapping)return j.MIRRORED_REPEAT;if(a===THREE.NearestFilter)return j.NEAREST;if(a===THREE.NearestMipMapNearestFilter)return j.NEAREST_MIPMAP_NEAREST;if(a===THREE.NearestMipMapLinearFilter)return j.NEAREST_MIPMAP_LINEAR;if(a===THREE.LinearFilter)return j.LINEAR;if(a===THREE.LinearMipMapNearestFilter)return j.LINEAR_MIPMAP_NEAREST;
-if(a===THREE.LinearMipMapLinearFilter)return j.LINEAR_MIPMAP_LINEAR;if(a===THREE.UnsignedByteType)return j.UNSIGNED_BYTE;if(a===THREE.UnsignedShort4444Type)return j.UNSIGNED_SHORT_4_4_4_4;if(a===THREE.UnsignedShort5551Type)return j.UNSIGNED_SHORT_5_5_5_1;if(a===THREE.UnsignedShort565Type)return j.UNSIGNED_SHORT_5_6_5;if(a===THREE.ByteType)return j.BYTE;if(a===THREE.ShortType)return j.SHORT;if(a===THREE.UnsignedShortType)return j.UNSIGNED_SHORT;if(a===THREE.IntType)return j.INT;if(a===THREE.UnsignedIntType)return j.UNSIGNED_INT;
-if(a===THREE.FloatType)return j.FLOAT;if(a===THREE.AlphaFormat)return j.ALPHA;if(a===THREE.RGBFormat)return j.RGB;if(a===THREE.RGBAFormat)return j.RGBA;if(a===THREE.LuminanceFormat)return j.LUMINANCE;if(a===THREE.LuminanceAlphaFormat)return j.LUMINANCE_ALPHA;if(a===THREE.AddEquation)return j.FUNC_ADD;if(a===THREE.SubtractEquation)return j.FUNC_SUBTRACT;if(a===THREE.ReverseSubtractEquation)return j.FUNC_REVERSE_SUBTRACT;if(a===THREE.ZeroFactor)return j.ZERO;if(a===THREE.OneFactor)return j.ONE;if(a===
-THREE.SrcColorFactor)return j.SRC_COLOR;if(a===THREE.OneMinusSrcColorFactor)return j.ONE_MINUS_SRC_COLOR;if(a===THREE.SrcAlphaFactor)return j.SRC_ALPHA;if(a===THREE.OneMinusSrcAlphaFactor)return j.ONE_MINUS_SRC_ALPHA;if(a===THREE.DstAlphaFactor)return j.DST_ALPHA;if(a===THREE.OneMinusDstAlphaFactor)return j.ONE_MINUS_DST_ALPHA;if(a===THREE.DstColorFactor)return j.DST_COLOR;if(a===THREE.OneMinusDstColorFactor)return j.ONE_MINUS_DST_COLOR;if(a===THREE.SrcAlphaSaturateFactor)return j.SRC_ALPHA_SATURATE;
-if(void 0!==Ga){if(a===THREE.RGB_S3TC_DXT1_Format)return Ga.COMPRESSED_RGB_S3TC_DXT1_EXT;if(a===THREE.RGBA_S3TC_DXT1_Format)return Ga.COMPRESSED_RGBA_S3TC_DXT1_EXT;if(a===THREE.RGBA_S3TC_DXT3_Format)return Ga.COMPRESSED_RGBA_S3TC_DXT3_EXT;if(a===THREE.RGBA_S3TC_DXT5_Format)return Ga.COMPRESSED_RGBA_S3TC_DXT5_EXT}return 0}console.log("THREE.WebGLRenderer",THREE.REVISION);var a=a||{},G=void 0!==a.canvas?a.canvas:document.createElement("canvas"),K=void 0!==a.precision?a.precision:"highp",N=void 0!==
-a.alpha?a.alpha:!0,fa=void 0!==a.premultipliedAlpha?a.premultipliedAlpha:!0,ma=void 0!==a.antialias?a.antialias:!1,eb=void 0!==a.stencil?a.stencil:!0,M=void 0!==a.preserveDrawingBuffer?a.preserveDrawingBuffer:!1,T=void 0!==a.clearColor?new THREE.Color(a.clearColor):new THREE.Color(0),ja=void 0!==a.clearAlpha?a.clearAlpha:0;this.domElement=G;this.context=null;this.devicePixelRatio=void 0!==a.devicePixelRatio?a.devicePixelRatio:void 0!==window.devicePixelRatio?window.devicePixelRatio:1;this.autoUpdateScene=
-this.autoUpdateObjects=this.sortObjects=this.autoClearStencil=this.autoClearDepth=this.autoClearColor=this.autoClear=!0;this.shadowMapEnabled=this.physicallyBasedShading=this.gammaOutput=this.gammaInput=!1;this.shadowMapAutoUpdate=!0;this.shadowMapType=THREE.PCFShadowMap;this.shadowMapCullFace=THREE.CullFaceFront;this.shadowMapCascade=this.shadowMapDebug=!1;this.maxMorphTargets=8;this.maxMorphNormals=4;this.autoScaleCubemaps=!0;this.renderPluginsPre=[];this.renderPluginsPost=[];this.info={memory:{programs:0,
-geometries:0,textures:0},render:{calls:0,vertices:0,faces:0,points:0}};var L=this,ca=[],ra=0,kb=null,$a=null,lb=-1,db=null,La=null,Oa=0,ea=0,ha=-1,V=-1,$=-1,Y=-1,ia=-1,sa=-1,na=-1,Pa=-1,Ba=null,fb=null,jb=null,Sa=null,ob=0,Gb=0,Mb=0,wb=0,Nb=0,Ob=0,xb={},Hb=new THREE.Frustum,Qa=new THREE.Matrix4,Va=new THREE.Matrix4,wa=new THREE.Vector3,xa=new THREE.Vector3,yb=!0,pb={ambient:[0,0,0],directional:{length:0,colors:[],positions:[]},point:{length:0,colors:[],positions:[],distances:[]},spot:{length:0,colors:[],
-positions:[],distances:[],directions:[],anglesCos:[],exponents:[]},hemi:{length:0,skyColors:[],groundColors:[],positions:[]}},j,mb,vb,Wa,Ga;try{if(!(j=G.getContext("experimental-webgl",{alpha:N,premultipliedAlpha:fa,antialias:ma,stencil:eb,preserveDrawingBuffer:M})))throw"Error creating WebGL context.";}catch(zb){console.error(zb)}mb=j.getExtension("OES_texture_float");vb=j.getExtension("OES_standard_derivatives");Wa=j.getExtension("EXT_texture_filter_anisotropic")||j.getExtension("MOZ_EXT_texture_filter_anisotropic")||
-j.getExtension("WEBKIT_EXT_texture_filter_anisotropic");Ga=j.getExtension("WEBGL_compressed_texture_s3tc")||j.getExtension("MOZ_WEBGL_compressed_texture_s3tc")||j.getExtension("WEBKIT_WEBGL_compressed_texture_s3tc");mb||console.log("THREE.WebGLRenderer: Float textures not supported.");vb||console.log("THREE.WebGLRenderer: Standard derivatives not supported.");Wa||console.log("THREE.WebGLRenderer: Anisotropic texture filtering not supported.");Ga||console.log("THREE.WebGLRenderer: S3TC compressed textures not supported.");
-void 0===j.getShaderPrecisionFormat&&(j.getShaderPrecisionFormat=function(){return{rangeMin:1,rangeMax:1,precision:1}});j.clearColor(0,0,0,1);j.clearDepth(1);j.clearStencil(0);j.enable(j.DEPTH_TEST);j.depthFunc(j.LEQUAL);j.frontFace(j.CCW);j.cullFace(j.BACK);j.enable(j.CULL_FACE);j.enable(j.BLEND);j.blendEquation(j.FUNC_ADD);j.blendFunc(j.SRC_ALPHA,j.ONE_MINUS_SRC_ALPHA);j.clearColor(T.r,T.g,T.b,ja);this.context=j;var Ib=j.getParameter(j.MAX_TEXTURE_IMAGE_UNITS),a=j.getParameter(j.MAX_VERTEX_TEXTURE_IMAGE_UNITS);
-j.getParameter(j.MAX_TEXTURE_SIZE);var pd=j.getParameter(j.MAX_CUBE_MAP_TEXTURE_SIZE),Wc=Wa?j.getParameter(Wa.MAX_TEXTURE_MAX_ANISOTROPY_EXT):0,Bc=0<a,Cc=Bc&&mb;Ga&&j.getParameter(j.COMPRESSED_TEXTURE_FORMATS);fa=j.getShaderPrecisionFormat(j.VERTEX_SHADER,j.HIGH_FLOAT);a=j.getShaderPrecisionFormat(j.VERTEX_SHADER,j.MEDIUM_FLOAT);j.getShaderPrecisionFormat(j.VERTEX_SHADER,j.LOW_FLOAT);ma=j.getShaderPrecisionFormat(j.FRAGMENT_SHADER,j.HIGH_FLOAT);N=j.getShaderPrecisionFormat(j.FRAGMENT_SHADER,j.MEDIUM_FLOAT);
-j.getShaderPrecisionFormat(j.FRAGMENT_SHADER,j.LOW_FLOAT);j.getShaderPrecisionFormat(j.VERTEX_SHADER,j.HIGH_INT);j.getShaderPrecisionFormat(j.VERTEX_SHADER,j.MEDIUM_INT);j.getShaderPrecisionFormat(j.VERTEX_SHADER,j.LOW_INT);j.getShaderPrecisionFormat(j.FRAGMENT_SHADER,j.HIGH_INT);j.getShaderPrecisionFormat(j.FRAGMENT_SHADER,j.MEDIUM_INT);j.getShaderPrecisionFormat(j.FRAGMENT_SHADER,j.LOW_INT);fa=0<fa.precision&&0<ma.precision;a=0<a.precision&&0<N.precision;"highp"===K&&!fa&&(a?(K="mediump",console.warn("WebGLRenderer: highp not supported, using mediump")):
-(K="lowp",console.warn("WebGLRenderer: highp and mediump not supported, using lowp")));"mediump"===K&&!a&&(K="lowp",console.warn("WebGLRenderer: mediump not supported, using lowp"));this.getContext=function(){return j};this.supportsVertexTextures=function(){return Bc};this.supportsFloatTextures=function(){return mb};this.supportsStandardDerivatives=function(){return vb};this.supportsCompressedTextureS3TC=function(){return Ga};this.getMaxAnisotropy=function(){return Wc};this.getPrecision=function(){return K};
-this.setSize=function(a,b){G.width=a*this.devicePixelRatio;G.height=b*this.devicePixelRatio;G.style.width=a+"px";G.style.height=b+"px";this.setViewport(0,0,G.width,G.height)};this.setViewport=function(a,b,c,d){ob=void 0!==a?a:0;Gb=void 0!==b?b:0;Mb=void 0!==c?c:G.width;wb=void 0!==d?d:G.height;j.viewport(ob,Gb,Mb,wb)};this.setScissor=function(a,b,c,d){j.scissor(a,b,c,d)};this.enableScissorTest=function(a){a?j.enable(j.SCISSOR_TEST):j.disable(j.SCISSOR_TEST)};this.setClearColorHex=function(a,b){T.setHex(a);
-ja=b;j.clearColor(T.r,T.g,T.b,ja)};this.setClearColor=function(a,b){T.copy(a);ja=b;j.clearColor(T.r,T.g,T.b,ja)};this.getClearColor=function(){return T};this.getClearAlpha=function(){return ja};this.clear=function(a,b,c){var d=0;if(void 0===a||a)d|=j.COLOR_BUFFER_BIT;if(void 0===b||b)d|=j.DEPTH_BUFFER_BIT;if(void 0===c||c)d|=j.STENCIL_BUFFER_BIT;j.clear(d)};this.clearTarget=function(a,b,c,d){this.setRenderTarget(a);this.clear(b,c,d)};this.addPostPlugin=function(a){a.init(this);this.renderPluginsPost.push(a)};
-this.addPrePlugin=function(a){a.init(this);this.renderPluginsPre.push(a)};this.updateShadowMap=function(a,b){kb=null;lb=db=Pa=na=$=-1;yb=!0;V=ha=-1;this.shadowMapPlugin.update(a,b)};var Bd=function(a){a=a.target;a.removeEventListener("dispose",Bd);a.__webglInit=void 0;void 0!==a.__webglVertexBuffer&&j.deleteBuffer(a.__webglVertexBuffer);void 0!==a.__webglNormalBuffer&&j.deleteBuffer(a.__webglNormalBuffer);void 0!==a.__webglTangentBuffer&&j.deleteBuffer(a.__webglTangentBuffer);void 0!==a.__webglColorBuffer&&
-j.deleteBuffer(a.__webglColorBuffer);void 0!==a.__webglUVBuffer&&j.deleteBuffer(a.__webglUVBuffer);void 0!==a.__webglUV2Buffer&&j.deleteBuffer(a.__webglUV2Buffer);void 0!==a.__webglSkinIndicesBuffer&&j.deleteBuffer(a.__webglSkinIndicesBuffer);void 0!==a.__webglSkinWeightsBuffer&&j.deleteBuffer(a.__webglSkinWeightsBuffer);void 0!==a.__webglFaceBuffer&&j.deleteBuffer(a.__webglFaceBuffer);void 0!==a.__webglLineBuffer&&j.deleteBuffer(a.__webglLineBuffer);void 0!==a.__webglLineDistanceBuffer&&j.deleteBuffer(a.__webglLineDistanceBuffer);
-if(void 0!==a.geometryGroups)for(var c in a.geometryGroups){var d=a.geometryGroups[c];if(void 0!==d.numMorphTargets)for(var e=0,f=d.numMorphTargets;e<f;e++)j.deleteBuffer(d.__webglMorphTargetsBuffers[e]);if(void 0!==d.numMorphNormals){e=0;for(f=d.numMorphNormals;e<f;e++)j.deleteBuffer(d.__webglMorphNormalsBuffers[e])}b(d)}b(a);L.info.memory.geometries--},Zc=function(a){a=a.target;a.removeEventListener("dispose",Zc);a.image&&a.image.__webglTextureCube?j.deleteTexture(a.image.__webglTextureCube):a.__webglInit&&
-(a.__webglInit=!1,j.deleteTexture(a.__webglTexture));L.info.memory.textures--},Jc=function(a){a=a.target;a.removeEventListener("dispose",Jc);if(a&&a.__webglTexture)if(j.deleteTexture(a.__webglTexture),a instanceof THREE.WebGLRenderTargetCube)for(var b=0;6>b;b++)j.deleteFramebuffer(a.__webglFramebuffer[b]),j.deleteRenderbuffer(a.__webglRenderbuffer[b]);else j.deleteFramebuffer(a.__webglFramebuffer),j.deleteRenderbuffer(a.__webglRenderbuffer);L.info.memory.textures--},Xc=function(a){a=a.target;a.removeEventListener("dispose",
-Xc);Yc(a)},Yc=function(a){var b=a.program;if(void 0!==b){a.program=void 0;var c,d,e=!1,a=0;for(c=ca.length;a<c;a++)if(d=ca[a],d.program===b){d.usedTimes--;0===d.usedTimes&&(e=!0);break}if(!0===e){e=[];a=0;for(c=ca.length;a<c;a++)d=ca[a],d.program!==b&&e.push(d);ca=e;j.deleteProgram(b);L.info.memory.programs--}}};this.renderBufferImmediate=function(a,b,c){a.hasPositions&&!a.__webglVertexBuffer&&(a.__webglVertexBuffer=j.createBuffer());a.hasNormals&&!a.__webglNormalBuffer&&(a.__webglNormalBuffer=j.createBuffer());
-a.hasUvs&&!a.__webglUvBuffer&&(a.__webglUvBuffer=j.createBuffer());a.hasColors&&!a.__webglColorBuffer&&(a.__webglColorBuffer=j.createBuffer());a.hasPositions&&(j.bindBuffer(j.ARRAY_BUFFER,a.__webglVertexBuffer),j.bufferData(j.ARRAY_BUFFER,a.positionArray,j.DYNAMIC_DRAW),j.enableVertexAttribArray(b.attributes.position),j.vertexAttribPointer(b.attributes.position,3,j.FLOAT,!1,0,0));if(a.hasNormals){j.bindBuffer(j.ARRAY_BUFFER,a.__webglNormalBuffer);if(c.shading===THREE.FlatShading){var d,e,f,g,i,h,
-k,l,m,n,p,q=3*a.count;for(p=0;p<q;p+=9)n=a.normalArray,d=n[p],e=n[p+1],f=n[p+2],g=n[p+3],h=n[p+4],l=n[p+5],i=n[p+6],k=n[p+7],m=n[p+8],d=(d+g+i)/3,e=(e+h+k)/3,f=(f+l+m)/3,n[p]=d,n[p+1]=e,n[p+2]=f,n[p+3]=d,n[p+4]=e,n[p+5]=f,n[p+6]=d,n[p+7]=e,n[p+8]=f}j.bufferData(j.ARRAY_BUFFER,a.normalArray,j.DYNAMIC_DRAW);j.enableVertexAttribArray(b.attributes.normal);j.vertexAttribPointer(b.attributes.normal,3,j.FLOAT,!1,0,0)}a.hasUvs&&c.map&&(j.bindBuffer(j.ARRAY_BUFFER,a.__webglUvBuffer),j.bufferData(j.ARRAY_BUFFER,
-a.uvArray,j.DYNAMIC_DRAW),j.enableVertexAttribArray(b.attributes.uv),j.vertexAttribPointer(b.attributes.uv,2,j.FLOAT,!1,0,0));a.hasColors&&c.vertexColors!==THREE.NoColors&&(j.bindBuffer(j.ARRAY_BUFFER,a.__webglColorBuffer),j.bufferData(j.ARRAY_BUFFER,a.colorArray,j.DYNAMIC_DRAW),j.enableVertexAttribArray(b.attributes.color),j.vertexAttribPointer(b.attributes.color,3,j.FLOAT,!1,0,0));j.drawArrays(j.TRIANGLES,0,a.count);a.count=0};this.renderBufferDirect=function(a,b,c,d,e,f){if(!1!==d.visible){var g,
-k,l;g=z(a,b,c,d,f);a=g.attributes;b=e.attributes;c=!1;g=16777215*e.id+2*g.id+(d.wireframe?1:0);g!==db&&(db=g,c=!0);c&&i();if(f instanceof THREE.Mesh)if(d=b.index){e=e.offsets;1<e.length&&(c=!0);for(var m=0,n=e.length;m<n;m++){var p=e[m].index;if(c){for(k in b)"index"!==k&&(g=a[k],f=b[k],l=f.itemSize,0<=g&&(j.bindBuffer(j.ARRAY_BUFFER,f.buffer),h(g),j.vertexAttribPointer(g,l,j.FLOAT,!1,0,4*p*l)));j.bindBuffer(j.ELEMENT_ARRAY_BUFFER,d.buffer)}j.drawElements(j.TRIANGLES,e[m].count,j.UNSIGNED_SHORT,2*
-e[m].start);L.info.render.calls++;L.info.render.vertices+=e[m].count;L.info.render.faces+=e[m].count/3}}else{if(c)for(k in b)"index"!==k&&(g=a[k],f=b[k],l=f.itemSize,0<=g&&(j.bindBuffer(j.ARRAY_BUFFER,f.buffer),h(g),j.vertexAttribPointer(g,l,j.FLOAT,!1,0,0)));k=e.attributes.position;j.drawArrays(j.TRIANGLES,0,k.numItems/3);L.info.render.calls++;L.info.render.vertices+=k.numItems/3;L.info.render.faces+=k.numItems/3/3}else if(f instanceof THREE.ParticleSystem){if(c){for(k in b)g=a[k],f=b[k],l=f.itemSize,
-0<=g&&(j.bindBuffer(j.ARRAY_BUFFER,f.buffer),h(g),j.vertexAttribPointer(g,l,j.FLOAT,!1,0,0));k=b.position;j.drawArrays(j.POINTS,0,k.numItems/3);L.info.render.calls++;L.info.render.points+=k.numItems/3}}else if(f instanceof THREE.Line&&c){for(k in b)g=a[k],f=b[k],l=f.itemSize,0<=g&&(j.bindBuffer(j.ARRAY_BUFFER,f.buffer),h(g),j.vertexAttribPointer(g,l,j.FLOAT,!1,0,0));w(d.linewidth);k=b.position;j.drawArrays(j.LINE_STRIP,0,k.numItems/3);L.info.render.calls++;L.info.render.points+=k.numItems}}};this.renderBuffer=
-function(a,b,c,d,e,f){if(!1!==d.visible){var g,k,c=z(a,b,c,d,f),a=c.attributes,b=!1,c=16777215*e.id+2*c.id+(d.wireframe?1:0);c!==db&&(db=c,b=!0);b&&i();if(!d.morphTargets&&0<=a.position)b&&(j.bindBuffer(j.ARRAY_BUFFER,e.__webglVertexBuffer),h(a.position),j.vertexAttribPointer(a.position,3,j.FLOAT,!1,0,0));else if(f.morphTargetBase){c=d.program.attributes;-1!==f.morphTargetBase&&0<=c.position?(j.bindBuffer(j.ARRAY_BUFFER,e.__webglMorphTargetsBuffers[f.morphTargetBase]),h(c.position),j.vertexAttribPointer(c.position,
-3,j.FLOAT,!1,0,0)):0<=c.position&&(j.bindBuffer(j.ARRAY_BUFFER,e.__webglVertexBuffer),h(c.position),j.vertexAttribPointer(c.position,3,j.FLOAT,!1,0,0));if(f.morphTargetForcedOrder.length){var m=0;k=f.morphTargetForcedOrder;for(g=f.morphTargetInfluences;m<d.numSupportedMorphTargets&&m<k.length;)0<=c["morphTarget"+m]&&(j.bindBuffer(j.ARRAY_BUFFER,e.__webglMorphTargetsBuffers[k[m]]),h(c["morphTarget"+m]),j.vertexAttribPointer(c["morphTarget"+m],3,j.FLOAT,!1,0,0)),0<=c["morphNormal"+m]&&d.morphNormals&&
-(j.bindBuffer(j.ARRAY_BUFFER,e.__webglMorphNormalsBuffers[k[m]]),h(c["morphNormal"+m]),j.vertexAttribPointer(c["morphNormal"+m],3,j.FLOAT,!1,0,0)),f.__webglMorphTargetInfluences[m]=g[k[m]],m++}else{k=[];g=f.morphTargetInfluences;var n,p=g.length;for(n=0;n<p;n++)m=g[n],0<m&&k.push([m,n]);k.length>d.numSupportedMorphTargets?(k.sort(l),k.length=d.numSupportedMorphTargets):k.length>d.numSupportedMorphNormals?k.sort(l):0===k.length&&k.push([0,0]);for(m=0;m<d.numSupportedMorphTargets;)k[m]?(n=k[m][1],0<=
-c["morphTarget"+m]&&(j.bindBuffer(j.ARRAY_BUFFER,e.__webglMorphTargetsBuffers[n]),h(c["morphTarget"+m]),j.vertexAttribPointer(c["morphTarget"+m],3,j.FLOAT,!1,0,0)),0<=c["morphNormal"+m]&&d.morphNormals&&(j.bindBuffer(j.ARRAY_BUFFER,e.__webglMorphNormalsBuffers[n]),h(c["morphNormal"+m]),j.vertexAttribPointer(c["morphNormal"+m],3,j.FLOAT,!1,0,0)),f.__webglMorphTargetInfluences[m]=g[n]):f.__webglMorphTargetInfluences[m]=0,m++}null!==d.program.uniforms.morphTargetInfluences&&j.uniform1fv(d.program.uniforms.morphTargetInfluences,
-f.__webglMorphTargetInfluences)}if(b){if(e.__webglCustomAttributesList){g=0;for(k=e.__webglCustomAttributesList.length;g<k;g++)c=e.__webglCustomAttributesList[g],0<=a[c.buffer.belongsToAttribute]&&(j.bindBuffer(j.ARRAY_BUFFER,c.buffer),h(a[c.buffer.belongsToAttribute]),j.vertexAttribPointer(a[c.buffer.belongsToAttribute],c.size,j.FLOAT,!1,0,0))}0<=a.color&&(j.bindBuffer(j.ARRAY_BUFFER,e.__webglColorBuffer),h(a.color),j.vertexAttribPointer(a.color,3,j.FLOAT,!1,0,0));0<=a.normal&&(j.bindBuffer(j.ARRAY_BUFFER,
-e.__webglNormalBuffer),h(a.normal),j.vertexAttribPointer(a.normal,3,j.FLOAT,!1,0,0));0<=a.tangent&&(j.bindBuffer(j.ARRAY_BUFFER,e.__webglTangentBuffer),h(a.tangent),j.vertexAttribPointer(a.tangent,4,j.FLOAT,!1,0,0));0<=a.uv&&(j.bindBuffer(j.ARRAY_BUFFER,e.__webglUVBuffer),h(a.uv),j.vertexAttribPointer(a.uv,2,j.FLOAT,!1,0,0));0<=a.uv2&&(j.bindBuffer(j.ARRAY_BUFFER,e.__webglUV2Buffer),h(a.uv2),j.vertexAttribPointer(a.uv2,2,j.FLOAT,!1,0,0));d.skinning&&(0<=a.skinIndex&&0<=a.skinWeight)&&(j.bindBuffer(j.ARRAY_BUFFER,
-e.__webglSkinIndicesBuffer),h(a.skinIndex),j.vertexAttribPointer(a.skinIndex,4,j.FLOAT,!1,0,0),j.bindBuffer(j.ARRAY_BUFFER,e.__webglSkinWeightsBuffer),h(a.skinWeight),j.vertexAttribPointer(a.skinWeight,4,j.FLOAT,!1,0,0));0<=a.lineDistance&&(j.bindBuffer(j.ARRAY_BUFFER,e.__webglLineDistanceBuffer),h(a.lineDistance),j.vertexAttribPointer(a.lineDistance,1,j.FLOAT,!1,0,0))}f instanceof THREE.Mesh?(d.wireframe?(w(d.wireframeLinewidth),b&&j.bindBuffer(j.ELEMENT_ARRAY_BUFFER,e.__webglLineBuffer),j.drawElements(j.LINES,
-e.__webglLineCount,j.UNSIGNED_SHORT,0)):(b&&j.bindBuffer(j.ELEMENT_ARRAY_BUFFER,e.__webglFaceBuffer),j.drawElements(j.TRIANGLES,e.__webglFaceCount,j.UNSIGNED_SHORT,0)),L.info.render.calls++,L.info.render.vertices+=e.__webglFaceCount,L.info.render.faces+=e.__webglFaceCount/3):f instanceof THREE.Line?(f=f.type===THREE.LineStrip?j.LINE_STRIP:j.LINES,w(d.linewidth),j.drawArrays(f,0,e.__webglLineCount),L.info.render.calls++):f instanceof THREE.ParticleSystem?(j.drawArrays(j.POINTS,0,e.__webglParticleCount),
-L.info.render.calls++,L.info.render.points+=e.__webglParticleCount):f instanceof THREE.Ribbon&&(j.drawArrays(j.TRIANGLE_STRIP,0,e.__webglVertexCount),L.info.render.calls++)}};this.render=function(a,b,c,d){if(!1===b instanceof THREE.Camera)console.error("THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.");else{var e,f,g,i,h=a.__lights,l=a.fog;lb=-1;yb=!0;this.autoUpdateScene&&a.updateMatrixWorld();void 0===b.parent&&b.updateMatrixWorld();b.matrixWorldInverse.getInverse(b.matrixWorld);
-Qa.multiplyMatrices(b.projectionMatrix,b.matrixWorldInverse);Hb.setFromMatrix(Qa);this.autoUpdateObjects&&this.initWebGLObjects(a);n(this.renderPluginsPre,a,b);L.info.render.calls=0;L.info.render.vertices=0;L.info.render.faces=0;L.info.render.points=0;this.setRenderTarget(c);(this.autoClear||d)&&this.clear(this.autoClearColor,this.autoClearDepth,this.autoClearStencil);i=a.__webglObjects;d=0;for(e=i.length;d<e;d++)if(f=i[d],g=f.object,f.render=!1,g.visible&&(!(g instanceof THREE.Mesh||g instanceof
-THREE.ParticleSystem)||!g.frustumCulled||Hb.intersectsObject(g))){C(g,b);var p=f,q=p.buffer,r=void 0,s=r=void 0,s=p.object.material;if(s instanceof THREE.MeshFaceMaterial)r=q.materialIndex,r=s.materials[r],r.transparent?(p.transparent=r,p.opaque=null):(p.opaque=r,p.transparent=null);else if(r=s)r.transparent?(p.transparent=r,p.opaque=null):(p.opaque=r,p.transparent=null);f.render=!0;!0===this.sortObjects&&(null!==g.renderDepth?f.z=g.renderDepth:(wa.getPositionFromMatrix(g.matrixWorld),wa.applyProjection(Qa),
-f.z=wa.z),f.id=g.id)}this.sortObjects&&i.sort(k);i=a.__webglObjectsImmediate;d=0;for(e=i.length;d<e;d++)f=i[d],g=f.object,g.visible&&(C(g,b),g=f.object.material,g.transparent?(f.transparent=g,f.opaque=null):(f.opaque=g,f.transparent=null));a.overrideMaterial?(d=a.overrideMaterial,this.setBlending(d.blending,d.blendEquation,d.blendSrc,d.blendDst),this.setDepthTest(d.depthTest),this.setDepthWrite(d.depthWrite),I(d.polygonOffset,d.polygonOffsetFactor,d.polygonOffsetUnits),m(a.__webglObjects,!1,"",b,
-h,l,!0,d),t(a.__webglObjectsImmediate,"",b,h,l,!1,d)):(d=null,this.setBlending(THREE.NoBlending),m(a.__webglObjects,!0,"opaque",b,h,l,!1,d),t(a.__webglObjectsImmediate,"opaque",b,h,l,!1,d),m(a.__webglObjects,!1,"transparent",b,h,l,!0,d),t(a.__webglObjectsImmediate,"transparent",b,h,l,!0,d));n(this.renderPluginsPost,a,b);c&&(c.generateMipmaps&&c.minFilter!==THREE.NearestFilter&&c.minFilter!==THREE.LinearFilter)&&(c instanceof THREE.WebGLRenderTargetCube?(j.bindTexture(j.TEXTURE_CUBE_MAP,c.__webglTexture),
-j.generateMipmap(j.TEXTURE_CUBE_MAP),j.bindTexture(j.TEXTURE_CUBE_MAP,null)):(j.bindTexture(j.TEXTURE_2D,c.__webglTexture),j.generateMipmap(j.TEXTURE_2D),j.bindTexture(j.TEXTURE_2D,null)));this.setDepthTest(!0);this.setDepthWrite(!0)}};this.renderImmediateObject=function(a,b,c,d,e){var f=z(a,b,c,d,e);db=-1;L.setMaterialFaces(d);e.immediateRenderCallback?e.immediateRenderCallback(f,j,Hb):e.render(function(a){L.renderBufferImmediate(a,f,d)})};this.initWebGLObjects=function(a){a.__webglObjects||(a.__webglObjects=
-[],a.__webglObjectsImmediate=[],a.__webglSprites=[],a.__webglFlares=[]);for(;a.__objectsAdded.length;){var b=a.__objectsAdded[0],i=a,h=void 0,k=void 0,m=void 0,n=void 0;if(!b.__webglInit&&(b.__webglInit=!0,b._modelViewMatrix=new THREE.Matrix4,b._normalMatrix=new THREE.Matrix3,void 0!==b.geometry&&void 0===b.geometry.__webglInit&&(b.geometry.__webglInit=!0,b.geometry.addEventListener("dispose",Bd)),k=b.geometry,void 0!==k))if(k instanceof THREE.BufferGeometry){var t=k,s=void 0,w=void 0,z=void 0;for(s in t.attributes)z=
-"index"===s?j.ELEMENT_ARRAY_BUFFER:j.ARRAY_BUFFER,w=t.attributes[s],w.buffer=j.createBuffer(),j.bindBuffer(z,w.buffer),j.bufferData(z,w.array,j.STATIC_DRAW)}else if(b instanceof THREE.Mesh){m=b.material;if(void 0===k.geometryGroups){var A=k,B=void 0,C=void 0,F=void 0,E=void 0,H=void 0,G=void 0,I={},J=A.morphTargets.length,K=A.morphNormals.length,M=m instanceof THREE.MeshFaceMaterial;A.geometryGroups={};B=0;for(C=A.faces.length;B<C;B++)F=A.faces[B],E=M?F.materialIndex:0,void 0===I[E]&&(I[E]={hash:E,
-counter:0}),G=I[E].hash+"_"+I[E].counter,void 0===A.geometryGroups[G]&&(A.geometryGroups[G]={faces3:[],faces4:[],materialIndex:E,vertices:0,numMorphTargets:J,numMorphNormals:K}),H=F instanceof THREE.Face3?3:4,65535<A.geometryGroups[G].vertices+H&&(I[E].counter+=1,G=I[E].hash+"_"+I[E].counter,void 0===A.geometryGroups[G]&&(A.geometryGroups[G]={faces3:[],faces4:[],materialIndex:E,vertices:0,numMorphTargets:J,numMorphNormals:K})),F instanceof THREE.Face3?A.geometryGroups[G].faces3.push(B):A.geometryGroups[G].faces4.push(B),
-A.geometryGroups[G].vertices+=H;A.geometryGroupsList=[];var V=void 0;for(V in A.geometryGroups)A.geometryGroups[V].id=Oa++,A.geometryGroupsList.push(A.geometryGroups[V])}for(h in k.geometryGroups)if(n=k.geometryGroups[h],!n.__webglVertexBuffer){var N=n;N.__webglVertexBuffer=j.createBuffer();N.__webglNormalBuffer=j.createBuffer();N.__webglTangentBuffer=j.createBuffer();N.__webglColorBuffer=j.createBuffer();N.__webglUVBuffer=j.createBuffer();N.__webglUV2Buffer=j.createBuffer();N.__webglSkinIndicesBuffer=
-j.createBuffer();N.__webglSkinWeightsBuffer=j.createBuffer();N.__webglFaceBuffer=j.createBuffer();N.__webglLineBuffer=j.createBuffer();var ra=void 0,U=void 0;if(N.numMorphTargets){N.__webglMorphTargetsBuffers=[];ra=0;for(U=N.numMorphTargets;ra<U;ra++)N.__webglMorphTargetsBuffers.push(j.createBuffer())}if(N.numMorphNormals){N.__webglMorphNormalsBuffers=[];ra=0;for(U=N.numMorphNormals;ra<U;ra++)N.__webglMorphNormalsBuffers.push(j.createBuffer())}L.info.memory.geometries++;d(n,b);k.verticesNeedUpdate=
-!0;k.morphTargetsNeedUpdate=!0;k.elementsNeedUpdate=!0;k.uvsNeedUpdate=!0;k.normalsNeedUpdate=!0;k.tangentsNeedUpdate=!0;k.colorsNeedUpdate=!0}}else if(b instanceof THREE.Ribbon){if(!k.__webglVertexBuffer){var ea=k;ea.__webglVertexBuffer=j.createBuffer();ea.__webglColorBuffer=j.createBuffer();ea.__webglNormalBuffer=j.createBuffer();L.info.memory.geometries++;var T=k,$=b,ha=T.vertices.length;T.__vertexArray=new Float32Array(3*ha);T.__colorArray=new Float32Array(3*ha);T.__normalArray=new Float32Array(3*
-ha);T.__webglVertexCount=ha;c(T,$);k.verticesNeedUpdate=!0;k.colorsNeedUpdate=!0;k.normalsNeedUpdate=!0}}else if(b instanceof THREE.Line){if(!k.__webglVertexBuffer){var Z=k;Z.__webglVertexBuffer=j.createBuffer();Z.__webglColorBuffer=j.createBuffer();Z.__webglLineDistanceBuffer=j.createBuffer();L.info.memory.geometries++;var Y=k,ca=b,fa=Y.vertices.length;Y.__vertexArray=new Float32Array(3*fa);Y.__colorArray=new Float32Array(3*fa);Y.__lineDistanceArray=new Float32Array(1*fa);Y.__webglLineCount=fa;c(Y,
-ca);k.verticesNeedUpdate=!0;k.colorsNeedUpdate=!0;k.lineDistancesNeedUpdate=!0}}else if(b instanceof THREE.ParticleSystem&&!k.__webglVertexBuffer){var $a=k;$a.__webglVertexBuffer=j.createBuffer();$a.__webglColorBuffer=j.createBuffer();L.info.memory.geometries++;var ia=k,kb=b,sa=ia.vertices.length;ia.__vertexArray=new Float32Array(3*sa);ia.__colorArray=new Float32Array(3*sa);ia.__sortArray=[];ia.__webglParticleCount=sa;c(ia,kb);k.verticesNeedUpdate=!0;k.colorsNeedUpdate=!0}if(!b.__webglActive){if(b instanceof
-THREE.Mesh)if(k=b.geometry,k instanceof THREE.BufferGeometry)r(i.__webglObjects,k,b);else{if(k instanceof THREE.Geometry)for(h in k.geometryGroups)n=k.geometryGroups[h],r(i.__webglObjects,n,b)}else b instanceof THREE.Ribbon||b instanceof THREE.Line||b instanceof THREE.ParticleSystem?(k=b.geometry,r(i.__webglObjects,k,b)):b instanceof THREE.ImmediateRenderObject||b.immediateRenderCallback?i.__webglObjectsImmediate.push({object:b,opaque:null,transparent:null}):b instanceof THREE.Sprite?i.__webglSprites.push(b):
-b instanceof THREE.LensFlare&&i.__webglFlares.push(b);b.__webglActive=!0}a.__objectsAdded.splice(0,1)}for(;a.__objectsRemoved.length;){var ja=a.__objectsRemoved[0],La=a;ja instanceof THREE.Mesh||ja instanceof THREE.ParticleSystem||ja instanceof THREE.Ribbon||ja instanceof THREE.Line?y(La.__webglObjects,ja):ja instanceof THREE.Sprite?v(La.__webglSprites,ja):ja instanceof THREE.LensFlare?v(La.__webglFlares,ja):(ja instanceof THREE.ImmediateRenderObject||ja.immediateRenderCallback)&&y(La.__webglObjectsImmediate,
-ja);ja.__webglActive=!1;a.__objectsRemoved.splice(0,1)}for(var lb=0,db=a.__webglObjects.length;lb<db;lb++){var ma=a.__webglObjects[lb].object,la=ma.geometry,Ba=void 0,xa=void 0,na=void 0;if(la instanceof THREE.BufferGeometry){var Sa=j.DYNAMIC_DRAW,Wa=!la.dynamic,eb=la.attributes,fb=void 0,Pa=void 0;for(fb in eb)Pa=eb[fb],Pa.needsUpdate&&("index"===fb?(j.bindBuffer(j.ELEMENT_ARRAY_BUFFER,Pa.buffer),j.bufferData(j.ELEMENT_ARRAY_BUFFER,Pa.array,Sa)):(j.bindBuffer(j.ARRAY_BUFFER,Pa.buffer),j.bufferData(j.ARRAY_BUFFER,
-Pa.array,Sa)),Pa.needsUpdate=!1),Wa&&!Pa.dynamic&&delete Pa.array}else if(ma instanceof THREE.Mesh){for(var jb=0,ob=la.geometryGroupsList.length;jb<ob;jb++)if(Ba=la.geometryGroupsList[jb],na=e(ma,Ba),la.buffersNeedUpdate&&d(Ba,ma),xa=na.attributes&&p(na),la.verticesNeedUpdate||la.morphTargetsNeedUpdate||la.elementsNeedUpdate||la.uvsNeedUpdate||la.normalsNeedUpdate||la.colorsNeedUpdate||la.tangentsNeedUpdate||xa){var ta=Ba,pb=ma,Ga=j.DYNAMIC_DRAW,Hb=!la.dynamic,mb=na;if(ta.__inittedArrays){var Gb=
-f(mb),yb=mb.vertexColors?mb.vertexColors:!1,Ib=g(mb),xb=Gb===THREE.SmoothShading,D=void 0,S=void 0,pc=void 0,O=void 0,vb=void 0,qc=void 0,Pb=void 0,Mb=void 0,jc=void 0,wb=void 0,zb=void 0,P=void 0,Q=void 0,R=void 0,qa=void 0,Qb=void 0,Rb=void 0,Sb=void 0,Nb=void 0,Tb=void 0,Ub=void 0,Vb=void 0,Ob=void 0,Wb=void 0,Xb=void 0,Yb=void 0,Kc=void 0,Zb=void 0,$b=void 0,ac=void 0,Lc=void 0,bc=void 0,cc=void 0,dc=void 0,Mc=void 0,ya=void 0,Bc=void 0,rc=void 0,Ec=void 0,Fc=void 0,Xa=void 0,Cc=void 0,Ta=void 0,
-Ua=void 0,sc=void 0,kc=void 0,Ma=0,Ra=0,lc=0,mc=0,Cb=0,hb=0,Ca=0,nb=0,Na=0,aa=0,ka=0,x=0,za=void 0,Ya=ta.__vertexArray,Nc=ta.__uvArray,Oc=ta.__uv2Array,Db=ta.__normalArray,Ha=ta.__tangentArray,Za=ta.__colorArray,Ia=ta.__skinIndexArray,Ja=ta.__skinWeightArray,rd=ta.__morphTargetsArrays,sd=ta.__morphNormalsArrays,td=ta.__webglCustomAttributesList,u=void 0,ec=ta.__faceArray,ub=ta.__lineArray,qb=pb.geometry,Wc=qb.elementsNeedUpdate,Jc=qb.uvsNeedUpdate,Xc=qb.normalsNeedUpdate,Yc=qb.tangentsNeedUpdate,
-Zc=qb.colorsNeedUpdate,pd=qb.morphTargetsNeedUpdate,xc=qb.vertices,ua=ta.faces3,va=ta.faces4,ib=qb.faces,ud=qb.faceVertexUvs[0],vd=qb.faceVertexUvs[1],yc=qb.skinIndices,tc=qb.skinWeights,uc=qb.morphTargets,$c=qb.morphNormals;if(qb.verticesNeedUpdate){D=0;for(S=ua.length;D<S;D++)O=ib[ua[D]],P=xc[O.a],Q=xc[O.b],R=xc[O.c],Ya[Ra]=P.x,Ya[Ra+1]=P.y,Ya[Ra+2]=P.z,Ya[Ra+3]=Q.x,Ya[Ra+4]=Q.y,Ya[Ra+5]=Q.z,Ya[Ra+6]=R.x,Ya[Ra+7]=R.y,Ya[Ra+8]=R.z,Ra+=9;D=0;for(S=va.length;D<S;D++)O=ib[va[D]],P=xc[O.a],Q=xc[O.b],
-R=xc[O.c],qa=xc[O.d],Ya[Ra]=P.x,Ya[Ra+1]=P.y,Ya[Ra+2]=P.z,Ya[Ra+3]=Q.x,Ya[Ra+4]=Q.y,Ya[Ra+5]=Q.z,Ya[Ra+6]=R.x,Ya[Ra+7]=R.y,Ya[Ra+8]=R.z,Ya[Ra+9]=qa.x,Ya[Ra+10]=qa.y,Ya[Ra+11]=qa.z,Ra+=12;j.bindBuffer(j.ARRAY_BUFFER,ta.__webglVertexBuffer);j.bufferData(j.ARRAY_BUFFER,Ya,Ga)}if(pd){Xa=0;for(Cc=uc.length;Xa<Cc;Xa++){D=ka=0;for(S=ua.length;D<S;D++)sc=ua[D],O=ib[sc],P=uc[Xa].vertices[O.a],Q=uc[Xa].vertices[O.b],R=uc[Xa].vertices[O.c],Ta=rd[Xa],Ta[ka]=P.x,Ta[ka+1]=P.y,Ta[ka+2]=P.z,Ta[ka+3]=Q.x,Ta[ka+4]=
-Q.y,Ta[ka+5]=Q.z,Ta[ka+6]=R.x,Ta[ka+7]=R.y,Ta[ka+8]=R.z,mb.morphNormals&&(xb?(kc=$c[Xa].vertexNormals[sc],Tb=kc.a,Ub=kc.b,Vb=kc.c):Vb=Ub=Tb=$c[Xa].faceNormals[sc],Ua=sd[Xa],Ua[ka]=Tb.x,Ua[ka+1]=Tb.y,Ua[ka+2]=Tb.z,Ua[ka+3]=Ub.x,Ua[ka+4]=Ub.y,Ua[ka+5]=Ub.z,Ua[ka+6]=Vb.x,Ua[ka+7]=Vb.y,Ua[ka+8]=Vb.z),ka+=9;D=0;for(S=va.length;D<S;D++)sc=va[D],O=ib[sc],P=uc[Xa].vertices[O.a],Q=uc[Xa].vertices[O.b],R=uc[Xa].vertices[O.c],qa=uc[Xa].vertices[O.d],Ta=rd[Xa],Ta[ka]=P.x,Ta[ka+1]=P.y,Ta[ka+2]=P.z,Ta[ka+3]=Q.x,
-Ta[ka+4]=Q.y,Ta[ka+5]=Q.z,Ta[ka+6]=R.x,Ta[ka+7]=R.y,Ta[ka+8]=R.z,Ta[ka+9]=qa.x,Ta[ka+10]=qa.y,Ta[ka+11]=qa.z,mb.morphNormals&&(xb?(kc=$c[Xa].vertexNormals[sc],Tb=kc.a,Ub=kc.b,Vb=kc.c,Ob=kc.d):Ob=Vb=Ub=Tb=$c[Xa].faceNormals[sc],Ua=sd[Xa],Ua[ka]=Tb.x,Ua[ka+1]=Tb.y,Ua[ka+2]=Tb.z,Ua[ka+3]=Ub.x,Ua[ka+4]=Ub.y,Ua[ka+5]=Ub.z,Ua[ka+6]=Vb.x,Ua[ka+7]=Vb.y,Ua[ka+8]=Vb.z,Ua[ka+9]=Ob.x,Ua[ka+10]=Ob.y,Ua[ka+11]=Ob.z),ka+=12;j.bindBuffer(j.ARRAY_BUFFER,ta.__webglMorphTargetsBuffers[Xa]);j.bufferData(j.ARRAY_BUFFER,
-rd[Xa],Ga);mb.morphNormals&&(j.bindBuffer(j.ARRAY_BUFFER,ta.__webglMorphNormalsBuffers[Xa]),j.bufferData(j.ARRAY_BUFFER,sd[Xa],Ga))}}if(tc.length){D=0;for(S=ua.length;D<S;D++)O=ib[ua[D]],Zb=tc[O.a],$b=tc[O.b],ac=tc[O.c],Ja[aa]=Zb.x,Ja[aa+1]=Zb.y,Ja[aa+2]=Zb.z,Ja[aa+3]=Zb.w,Ja[aa+4]=$b.x,Ja[aa+5]=$b.y,Ja[aa+6]=$b.z,Ja[aa+7]=$b.w,Ja[aa+8]=ac.x,Ja[aa+9]=ac.y,Ja[aa+10]=ac.z,Ja[aa+11]=ac.w,bc=yc[O.a],cc=yc[O.b],dc=yc[O.c],Ia[aa]=bc.x,Ia[aa+1]=bc.y,Ia[aa+2]=bc.z,Ia[aa+3]=bc.w,Ia[aa+4]=cc.x,Ia[aa+5]=cc.y,
-Ia[aa+6]=cc.z,Ia[aa+7]=cc.w,Ia[aa+8]=dc.x,Ia[aa+9]=dc.y,Ia[aa+10]=dc.z,Ia[aa+11]=dc.w,aa+=12;D=0;for(S=va.length;D<S;D++)O=ib[va[D]],Zb=tc[O.a],$b=tc[O.b],ac=tc[O.c],Lc=tc[O.d],Ja[aa]=Zb.x,Ja[aa+1]=Zb.y,Ja[aa+2]=Zb.z,Ja[aa+3]=Zb.w,Ja[aa+4]=$b.x,Ja[aa+5]=$b.y,Ja[aa+6]=$b.z,Ja[aa+7]=$b.w,Ja[aa+8]=ac.x,Ja[aa+9]=ac.y,Ja[aa+10]=ac.z,Ja[aa+11]=ac.w,Ja[aa+12]=Lc.x,Ja[aa+13]=Lc.y,Ja[aa+14]=Lc.z,Ja[aa+15]=Lc.w,bc=yc[O.a],cc=yc[O.b],dc=yc[O.c],Mc=yc[O.d],Ia[aa]=bc.x,Ia[aa+1]=bc.y,Ia[aa+2]=bc.z,Ia[aa+3]=bc.w,
-Ia[aa+4]=cc.x,Ia[aa+5]=cc.y,Ia[aa+6]=cc.z,Ia[aa+7]=cc.w,Ia[aa+8]=dc.x,Ia[aa+9]=dc.y,Ia[aa+10]=dc.z,Ia[aa+11]=dc.w,Ia[aa+12]=Mc.x,Ia[aa+13]=Mc.y,Ia[aa+14]=Mc.z,Ia[aa+15]=Mc.w,aa+=16;0<aa&&(j.bindBuffer(j.ARRAY_BUFFER,ta.__webglSkinIndicesBuffer),j.bufferData(j.ARRAY_BUFFER,Ia,Ga),j.bindBuffer(j.ARRAY_BUFFER,ta.__webglSkinWeightsBuffer),j.bufferData(j.ARRAY_BUFFER,Ja,Ga))}if(Zc&&yb){D=0;for(S=ua.length;D<S;D++)O=ib[ua[D]],Pb=O.vertexColors,Mb=O.color,3===Pb.length&&yb===THREE.VertexColors?(Wb=Pb[0],
-Xb=Pb[1],Yb=Pb[2]):Yb=Xb=Wb=Mb,Za[Na]=Wb.r,Za[Na+1]=Wb.g,Za[Na+2]=Wb.b,Za[Na+3]=Xb.r,Za[Na+4]=Xb.g,Za[Na+5]=Xb.b,Za[Na+6]=Yb.r,Za[Na+7]=Yb.g,Za[Na+8]=Yb.b,Na+=9;D=0;for(S=va.length;D<S;D++)O=ib[va[D]],Pb=O.vertexColors,Mb=O.color,4===Pb.length&&yb===THREE.VertexColors?(Wb=Pb[0],Xb=Pb[1],Yb=Pb[2],Kc=Pb[3]):Kc=Yb=Xb=Wb=Mb,Za[Na]=Wb.r,Za[Na+1]=Wb.g,Za[Na+2]=Wb.b,Za[Na+3]=Xb.r,Za[Na+4]=Xb.g,Za[Na+5]=Xb.b,Za[Na+6]=Yb.r,Za[Na+7]=Yb.g,Za[Na+8]=Yb.b,Za[Na+9]=Kc.r,Za[Na+10]=Kc.g,Za[Na+11]=Kc.b,Na+=12;0<Na&&
-(j.bindBuffer(j.ARRAY_BUFFER,ta.__webglColorBuffer),j.bufferData(j.ARRAY_BUFFER,Za,Ga))}if(Yc&&qb.hasTangents){D=0;for(S=ua.length;D<S;D++)O=ib[ua[D]],jc=O.vertexTangents,Qb=jc[0],Rb=jc[1],Sb=jc[2],Ha[Ca]=Qb.x,Ha[Ca+1]=Qb.y,Ha[Ca+2]=Qb.z,Ha[Ca+3]=Qb.w,Ha[Ca+4]=Rb.x,Ha[Ca+5]=Rb.y,Ha[Ca+6]=Rb.z,Ha[Ca+7]=Rb.w,Ha[Ca+8]=Sb.x,Ha[Ca+9]=Sb.y,Ha[Ca+10]=Sb.z,Ha[Ca+11]=Sb.w,Ca+=12;D=0;for(S=va.length;D<S;D++)O=ib[va[D]],jc=O.vertexTangents,Qb=jc[0],Rb=jc[1],Sb=jc[2],Nb=jc[3],Ha[Ca]=Qb.x,Ha[Ca+1]=Qb.y,Ha[Ca+
-2]=Qb.z,Ha[Ca+3]=Qb.w,Ha[Ca+4]=Rb.x,Ha[Ca+5]=Rb.y,Ha[Ca+6]=Rb.z,Ha[Ca+7]=Rb.w,Ha[Ca+8]=Sb.x,Ha[Ca+9]=Sb.y,Ha[Ca+10]=Sb.z,Ha[Ca+11]=Sb.w,Ha[Ca+12]=Nb.x,Ha[Ca+13]=Nb.y,Ha[Ca+14]=Nb.z,Ha[Ca+15]=Nb.w,Ca+=16;j.bindBuffer(j.ARRAY_BUFFER,ta.__webglTangentBuffer);j.bufferData(j.ARRAY_BUFFER,Ha,Ga)}if(Xc&&Gb){D=0;for(S=ua.length;D<S;D++)if(O=ib[ua[D]],vb=O.vertexNormals,qc=O.normal,3===vb.length&&xb)for(ya=0;3>ya;ya++)rc=vb[ya],Db[hb]=rc.x,Db[hb+1]=rc.y,Db[hb+2]=rc.z,hb+=3;else for(ya=0;3>ya;ya++)Db[hb]=qc.x,
-Db[hb+1]=qc.y,Db[hb+2]=qc.z,hb+=3;D=0;for(S=va.length;D<S;D++)if(O=ib[va[D]],vb=O.vertexNormals,qc=O.normal,4===vb.length&&xb)for(ya=0;4>ya;ya++)rc=vb[ya],Db[hb]=rc.x,Db[hb+1]=rc.y,Db[hb+2]=rc.z,hb+=3;else for(ya=0;4>ya;ya++)Db[hb]=qc.x,Db[hb+1]=qc.y,Db[hb+2]=qc.z,hb+=3;j.bindBuffer(j.ARRAY_BUFFER,ta.__webglNormalBuffer);j.bufferData(j.ARRAY_BUFFER,Db,Ga)}if(Jc&&ud&&Ib){D=0;for(S=ua.length;D<S;D++)if(pc=ua[D],wb=ud[pc],void 0!==wb)for(ya=0;3>ya;ya++)Ec=wb[ya],Nc[lc]=Ec.x,Nc[lc+1]=Ec.y,lc+=2;D=0;for(S=
-va.length;D<S;D++)if(pc=va[D],wb=ud[pc],void 0!==wb)for(ya=0;4>ya;ya++)Ec=wb[ya],Nc[lc]=Ec.x,Nc[lc+1]=Ec.y,lc+=2;0<lc&&(j.bindBuffer(j.ARRAY_BUFFER,ta.__webglUVBuffer),j.bufferData(j.ARRAY_BUFFER,Nc,Ga))}if(Jc&&vd&&Ib){D=0;for(S=ua.length;D<S;D++)if(pc=ua[D],zb=vd[pc],void 0!==zb)for(ya=0;3>ya;ya++)Fc=zb[ya],Oc[mc]=Fc.x,Oc[mc+1]=Fc.y,mc+=2;D=0;for(S=va.length;D<S;D++)if(pc=va[D],zb=vd[pc],void 0!==zb)for(ya=0;4>ya;ya++)Fc=zb[ya],Oc[mc]=Fc.x,Oc[mc+1]=Fc.y,mc+=2;0<mc&&(j.bindBuffer(j.ARRAY_BUFFER,ta.__webglUV2Buffer),
-j.bufferData(j.ARRAY_BUFFER,Oc,Ga))}if(Wc){D=0;for(S=ua.length;D<S;D++)ec[Cb]=Ma,ec[Cb+1]=Ma+1,ec[Cb+2]=Ma+2,Cb+=3,ub[nb]=Ma,ub[nb+1]=Ma+1,ub[nb+2]=Ma,ub[nb+3]=Ma+2,ub[nb+4]=Ma+1,ub[nb+5]=Ma+2,nb+=6,Ma+=3;D=0;for(S=va.length;D<S;D++)ec[Cb]=Ma,ec[Cb+1]=Ma+1,ec[Cb+2]=Ma+3,ec[Cb+3]=Ma+1,ec[Cb+4]=Ma+2,ec[Cb+5]=Ma+3,Cb+=6,ub[nb]=Ma,ub[nb+1]=Ma+1,ub[nb+2]=Ma,ub[nb+3]=Ma+3,ub[nb+4]=Ma+1,ub[nb+5]=Ma+2,ub[nb+6]=Ma+2,ub[nb+7]=Ma+3,nb+=8,Ma+=4;j.bindBuffer(j.ELEMENT_ARRAY_BUFFER,ta.__webglFaceBuffer);j.bufferData(j.ELEMENT_ARRAY_BUFFER,
-ec,Ga);j.bindBuffer(j.ELEMENT_ARRAY_BUFFER,ta.__webglLineBuffer);j.bufferData(j.ELEMENT_ARRAY_BUFFER,ub,Ga)}if(td){ya=0;for(Bc=td.length;ya<Bc;ya++)if(u=td[ya],u.__original.needsUpdate){x=0;if(1===u.size)if(void 0===u.boundTo||"vertices"===u.boundTo){D=0;for(S=ua.length;D<S;D++)O=ib[ua[D]],u.array[x]=u.value[O.a],u.array[x+1]=u.value[O.b],u.array[x+2]=u.value[O.c],x+=3;D=0;for(S=va.length;D<S;D++)O=ib[va[D]],u.array[x]=u.value[O.a],u.array[x+1]=u.value[O.b],u.array[x+2]=u.value[O.c],u.array[x+3]=
-u.value[O.d],x+=4}else{if("faces"===u.boundTo){D=0;for(S=ua.length;D<S;D++)za=u.value[ua[D]],u.array[x]=za,u.array[x+1]=za,u.array[x+2]=za,x+=3;D=0;for(S=va.length;D<S;D++)za=u.value[va[D]],u.array[x]=za,u.array[x+1]=za,u.array[x+2]=za,u.array[x+3]=za,x+=4}}else if(2===u.size)if(void 0===u.boundTo||"vertices"===u.boundTo){D=0;for(S=ua.length;D<S;D++)O=ib[ua[D]],P=u.value[O.a],Q=u.value[O.b],R=u.value[O.c],u.array[x]=P.x,u.array[x+1]=P.y,u.array[x+2]=Q.x,u.array[x+3]=Q.y,u.array[x+4]=R.x,u.array[x+
-5]=R.y,x+=6;D=0;for(S=va.length;D<S;D++)O=ib[va[D]],P=u.value[O.a],Q=u.value[O.b],R=u.value[O.c],qa=u.value[O.d],u.array[x]=P.x,u.array[x+1]=P.y,u.array[x+2]=Q.x,u.array[x+3]=Q.y,u.array[x+4]=R.x,u.array[x+5]=R.y,u.array[x+6]=qa.x,u.array[x+7]=qa.y,x+=8}else{if("faces"===u.boundTo){D=0;for(S=ua.length;D<S;D++)R=Q=P=za=u.value[ua[D]],u.array[x]=P.x,u.array[x+1]=P.y,u.array[x+2]=Q.x,u.array[x+3]=Q.y,u.array[x+4]=R.x,u.array[x+5]=R.y,x+=6;D=0;for(S=va.length;D<S;D++)qa=R=Q=P=za=u.value[va[D]],u.array[x]=
-P.x,u.array[x+1]=P.y,u.array[x+2]=Q.x,u.array[x+3]=Q.y,u.array[x+4]=R.x,u.array[x+5]=R.y,u.array[x+6]=qa.x,u.array[x+7]=qa.y,x+=8}}else if(3===u.size){var X;X="c"===u.type?["r","g","b"]:["x","y","z"];if(void 0===u.boundTo||"vertices"===u.boundTo){D=0;for(S=ua.length;D<S;D++)O=ib[ua[D]],P=u.value[O.a],Q=u.value[O.b],R=u.value[O.c],u.array[x]=P[X[0]],u.array[x+1]=P[X[1]],u.array[x+2]=P[X[2]],u.array[x+3]=Q[X[0]],u.array[x+4]=Q[X[1]],u.array[x+5]=Q[X[2]],u.array[x+6]=R[X[0]],u.array[x+7]=R[X[1]],u.array[x+
-8]=R[X[2]],x+=9;D=0;for(S=va.length;D<S;D++)O=ib[va[D]],P=u.value[O.a],Q=u.value[O.b],R=u.value[O.c],qa=u.value[O.d],u.array[x]=P[X[0]],u.array[x+1]=P[X[1]],u.array[x+2]=P[X[2]],u.array[x+3]=Q[X[0]],u.array[x+4]=Q[X[1]],u.array[x+5]=Q[X[2]],u.array[x+6]=R[X[0]],u.array[x+7]=R[X[1]],u.array[x+8]=R[X[2]],u.array[x+9]=qa[X[0]],u.array[x+10]=qa[X[1]],u.array[x+11]=qa[X[2]],x+=12}else if("faces"===u.boundTo){D=0;for(S=ua.length;D<S;D++)R=Q=P=za=u.value[ua[D]],u.array[x]=P[X[0]],u.array[x+1]=P[X[1]],u.array[x+
-2]=P[X[2]],u.array[x+3]=Q[X[0]],u.array[x+4]=Q[X[1]],u.array[x+5]=Q[X[2]],u.array[x+6]=R[X[0]],u.array[x+7]=R[X[1]],u.array[x+8]=R[X[2]],x+=9;D=0;for(S=va.length;D<S;D++)qa=R=Q=P=za=u.value[va[D]],u.array[x]=P[X[0]],u.array[x+1]=P[X[1]],u.array[x+2]=P[X[2]],u.array[x+3]=Q[X[0]],u.array[x+4]=Q[X[1]],u.array[x+5]=Q[X[2]],u.array[x+6]=R[X[0]],u.array[x+7]=R[X[1]],u.array[x+8]=R[X[2]],u.array[x+9]=qa[X[0]],u.array[x+10]=qa[X[1]],u.array[x+11]=qa[X[2]],x+=12}else if("faceVertices"===u.boundTo){D=0;for(S=
-ua.length;D<S;D++)za=u.value[ua[D]],P=za[0],Q=za[1],R=za[2],u.array[x]=P[X[0]],u.array[x+1]=P[X[1]],u.array[x+2]=P[X[2]],u.array[x+3]=Q[X[0]],u.array[x+4]=Q[X[1]],u.array[x+5]=Q[X[2]],u.array[x+6]=R[X[0]],u.array[x+7]=R[X[1]],u.array[x+8]=R[X[2]],x+=9;D=0;for(S=va.length;D<S;D++)za=u.value[va[D]],P=za[0],Q=za[1],R=za[2],qa=za[3],u.array[x]=P[X[0]],u.array[x+1]=P[X[1]],u.array[x+2]=P[X[2]],u.array[x+3]=Q[X[0]],u.array[x+4]=Q[X[1]],u.array[x+5]=Q[X[2]],u.array[x+6]=R[X[0]],u.array[x+7]=R[X[1]],u.array[x+
-8]=R[X[2]],u.array[x+9]=qa[X[0]],u.array[x+10]=qa[X[1]],u.array[x+11]=qa[X[2]],x+=12}}else if(4===u.size)if(void 0===u.boundTo||"vertices"===u.boundTo){D=0;for(S=ua.length;D<S;D++)O=ib[ua[D]],P=u.value[O.a],Q=u.value[O.b],R=u.value[O.c],u.array[x]=P.x,u.array[x+1]=P.y,u.array[x+2]=P.z,u.array[x+3]=P.w,u.array[x+4]=Q.x,u.array[x+5]=Q.y,u.array[x+6]=Q.z,u.array[x+7]=Q.w,u.array[x+8]=R.x,u.array[x+9]=R.y,u.array[x+10]=R.z,u.array[x+11]=R.w,x+=12;D=0;for(S=va.length;D<S;D++)O=ib[va[D]],P=u.value[O.a],
-Q=u.value[O.b],R=u.value[O.c],qa=u.value[O.d],u.array[x]=P.x,u.array[x+1]=P.y,u.array[x+2]=P.z,u.array[x+3]=P.w,u.array[x+4]=Q.x,u.array[x+5]=Q.y,u.array[x+6]=Q.z,u.array[x+7]=Q.w,u.array[x+8]=R.x,u.array[x+9]=R.y,u.array[x+10]=R.z,u.array[x+11]=R.w,u.array[x+12]=qa.x,u.array[x+13]=qa.y,u.array[x+14]=qa.z,u.array[x+15]=qa.w,x+=16}else if("faces"===u.boundTo){D=0;for(S=ua.length;D<S;D++)R=Q=P=za=u.value[ua[D]],u.array[x]=P.x,u.array[x+1]=P.y,u.array[x+2]=P.z,u.array[x+3]=P.w,u.array[x+4]=Q.x,u.array[x+
-5]=Q.y,u.array[x+6]=Q.z,u.array[x+7]=Q.w,u.array[x+8]=R.x,u.array[x+9]=R.y,u.array[x+10]=R.z,u.array[x+11]=R.w,x+=12;D=0;for(S=va.length;D<S;D++)qa=R=Q=P=za=u.value[va[D]],u.array[x]=P.x,u.array[x+1]=P.y,u.array[x+2]=P.z,u.array[x+3]=P.w,u.array[x+4]=Q.x,u.array[x+5]=Q.y,u.array[x+6]=Q.z,u.array[x+7]=Q.w,u.array[x+8]=R.x,u.array[x+9]=R.y,u.array[x+10]=R.z,u.array[x+11]=R.w,u.array[x+12]=qa.x,u.array[x+13]=qa.y,u.array[x+14]=qa.z,u.array[x+15]=qa.w,x+=16}else if("faceVertices"===u.boundTo){D=0;for(S=
-ua.length;D<S;D++)za=u.value[ua[D]],P=za[0],Q=za[1],R=za[2],u.array[x]=P.x,u.array[x+1]=P.y,u.array[x+2]=P.z,u.array[x+3]=P.w,u.array[x+4]=Q.x,u.array[x+5]=Q.y,u.array[x+6]=Q.z,u.array[x+7]=Q.w,u.array[x+8]=R.x,u.array[x+9]=R.y,u.array[x+10]=R.z,u.array[x+11]=R.w,x+=12;D=0;for(S=va.length;D<S;D++)za=u.value[va[D]],P=za[0],Q=za[1],R=za[2],qa=za[3],u.array[x]=P.x,u.array[x+1]=P.y,u.array[x+2]=P.z,u.array[x+3]=P.w,u.array[x+4]=Q.x,u.array[x+5]=Q.y,u.array[x+6]=Q.z,u.array[x+7]=Q.w,u.array[x+8]=R.x,u.array[x+
-9]=R.y,u.array[x+10]=R.z,u.array[x+11]=R.w,u.array[x+12]=qa.x,u.array[x+13]=qa.y,u.array[x+14]=qa.z,u.array[x+15]=qa.w,x+=16}j.bindBuffer(j.ARRAY_BUFFER,u.buffer);j.bufferData(j.ARRAY_BUFFER,u.array,Ga)}}Hb&&(delete ta.__inittedArrays,delete ta.__colorArray,delete ta.__normalArray,delete ta.__tangentArray,delete ta.__uvArray,delete ta.__uv2Array,delete ta.__faceArray,delete ta.__vertexArray,delete ta.__lineArray,delete ta.__skinIndexArray,delete ta.__skinWeightArray)}}la.verticesNeedUpdate=!1;la.morphTargetsNeedUpdate=
-!1;la.elementsNeedUpdate=!1;la.uvsNeedUpdate=!1;la.normalsNeedUpdate=!1;la.colorsNeedUpdate=!1;la.tangentsNeedUpdate=!1;la.buffersNeedUpdate=!1;na.attributes&&q(na)}else if(ma instanceof THREE.Ribbon){na=e(ma,la);xa=na.attributes&&p(na);if(la.verticesNeedUpdate||la.colorsNeedUpdate||la.normalsNeedUpdate||xa){var Eb=la,ad=j.DYNAMIC_DRAW,Pc=void 0,Qc=void 0,Rc=void 0,bd=void 0,Aa=void 0,cd=void 0,dd=void 0,ed=void 0,Cd=void 0,bb=void 0,Gc=void 0,Ea=void 0,rb=void 0,Dd=Eb.vertices,Ed=Eb.colors,Fd=Eb.normals,
-Od=Dd.length,Pd=Ed.length,Qd=Fd.length,fd=Eb.__vertexArray,gd=Eb.__colorArray,hd=Eb.__normalArray,Rd=Eb.colorsNeedUpdate,Sd=Eb.normalsNeedUpdate,wd=Eb.__webglCustomAttributesList;if(Eb.verticesNeedUpdate){for(Pc=0;Pc<Od;Pc++)bd=Dd[Pc],Aa=3*Pc,fd[Aa]=bd.x,fd[Aa+1]=bd.y,fd[Aa+2]=bd.z;j.bindBuffer(j.ARRAY_BUFFER,Eb.__webglVertexBuffer);j.bufferData(j.ARRAY_BUFFER,fd,ad)}if(Rd){for(Qc=0;Qc<Pd;Qc++)cd=Ed[Qc],Aa=3*Qc,gd[Aa]=cd.r,gd[Aa+1]=cd.g,gd[Aa+2]=cd.b;j.bindBuffer(j.ARRAY_BUFFER,Eb.__webglColorBuffer);
-j.bufferData(j.ARRAY_BUFFER,gd,ad)}if(Sd){for(Rc=0;Rc<Qd;Rc++)dd=Fd[Rc],Aa=3*Rc,hd[Aa]=dd.x,hd[Aa+1]=dd.y,hd[Aa+2]=dd.z;j.bindBuffer(j.ARRAY_BUFFER,Eb.__webglNormalBuffer);j.bufferData(j.ARRAY_BUFFER,hd,ad)}if(wd){ed=0;for(Cd=wd.length;ed<Cd;ed++)if(Ea=wd[ed],Ea.needsUpdate&&(void 0===Ea.boundTo||"vertices"===Ea.boundTo)){Aa=0;Gc=Ea.value.length;if(1===Ea.size)for(bb=0;bb<Gc;bb++)Ea.array[bb]=Ea.value[bb];else if(2===Ea.size)for(bb=0;bb<Gc;bb++)rb=Ea.value[bb],Ea.array[Aa]=rb.x,Ea.array[Aa+1]=rb.y,
-Aa+=2;else if(3===Ea.size)if("c"===Ea.type)for(bb=0;bb<Gc;bb++)rb=Ea.value[bb],Ea.array[Aa]=rb.r,Ea.array[Aa+1]=rb.g,Ea.array[Aa+2]=rb.b,Aa+=3;else for(bb=0;bb<Gc;bb++)rb=Ea.value[bb],Ea.array[Aa]=rb.x,Ea.array[Aa+1]=rb.y,Ea.array[Aa+2]=rb.z,Aa+=3;else if(4===Ea.size)for(bb=0;bb<Gc;bb++)rb=Ea.value[bb],Ea.array[Aa]=rb.x,Ea.array[Aa+1]=rb.y,Ea.array[Aa+2]=rb.z,Ea.array[Aa+3]=rb.w,Aa+=4;j.bindBuffer(j.ARRAY_BUFFER,Ea.buffer);j.bufferData(j.ARRAY_BUFFER,Ea.array,ad)}}}la.verticesNeedUpdate=!1;la.colorsNeedUpdate=
-!1;la.normalsNeedUpdate=!1;na.attributes&&q(na)}else if(ma instanceof THREE.Line){na=e(ma,la);xa=na.attributes&&p(na);if(la.verticesNeedUpdate||la.colorsNeedUpdate||la.lineDistancesNeedUpdate||xa){var Fb=la,id=j.DYNAMIC_DRAW,Sc=void 0,Tc=void 0,Uc=void 0,jd=void 0,Ka=void 0,kd=void 0,Gd=Fb.vertices,Hd=Fb.colors,Id=Fb.lineDistances,Td=Gd.length,Ud=Hd.length,Vd=Id.length,ld=Fb.__vertexArray,md=Fb.__colorArray,Jd=Fb.__lineDistanceArray,Wd=Fb.colorsNeedUpdate,Xd=Fb.lineDistancesNeedUpdate,xd=Fb.__webglCustomAttributesList,
-nd=void 0,Kd=void 0,cb=void 0,Hc=void 0,sb=void 0,Fa=void 0;if(Fb.verticesNeedUpdate){for(Sc=0;Sc<Td;Sc++)jd=Gd[Sc],Ka=3*Sc,ld[Ka]=jd.x,ld[Ka+1]=jd.y,ld[Ka+2]=jd.z;j.bindBuffer(j.ARRAY_BUFFER,Fb.__webglVertexBuffer);j.bufferData(j.ARRAY_BUFFER,ld,id)}if(Wd){for(Tc=0;Tc<Ud;Tc++)kd=Hd[Tc],Ka=3*Tc,md[Ka]=kd.r,md[Ka+1]=kd.g,md[Ka+2]=kd.b;j.bindBuffer(j.ARRAY_BUFFER,Fb.__webglColorBuffer);j.bufferData(j.ARRAY_BUFFER,md,id)}if(Xd){for(Uc=0;Uc<Vd;Uc++)Jd[Uc]=Id[Uc];j.bindBuffer(j.ARRAY_BUFFER,Fb.__webglLineDistanceBuffer);
-j.bufferData(j.ARRAY_BUFFER,Jd,id)}if(xd){nd=0;for(Kd=xd.length;nd<Kd;nd++)if(Fa=xd[nd],Fa.needsUpdate&&(void 0===Fa.boundTo||"vertices"===Fa.boundTo)){Ka=0;Hc=Fa.value.length;if(1===Fa.size)for(cb=0;cb<Hc;cb++)Fa.array[cb]=Fa.value[cb];else if(2===Fa.size)for(cb=0;cb<Hc;cb++)sb=Fa.value[cb],Fa.array[Ka]=sb.x,Fa.array[Ka+1]=sb.y,Ka+=2;else if(3===Fa.size)if("c"===Fa.type)for(cb=0;cb<Hc;cb++)sb=Fa.value[cb],Fa.array[Ka]=sb.r,Fa.array[Ka+1]=sb.g,Fa.array[Ka+2]=sb.b,Ka+=3;else for(cb=0;cb<Hc;cb++)sb=
-Fa.value[cb],Fa.array[Ka]=sb.x,Fa.array[Ka+1]=sb.y,Fa.array[Ka+2]=sb.z,Ka+=3;else if(4===Fa.size)for(cb=0;cb<Hc;cb++)sb=Fa.value[cb],Fa.array[Ka]=sb.x,Fa.array[Ka+1]=sb.y,Fa.array[Ka+2]=sb.z,Fa.array[Ka+3]=sb.w,Ka+=4;j.bindBuffer(j.ARRAY_BUFFER,Fa.buffer);j.bufferData(j.ARRAY_BUFFER,Fa.array,id)}}}la.verticesNeedUpdate=!1;la.colorsNeedUpdate=!1;la.lineDistancesNeedUpdate=!1;na.attributes&&q(na)}else if(ma instanceof THREE.ParticleSystem){na=e(ma,la);xa=na.attributes&&p(na);if(la.verticesNeedUpdate||
-la.colorsNeedUpdate||ma.sortParticles||xa){var fc=la,yd=j.DYNAMIC_DRAW,Vc=ma,tb=void 0,gc=void 0,hc=void 0,da=void 0,ic=void 0,vc=void 0,od=fc.vertices,zd=od.length,Ad=fc.colors,Ld=Ad.length,zc=fc.__vertexArray,Ac=fc.__colorArray,nc=fc.__sortArray,Md=fc.verticesNeedUpdate,Nd=fc.colorsNeedUpdate,oc=fc.__webglCustomAttributesList,Kb=void 0,Ic=void 0,pa=void 0,Lb=void 0,Da=void 0,ba=void 0;if(Vc.sortParticles){Va.copy(Qa);Va.multiply(Vc.matrixWorld);for(tb=0;tb<zd;tb++)hc=od[tb],wa.copy(hc),wa.applyProjection(Va),
-nc[tb]=[wa.z,tb];nc.sort(l);for(tb=0;tb<zd;tb++)hc=od[nc[tb][1]],da=3*tb,zc[da]=hc.x,zc[da+1]=hc.y,zc[da+2]=hc.z;for(gc=0;gc<Ld;gc++)da=3*gc,vc=Ad[nc[gc][1]],Ac[da]=vc.r,Ac[da+1]=vc.g,Ac[da+2]=vc.b;if(oc){Kb=0;for(Ic=oc.length;Kb<Ic;Kb++)if(ba=oc[Kb],void 0===ba.boundTo||"vertices"===ba.boundTo)if(da=0,Lb=ba.value.length,1===ba.size)for(pa=0;pa<Lb;pa++)ic=nc[pa][1],ba.array[pa]=ba.value[ic];else if(2===ba.size)for(pa=0;pa<Lb;pa++)ic=nc[pa][1],Da=ba.value[ic],ba.array[da]=Da.x,ba.array[da+1]=Da.y,
-da+=2;else if(3===ba.size)if("c"===ba.type)for(pa=0;pa<Lb;pa++)ic=nc[pa][1],Da=ba.value[ic],ba.array[da]=Da.r,ba.array[da+1]=Da.g,ba.array[da+2]=Da.b,da+=3;else for(pa=0;pa<Lb;pa++)ic=nc[pa][1],Da=ba.value[ic],ba.array[da]=Da.x,ba.array[da+1]=Da.y,ba.array[da+2]=Da.z,da+=3;else if(4===ba.size)for(pa=0;pa<Lb;pa++)ic=nc[pa][1],Da=ba.value[ic],ba.array[da]=Da.x,ba.array[da+1]=Da.y,ba.array[da+2]=Da.z,ba.array[da+3]=Da.w,da+=4}}else{if(Md)for(tb=0;tb<zd;tb++)hc=od[tb],da=3*tb,zc[da]=hc.x,zc[da+1]=hc.y,
-zc[da+2]=hc.z;if(Nd)for(gc=0;gc<Ld;gc++)vc=Ad[gc],da=3*gc,Ac[da]=vc.r,Ac[da+1]=vc.g,Ac[da+2]=vc.b;if(oc){Kb=0;for(Ic=oc.length;Kb<Ic;Kb++)if(ba=oc[Kb],ba.needsUpdate&&(void 0===ba.boundTo||"vertices"===ba.boundTo))if(Lb=ba.value.length,da=0,1===ba.size)for(pa=0;pa<Lb;pa++)ba.array[pa]=ba.value[pa];else if(2===ba.size)for(pa=0;pa<Lb;pa++)Da=ba.value[pa],ba.array[da]=Da.x,ba.array[da+1]=Da.y,da+=2;else if(3===ba.size)if("c"===ba.type)for(pa=0;pa<Lb;pa++)Da=ba.value[pa],ba.array[da]=Da.r,ba.array[da+
-1]=Da.g,ba.array[da+2]=Da.b,da+=3;else for(pa=0;pa<Lb;pa++)Da=ba.value[pa],ba.array[da]=Da.x,ba.array[da+1]=Da.y,ba.array[da+2]=Da.z,da+=3;else if(4===ba.size)for(pa=0;pa<Lb;pa++)Da=ba.value[pa],ba.array[da]=Da.x,ba.array[da+1]=Da.y,ba.array[da+2]=Da.z,ba.array[da+3]=Da.w,da+=4}}if(Md||Vc.sortParticles)j.bindBuffer(j.ARRAY_BUFFER,fc.__webglVertexBuffer),j.bufferData(j.ARRAY_BUFFER,zc,yd);if(Nd||Vc.sortParticles)j.bindBuffer(j.ARRAY_BUFFER,fc.__webglColorBuffer),j.bufferData(j.ARRAY_BUFFER,Ac,yd);
-if(oc){Kb=0;for(Ic=oc.length;Kb<Ic;Kb++)if(ba=oc[Kb],ba.needsUpdate||Vc.sortParticles)j.bindBuffer(j.ARRAY_BUFFER,ba.buffer),j.bufferData(j.ARRAY_BUFFER,ba.array,yd)}}la.verticesNeedUpdate=!1;la.colorsNeedUpdate=!1;na.attributes&&q(na)}}};this.initMaterial=function(a,b,c,d){var e,f,g,i;a.addEventListener("dispose",Xc);var h,k,l,m,n;a instanceof THREE.MeshDepthMaterial?n="depth":a instanceof THREE.MeshNormalMaterial?n="normal":a instanceof THREE.MeshBasicMaterial?n="basic":a instanceof THREE.MeshLambertMaterial?
-n="lambert":a instanceof THREE.MeshPhongMaterial?n="phong":a instanceof THREE.LineBasicMaterial?n="basic":a instanceof THREE.LineDashedMaterial?n="dashed":a instanceof THREE.ParticleBasicMaterial&&(n="particle_basic");if(n){var p=THREE.ShaderLib[n];a.uniforms=THREE.UniformsUtils.clone(p.uniforms);a.vertexShader=p.vertexShader;a.fragmentShader=p.fragmentShader}var q,r,t;e=g=r=t=p=0;for(f=b.length;e<f;e++)q=b[e],q.onlyShadow||(q instanceof THREE.DirectionalLight&&g++,q instanceof THREE.PointLight&&
-r++,q instanceof THREE.SpotLight&&t++,q instanceof THREE.HemisphereLight&&p++);e=g;f=r;g=t;i=p;p=q=0;for(t=b.length;p<t;p++)r=b[p],r.castShadow&&(r instanceof THREE.SpotLight&&q++,r instanceof THREE.DirectionalLight&&!r.shadowCascade&&q++);m=q;Cc&&d&&d.useVertexTexture?l=1024:(b=j.getParameter(j.MAX_VERTEX_UNIFORM_VECTORS),b=Math.floor((b-20)/4),void 0!==d&&d instanceof THREE.SkinnedMesh&&(b=Math.min(d.bones.length,b),b<d.bones.length&&console.warn("WebGLRenderer: too many bones - "+d.bones.length+
-", this GPU supports just "+b+" (try OpenGL instead of ANGLE)")),l=b);a:{r=a.fragmentShader;t=a.vertexShader;p=a.uniforms;b=a.attributes;q=a.defines;var c={map:!!a.map,envMap:!!a.envMap,lightMap:!!a.lightMap,bumpMap:!!a.bumpMap,normalMap:!!a.normalMap,specularMap:!!a.specularMap,vertexColors:a.vertexColors,fog:c,useFog:a.fog,fogExp:c instanceof THREE.FogExp2,sizeAttenuation:a.sizeAttenuation,skinning:a.skinning,maxBones:l,useVertexTexture:Cc&&d&&d.useVertexTexture,boneTextureWidth:d&&d.boneTextureWidth,
-boneTextureHeight:d&&d.boneTextureHeight,morphTargets:a.morphTargets,morphNormals:a.morphNormals,maxMorphTargets:this.maxMorphTargets,maxMorphNormals:this.maxMorphNormals,maxDirLights:e,maxPointLights:f,maxSpotLights:g,maxHemiLights:i,maxShadows:m,shadowMapEnabled:this.shadowMapEnabled&&d.receiveShadow,shadowMapType:this.shadowMapType,shadowMapDebug:this.shadowMapDebug,shadowMapCascade:this.shadowMapCascade,alphaTest:a.alphaTest,metal:a.metal,perPixel:a.perPixel,wrapAround:a.wrapAround,doubleSided:a.side===
-THREE.DoubleSide,flipSided:a.side===THREE.BackSide},s,v,w,d=[];n?d.push(n):(d.push(r),d.push(t));for(v in q)d.push(v),d.push(q[v]);for(s in c)d.push(s),d.push(c[s]);n=d.join();s=0;for(v=ca.length;s<v;s++)if(d=ca[s],d.code===n){d.usedTimes++;k=d.program;break a}s="SHADOWMAP_TYPE_BASIC";c.shadowMapType===THREE.PCFShadowMap?s="SHADOWMAP_TYPE_PCF":c.shadowMapType===THREE.PCFSoftShadowMap&&(s="SHADOWMAP_TYPE_PCF_SOFT");v=[];for(w in q)d=q[w],!1!==d&&(d="#define "+w+" "+d,v.push(d));d=v.join("\n");w=j.createProgram();
-v=["precision "+K+" float;",d,Bc?"#define VERTEX_TEXTURES":"",L.gammaInput?"#define GAMMA_INPUT":"",L.gammaOutput?"#define GAMMA_OUTPUT":"",L.physicallyBasedShading?"#define PHYSICALLY_BASED_SHADING":"","#define MAX_DIR_LIGHTS "+c.maxDirLights,"#define MAX_POINT_LIGHTS "+c.maxPointLights,"#define MAX_SPOT_LIGHTS "+c.maxSpotLights,"#define MAX_HEMI_LIGHTS "+c.maxHemiLights,"#define MAX_SHADOWS "+c.maxShadows,"#define MAX_BONES "+c.maxBones,c.map?"#define USE_MAP":"",c.envMap?"#define USE_ENVMAP":"",
-c.lightMap?"#define USE_LIGHTMAP":"",c.bumpMap?"#define USE_BUMPMAP":"",c.normalMap?"#define USE_NORMALMAP":"",c.specularMap?"#define USE_SPECULARMAP":"",c.vertexColors?"#define USE_COLOR":"",c.skinning?"#define USE_SKINNING":"",c.useVertexTexture?"#define BONE_TEXTURE":"",c.boneTextureWidth?"#define N_BONE_PIXEL_X "+c.boneTextureWidth.toFixed(1):"",c.boneTextureHeight?"#define N_BONE_PIXEL_Y "+c.boneTextureHeight.toFixed(1):"",c.morphTargets?"#define USE_MORPHTARGETS":"",c.morphNormals?"#define USE_MORPHNORMALS":
-"",c.perPixel?"#define PHONG_PER_PIXEL":"",c.wrapAround?"#define WRAP_AROUND":"",c.doubleSided?"#define DOUBLE_SIDED":"",c.flipSided?"#define FLIP_SIDED":"",c.shadowMapEnabled?"#define USE_SHADOWMAP":"",c.shadowMapEnabled?"#define "+s:"",c.shadowMapDebug?"#define SHADOWMAP_DEBUG":"",c.shadowMapCascade?"#define SHADOWMAP_CASCADE":"",c.sizeAttenuation?"#define USE_SIZEATTENUATION":"","uniform mat4 modelMatrix;\nuniform mat4 modelViewMatrix;\nuniform mat4 projectionMatrix;\nuniform mat4 viewMatrix;\nuniform mat3 normalMatrix;\nuniform vec3 cameraPosition;\nattribute vec3 position;\nattribute vec3 normal;\nattribute vec2 uv;\nattribute vec2 uv2;\n#ifdef USE_COLOR\nattribute vec3 color;\n#endif\n#ifdef USE_MORPHTARGETS\nattribute vec3 morphTarget0;\nattribute vec3 morphTarget1;\nattribute vec3 morphTarget2;\nattribute vec3 morphTarget3;\n#ifdef USE_MORPHNORMALS\nattribute vec3 morphNormal0;\nattribute vec3 morphNormal1;\nattribute vec3 morphNormal2;\nattribute vec3 morphNormal3;\n#else\nattribute vec3 morphTarget4;\nattribute vec3 morphTarget5;\nattribute vec3 morphTarget6;\nattribute vec3 morphTarget7;\n#endif\n#endif\n#ifdef USE_SKINNING\nattribute vec4 skinIndex;\nattribute vec4 skinWeight;\n#endif\n"].join("\n");
-s=["precision "+K+" float;",c.bumpMap||c.normalMap?"#extension GL_OES_standard_derivatives : enable":"",d,"#define MAX_DIR_LIGHTS "+c.maxDirLights,"#define MAX_POINT_LIGHTS "+c.maxPointLights,"#define MAX_SPOT_LIGHTS "+c.maxSpotLights,"#define MAX_HEMI_LIGHTS "+c.maxHemiLights,"#define MAX_SHADOWS "+c.maxShadows,c.alphaTest?"#define ALPHATEST "+c.alphaTest:"",L.gammaInput?"#define GAMMA_INPUT":"",L.gammaOutput?"#define GAMMA_OUTPUT":"",L.physicallyBasedShading?"#define PHYSICALLY_BASED_SHADING":"",
-c.useFog&&c.fog?"#define USE_FOG":"",c.useFog&&c.fogExp?"#define FOG_EXP2":"",c.map?"#define USE_MAP":"",c.envMap?"#define USE_ENVMAP":"",c.lightMap?"#define USE_LIGHTMAP":"",c.bumpMap?"#define USE_BUMPMAP":"",c.normalMap?"#define USE_NORMALMAP":"",c.specularMap?"#define USE_SPECULARMAP":"",c.vertexColors?"#define USE_COLOR":"",c.metal?"#define METAL":"",c.perPixel?"#define PHONG_PER_PIXEL":"",c.wrapAround?"#define WRAP_AROUND":"",c.doubleSided?"#define DOUBLE_SIDED":"",c.flipSided?"#define FLIP_SIDED":
-"",c.shadowMapEnabled?"#define USE_SHADOWMAP":"",c.shadowMapEnabled?"#define "+s:"",c.shadowMapDebug?"#define SHADOWMAP_DEBUG":"",c.shadowMapCascade?"#define SHADOWMAP_CASCADE":"","uniform mat4 viewMatrix;\nuniform vec3 cameraPosition;\n"].join("\n");s=E("fragment",s+r);v=E("vertex",v+t);j.attachShader(w,v);j.attachShader(w,s);j.linkProgram(w);j.getProgramParameter(w,j.LINK_STATUS)||console.error("Could not initialise shader\nVALIDATE_STATUS: "+j.getProgramParameter(w,j.VALIDATE_STATUS)+", gl error ["+
-j.getError()+"]");j.deleteShader(s);j.deleteShader(v);w.uniforms={};w.attributes={};var y;s="viewMatrix modelViewMatrix projectionMatrix normalMatrix modelMatrix cameraPosition morphTargetInfluences".split(" ");c.useVertexTexture?s.push("boneTexture"):s.push("boneGlobalMatrices");for(y in p)s.push(y);y=s;s=0;for(v=y.length;s<v;s++)p=y[s],w.uniforms[p]=j.getUniformLocation(w,p);s="position normal uv uv2 tangent color skinIndex skinWeight lineDistance".split(" ");for(y=0;y<c.maxMorphTargets;y++)s.push("morphTarget"+
-y);for(y=0;y<c.maxMorphNormals;y++)s.push("morphNormal"+y);for(k in b)s.push(k);k=s;y=0;for(b=k.length;y<b;y++)s=k[y],w.attributes[s]=j.getAttribLocation(w,s);w.id=ra++;ca.push({program:w,code:n,usedTimes:1});L.info.memory.programs=ca.length;k=w}a.program=k;y=a.program.attributes;if(a.morphTargets){a.numSupportedMorphTargets=0;b="morphTarget";for(k=0;k<this.maxMorphTargets;k++)w=b+k,0<=y[w]&&a.numSupportedMorphTargets++}if(a.morphNormals){a.numSupportedMorphNormals=0;b="morphNormal";for(k=0;k<this.maxMorphNormals;k++)w=
-b+k,0<=y[w]&&a.numSupportedMorphNormals++}a.uniformsList=[];for(h in a.uniforms)a.uniformsList.push([a.uniforms[h],h])};this.setFaceCulling=function(a,b){a===THREE.CullFaceNone?j.disable(j.CULL_FACE):(b===THREE.FrontFaceDirectionCW?j.frontFace(j.CW):j.frontFace(j.CCW),a===THREE.CullFaceBack?j.cullFace(j.BACK):a===THREE.CullFaceFront?j.cullFace(j.FRONT):j.cullFace(j.FRONT_AND_BACK),j.enable(j.CULL_FACE))};this.setMaterialFaces=function(a){var b=a.side===THREE.DoubleSide,a=a.side===THREE.BackSide;ha!==
-b&&(b?j.disable(j.CULL_FACE):j.enable(j.CULL_FACE),ha=b);V!==a&&(a?j.frontFace(j.CW):j.frontFace(j.CCW),V=a)};this.setDepthTest=function(a){na!==a&&(a?j.enable(j.DEPTH_TEST):j.disable(j.DEPTH_TEST),na=a)};this.setDepthWrite=function(a){Pa!==a&&(j.depthMask(a),Pa=a)};this.setBlending=function(a,b,c,d){a!==$&&(a===THREE.NoBlending?j.disable(j.BLEND):a===THREE.AdditiveBlending?(j.enable(j.BLEND),j.blendEquation(j.FUNC_ADD),j.blendFunc(j.SRC_ALPHA,j.ONE)):a===THREE.SubtractiveBlending?(j.enable(j.BLEND),
-j.blendEquation(j.FUNC_ADD),j.blendFunc(j.ZERO,j.ONE_MINUS_SRC_COLOR)):a===THREE.MultiplyBlending?(j.enable(j.BLEND),j.blendEquation(j.FUNC_ADD),j.blendFunc(j.ZERO,j.SRC_COLOR)):a===THREE.CustomBlending?j.enable(j.BLEND):(j.enable(j.BLEND),j.blendEquationSeparate(j.FUNC_ADD,j.FUNC_ADD),j.blendFuncSeparate(j.SRC_ALPHA,j.ONE_MINUS_SRC_ALPHA,j.ONE,j.ONE_MINUS_SRC_ALPHA)),$=a);if(a===THREE.CustomBlending){if(b!==Y&&(j.blendEquation(F(b)),Y=b),c!==ia||d!==sa)j.blendFunc(F(c),F(d)),ia=c,sa=d}else sa=ia=
-Y=null};this.setTexture=function(a,b){if(a.needsUpdate){a.__webglInit||(a.__webglInit=!0,a.addEventListener("dispose",Zc),a.__webglTexture=j.createTexture(),L.info.memory.textures++);j.activeTexture(j.TEXTURE0+b);j.bindTexture(j.TEXTURE_2D,a.__webglTexture);j.pixelStorei(j.UNPACK_FLIP_Y_WEBGL,a.flipY);j.pixelStorei(j.UNPACK_PREMULTIPLY_ALPHA_WEBGL,a.premultiplyAlpha);j.pixelStorei(j.UNPACK_ALIGNMENT,a.unpackAlignment);var c=a.image,d=0===(c.width&c.width-1)&&0===(c.height&c.height-1),e=F(a.format),
-f=F(a.type);Z(j.TEXTURE_2D,a,d);var g=a.mipmaps;if(a instanceof THREE.DataTexture)if(0<g.length&&d){for(var i=0,h=g.length;i<h;i++)c=g[i],j.texImage2D(j.TEXTURE_2D,i,e,c.width,c.height,0,e,f,c.data);a.generateMipmaps=!1}else j.texImage2D(j.TEXTURE_2D,0,e,c.width,c.height,0,e,f,c.data);else if(a instanceof THREE.CompressedTexture){i=0;for(h=g.length;i<h;i++)c=g[i],j.compressedTexImage2D(j.TEXTURE_2D,i,e,c.width,c.height,0,c.data)}else if(0<g.length&&d){i=0;for(h=g.length;i<h;i++)c=g[i],j.texImage2D(j.TEXTURE_2D,
-i,e,e,f,c);a.generateMipmaps=!1}else j.texImage2D(j.TEXTURE_2D,0,e,e,f,a.image);a.generateMipmaps&&d&&j.generateMipmap(j.TEXTURE_2D);a.needsUpdate=!1;if(a.onUpdate)a.onUpdate()}else j.activeTexture(j.TEXTURE0+b),j.bindTexture(j.TEXTURE_2D,a.__webglTexture)};this.setRenderTarget=function(a){var b=a instanceof THREE.WebGLRenderTargetCube;if(a&&!a.__webglFramebuffer){void 0===a.depthBuffer&&(a.depthBuffer=!0);void 0===a.stencilBuffer&&(a.stencilBuffer=!0);a.addEventListener("dispose",Jc);a.__webglTexture=
-j.createTexture();L.info.memory.textures++;var c=0===(a.width&a.width-1)&&0===(a.height&a.height-1),d=F(a.format),e=F(a.type);if(b){a.__webglFramebuffer=[];a.__webglRenderbuffer=[];j.bindTexture(j.TEXTURE_CUBE_MAP,a.__webglTexture);Z(j.TEXTURE_CUBE_MAP,a,c);for(var f=0;6>f;f++){a.__webglFramebuffer[f]=j.createFramebuffer();a.__webglRenderbuffer[f]=j.createRenderbuffer();j.texImage2D(j.TEXTURE_CUBE_MAP_POSITIVE_X+f,0,d,a.width,a.height,0,d,e,null);var g=a,i=j.TEXTURE_CUBE_MAP_POSITIVE_X+f;j.bindFramebuffer(j.FRAMEBUFFER,
-a.__webglFramebuffer[f]);j.framebufferTexture2D(j.FRAMEBUFFER,j.COLOR_ATTACHMENT0,i,g.__webglTexture,0);A(a.__webglRenderbuffer[f],a)}c&&j.generateMipmap(j.TEXTURE_CUBE_MAP)}else a.__webglFramebuffer=j.createFramebuffer(),a.__webglRenderbuffer=a.shareDepthFrom?a.shareDepthFrom.__webglRenderbuffer:j.createRenderbuffer(),j.bindTexture(j.TEXTURE_2D,a.__webglTexture),Z(j.TEXTURE_2D,a,c),j.texImage2D(j.TEXTURE_2D,0,d,a.width,a.height,0,d,e,null),d=j.TEXTURE_2D,j.bindFramebuffer(j.FRAMEBUFFER,a.__webglFramebuffer),
-j.framebufferTexture2D(j.FRAMEBUFFER,j.COLOR_ATTACHMENT0,d,a.__webglTexture,0),a.shareDepthFrom?a.depthBuffer&&!a.stencilBuffer?j.framebufferRenderbuffer(j.FRAMEBUFFER,j.DEPTH_ATTACHMENT,j.RENDERBUFFER,a.__webglRenderbuffer):a.depthBuffer&&a.stencilBuffer&&j.framebufferRenderbuffer(j.FRAMEBUFFER,j.DEPTH_STENCIL_ATTACHMENT,j.RENDERBUFFER,a.__webglRenderbuffer):A(a.__webglRenderbuffer,a),c&&j.generateMipmap(j.TEXTURE_2D);b?j.bindTexture(j.TEXTURE_CUBE_MAP,null):j.bindTexture(j.TEXTURE_2D,null);j.bindRenderbuffer(j.RENDERBUFFER,
-null);j.bindFramebuffer(j.FRAMEBUFFER,null)}a?(b=b?a.__webglFramebuffer[a.activeCubeFace]:a.__webglFramebuffer,c=a.width,a=a.height,e=d=0):(b=null,c=Mb,a=wb,d=ob,e=Gb);b!==$a&&(j.bindFramebuffer(j.FRAMEBUFFER,b),j.viewport(d,e,c,a),$a=b);Nb=c;Ob=a};this.shadowMapPlugin=new THREE.ShadowMapPlugin;this.addPrePlugin(this.shadowMapPlugin);this.addPostPlugin(new THREE.SpritePlugin);this.addPostPlugin(new THREE.LensFlarePlugin)};THREE.WebGLRenderTarget=function(a,b,c){THREE.EventDispatcher.call(this);this.width=a;this.height=b;c=c||{};this.wrapS=void 0!==c.wrapS?c.wrapS:THREE.ClampToEdgeWrapping;this.wrapT=void 0!==c.wrapT?c.wrapT:THREE.ClampToEdgeWrapping;this.magFilter=void 0!==c.magFilter?c.magFilter:THREE.LinearFilter;this.minFilter=void 0!==c.minFilter?c.minFilter:THREE.LinearMipMapLinearFilter;this.anisotropy=void 0!==c.anisotropy?c.anisotropy:1;this.offset=new THREE.Vector2(0,0);this.repeat=new THREE.Vector2(1,1);
+depthRGBA:{uniforms:{},vertexShader:[THREE.ShaderChunk.morphtarget_pars_vertex,THREE.ShaderChunk.skinning_pars_vertex,"void main() {",THREE.ShaderChunk.skinbase_vertex,THREE.ShaderChunk.morphtarget_vertex,THREE.ShaderChunk.skinning_vertex,THREE.ShaderChunk.default_vertex,"}"].join("\n"),fragmentShader:"vec4 pack_depth( const in float depth ) {\nconst vec4 bit_shift = vec4( 256.0 * 256.0 * 256.0, 256.0 * 256.0, 256.0, 1.0 );\nconst vec4 bit_mask  = vec4( 0.0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0 );\nvec4 res = fract( depth * bit_shift );\nres -= res.xxyz * bit_mask;\nreturn res;\n}\nvoid main() {\ngl_FragData[ 0 ] = pack_depth( gl_FragCoord.z );\n}"}};THREE.WebGLRenderer=function(a){function b(a){if(a.__webglCustomAttributesList)for(var b in a.__webglCustomAttributesList)t.deleteBuffer(a.__webglCustomAttributesList[b].buffer)}function c(a,b){return a.material instanceof THREE.MeshFaceMaterial?a.material.materials[b.materialIndex]:a.material}function d(a){var b,c;for(b in a.attributes)c=a.attributes[b],c.buffer=t.createBuffer(),"index"===b?t.setStaticIndexBuffer(c.buffer,c.array):t.setStaticArrayBuffer(c.buffer,c.array)}function e(a,b){var c=a.attributes,
+d,e;for(d in c)e=c[d],e.needsUpdate&&("index"===d?t.setDynamicIndexBuffer(e.buffer,e.array):t.setDynamicArrayBuffer(e.buffer,e.array),e.needsUpdate=!1),b&&!e.dynamic&&delete e.array}function f(a,b){return a.z!==b.z?b.z-a.z:a.id-b.id}function g(a,b){return b[0]-a[0]}function h(a,b,c){if(a.length)for(var d=0,e=a.length;d<e;d++)E=P=null,A=G=-1,N=!0,t.resetState(),a[d].render(b,c,t.getCurrentWidth(),t.getCurrentWidth()),E=P=null,A=G=-1,N=!0,t.resetState()}function i(a,b,c,d,e,f,g,i){var h,j,k,l;b?(j=
+a.length-1,l=b=-1):(j=0,b=a.length,l=1);for(var m=j;m!==b;m+=l)if(h=a[m],h.render){j=h.object;k=h.buffer;if(i)h=i;else{h=h[c];if(!h)continue;g&&t.setBlending(h.blending,h.blendEquation,h.blendSrc,h.blendDst);t.setDepthTest(h.depthTest);t.setDepthWrite(h.depthWrite);t.setPolygonOffset(h.polygonOffset,h.polygonOffsetFactor,h.polygonOffsetUnits)}t.setMaterialFaces(h);k instanceof THREE.BufferGeometry?B.renderBufferDirect(d,e,f,h,k,j):B.renderBuffer(d,e,f,h,k,j)}}function j(a,b,c,d,e,f,g){for(var i,h,
+j=0,k=a.length;j<k;j++)if(i=a[j],h=i.object,h.visible){if(g)i=g;else{i=i[b];if(!i)continue;f&&t.setBlending(i.blending,i.blendEquation,i.blendSrc,i.blendDst);t.setDepthTest(i.depthTest);t.setDepthWrite(i.depthWrite);t.setPolygonOffset(i.polygonOffset,i.polygonOffsetFactor,i.polygonOffsetUnits)}B.renderImmediateObject(c,d,e,i,h)}}function l(a,b,c){a.push({id:null,buffer:b,object:c,opaque:null,transparent:null,render:!1,z:0})}function n(a){for(var b in a.attributes)if(a.attributes[b].needsUpdate)return!0;
+return!1}function m(a){for(var b in a.attributes)a.attributes[b].needsUpdate=!1}function r(a,b){for(var c=a.length-1;0<=c;c--)a[c].object===b&&a.splice(c,1)}function u(a,b){for(var c=a.length-1;0<=c;c--)a[c]===b&&a.splice(c,1)}function p(a,b,c,d,e){s=0;d.needsUpdate&&(d.program&&W(d),B.initMaterial(d,b,c,e),d.needsUpdate=!1);d.morphTargets&&!e.__webglMorphTargetInfluences&&(e.__webglMorphTargetInfluences=new Float32Array(B.maxMorphTargets));var f=!1,g=d.program,i=g.uniforms,h=d.uniforms;g!==P&&(t.useProgram(g),
+P=g,f=!0);d.id!==A&&(A=d.id,f=!0);if(f||a!==E)t.uniformMatrix4fv(i.projectionMatrix,a.projectionMatrix.elements),a!==E&&(E=a);if(d.skinning)if(t.supportsBoneTextures&&e.useVertexTexture){if(null!==i.boneTexture){var j=q();t.uniform1i(i.boneTexture,j);t.setTexture(e.boneTexture,j)}}else null!==i.boneGlobalMatrices&&t.uniformMatrix4fv(i.boneGlobalMatrices,e.boneMatrices);if(f){c&&d.fog&&(h.fogColor.value=c.color,c instanceof THREE.Fog?(h.fogNear.value=c.near,h.fogFar.value=c.far):c instanceof THREE.FogExp2&&
+(h.fogDensity.value=c.density));if(d instanceof THREE.MeshPhongMaterial||d instanceof THREE.MeshLambertMaterial||d.lights){if(N){for(var k,l=j=0,m=0,n,p,r,u=R,w=u.directional.colors,y=u.directional.positions,C=u.point.colors,D=u.point.positions,H=u.point.distances,F=u.spot.colors,G=u.spot.positions,I=u.spot.distances,J=u.spot.directions,O=u.spot.anglesCos,Y=u.spot.exponents,$=u.hemi.skyColors,fa=u.hemi.groundColors,oa=u.hemi.positions,Da=0,Ba=0,ga=0,xa=0,Ca=0,Ea=0,ma=0,za=0,ha=k=0,c=r=ha=0,f=b.length;c<
+f;c++)k=b[c],k.onlyShadow||(n=k.color,p=k.intensity,r=k.distance,k instanceof THREE.AmbientLight?k.visible&&(B.gammaInput?(j+=n.r*n.r,l+=n.g*n.g,m+=n.b*n.b):(j+=n.r,l+=n.g,m+=n.b)):k instanceof THREE.DirectionalLight?(Ca+=1,k.visible&&(x.getPositionFromMatrix(k.matrixWorld),K.getPositionFromMatrix(k.target.matrixWorld),x.sub(K),x.normalize(),0===x.x&&0===x.y&&0===x.z||(k=3*Da,y[k]=x.x,y[k+1]=x.y,y[k+2]=x.z,B.gammaInput?v(w,k,n,p*p):z(w,k,n,p),Da+=1))):k instanceof THREE.PointLight?(Ea+=1,k.visible&&
+(ha=3*Ba,B.gammaInput?v(C,ha,n,p*p):z(C,ha,n,p),K.getPositionFromMatrix(k.matrixWorld),D[ha]=K.x,D[ha+1]=K.y,D[ha+2]=K.z,H[Ba]=r,Ba+=1)):k instanceof THREE.SpotLight?(ma+=1,k.visible&&(ha=3*ga,B.gammaInput?v(F,ha,n,p*p):z(F,ha,n,p),K.getPositionFromMatrix(k.matrixWorld),G[ha]=K.x,G[ha+1]=K.y,G[ha+2]=K.z,I[ga]=r,x.copy(K),K.getPositionFromMatrix(k.target.matrixWorld),x.sub(K),x.normalize(),J[ha]=x.x,J[ha+1]=x.y,J[ha+2]=x.z,O[ga]=Math.cos(k.angle),Y[ga]=k.exponent,ga+=1)):k instanceof THREE.HemisphereLight&&
+(za+=1,k.visible&&(x.getPositionFromMatrix(k.matrixWorld),x.normalize(),0===x.x&&0===x.y&&0===x.z||(r=3*xa,oa[r]=x.x,oa[r+1]=x.y,oa[r+2]=x.z,n=k.color,k=k.groundColor,B.gammaInput?(p*=p,v($,r,n,p),v(fa,r,k,p)):(z($,r,n,p),z(fa,r,k,p)),xa+=1))));c=3*Da;for(f=Math.max(w.length,3*Ca);c<f;c++)w[c]=0;c=3*Ba;for(f=Math.max(C.length,3*Ea);c<f;c++)C[c]=0;c=3*ga;for(f=Math.max(F.length,3*ma);c<f;c++)F[c]=0;c=3*xa;for(f=Math.max($.length,3*za);c<f;c++)$[c]=0;c=3*xa;for(f=Math.max(fa.length,3*za);c<f;c++)fa[c]=
+0;u.directional.length=Da;u.point.length=Ba;u.spot.length=ga;u.hemi.length=xa;u.ambient[0]=j;u.ambient[1]=l;u.ambient[2]=m;N=!1}c=R;h.ambientLightColor.value=c.ambient;h.directionalLightColor.value=c.directional.colors;h.directionalLightDirection.value=c.directional.positions;h.pointLightColor.value=c.point.colors;h.pointLightPosition.value=c.point.positions;h.pointLightDistance.value=c.point.distances;h.spotLightColor.value=c.spot.colors;h.spotLightPosition.value=c.spot.positions;h.spotLightDistance.value=
+c.spot.distances;h.spotLightDirection.value=c.spot.directions;h.spotLightAngleCos.value=c.spot.anglesCos;h.spotLightExponent.value=c.spot.exponents;h.hemisphereLightSkyColor.value=c.hemi.skyColors;h.hemisphereLightGroundColor.value=c.hemi.groundColors;h.hemisphereLightDirection.value=c.hemi.positions}if(d instanceof THREE.MeshBasicMaterial||d instanceof THREE.MeshLambertMaterial||d instanceof THREE.MeshPhongMaterial){h.opacity.value=d.opacity;B.gammaInput?h.diffuse.value.copyGammaToLinear(d.color):
+h.diffuse.value=d.color;h.map.value=d.map;h.lightMap.value=d.lightMap;h.specularMap.value=d.specularMap;d.bumpMap&&(h.bumpMap.value=d.bumpMap,h.bumpScale.value=d.bumpScale);d.normalMap&&(h.normalMap.value=d.normalMap,h.normalScale.value.copy(d.normalScale));var Q;d.map?Q=d.map:d.specularMap?Q=d.specularMap:d.normalMap?Q=d.normalMap:d.bumpMap&&(Q=d.bumpMap);void 0!==Q&&(c=Q.offset,Q=Q.repeat,h.offsetRepeat.value.set(c.x,c.y,Q.x,Q.y));h.envMap.value=d.envMap;h.flipEnvMap.value=d.envMap instanceof THREE.WebGLRenderTargetCube?
+1:-1;h.reflectivity.value=d.reflectivity;h.refractionRatio.value=d.refractionRatio;h.combine.value=d.combine;h.useRefract.value=d.envMap&&d.envMap.mapping instanceof THREE.CubeRefractionMapping}d instanceof THREE.LineBasicMaterial?(h.diffuse.value=d.color,h.opacity.value=d.opacity):d instanceof THREE.LineDashedMaterial?(h.diffuse.value=d.color,h.opacity.value=d.opacity,h.dashSize.value=d.dashSize,h.totalSize.value=d.dashSize+d.gapSize,h.scale.value=d.scale):d instanceof THREE.ParticleBasicMaterial?
+(h.psColor.value=d.color,h.opacity.value=d.opacity,h.size.value=d.size,h.scale.value=t.getDomElement().height/2,h.map.value=d.map):d instanceof THREE.MeshPhongMaterial?(h.shininess.value=d.shininess,B.gammaInput?(h.ambient.value.copyGammaToLinear(d.ambient),h.emissive.value.copyGammaToLinear(d.emissive),h.specular.value.copyGammaToLinear(d.specular)):(h.ambient.value=d.ambient,h.emissive.value=d.emissive,h.specular.value=d.specular),d.wrapAround&&h.wrapRGB.value.copy(d.wrapRGB)):d instanceof THREE.MeshLambertMaterial?
+(B.gammaInput?(h.ambient.value.copyGammaToLinear(d.ambient),h.emissive.value.copyGammaToLinear(d.emissive)):(h.ambient.value=d.ambient,h.emissive.value=d.emissive),d.wrapAround&&h.wrapRGB.value.copy(d.wrapRGB)):d instanceof THREE.MeshDepthMaterial?(h.mNear.value=a.near,h.mFar.value=a.far,h.opacity.value=d.opacity):d instanceof THREE.MeshNormalMaterial&&(h.opacity.value=d.opacity);if(e.receiveShadow&&!d._shadowPass&&h.shadowMatrix){c=Q=0;for(f=b.length;c<f;c++)if(j=b[c],j.castShadow&&(j instanceof
+THREE.SpotLight||j instanceof THREE.DirectionalLight&&!j.shadowCascade))h.shadowMap.value[Q]=j.shadowMap,h.shadowMapSize.value[Q]=j.shadowMapSize,h.shadowMatrix.value[Q]=j.shadowMatrix,h.shadowDarkness.value[Q]=j.shadowDarkness,h.shadowBias.value[Q]=j.shadowBias,Q++}b=d.uniformsList;c=0;for(f=b.length;c<f;c++)if(Q=g.uniforms[b[c][1]])if(h=b[c][0],j=h.type,m=h.value,"i"===j)t.uniform1i(Q,m);else if("f"===j)t.uniform1f(Q,m);else if("v2"===j)t.uniform2f(Q,m.x,m.y);else if("v3"===j)t.uniform3f(Q,m.x,
+m.y,m.z);else if("v4"===j)t.uniform4f(Q,m.x,m.y,m.z,m.w);else if("c"===j)t.uniform3f(Q,m.r,m.g,m.b);else if("iv1"===j)t.uniform1iv(Q,m);else if("iv"===j)t.uniform3iv(Q,m);else if("fv1"===j)t.uniform1fv(Q,m);else if("fv"===j)t.uniform3fv(Q,m);else if("v2v"===j){void 0===h._array&&(h._array=new Float32Array(2*m.length));j=0;for(l=m.length;j<l;j++)u=2*j,h._array[u]=m[j].x,h._array[u+1]=m[j].y;t.uniform2fv(Q,h._array)}else if("v3v"===j){void 0===h._array&&(h._array=new Float32Array(3*m.length));j=0;for(l=
+m.length;j<l;j++)u=3*j,h._array[u]=m[j].x,h._array[u+1]=m[j].y,h._array[u+2]=m[j].z;t.uniform3fv(Q,h._array)}else if("v4v"===j){void 0===h._array&&(h._array=new Float32Array(4*m.length));j=0;for(l=m.length;j<l;j++)u=4*j,h._array[u]=m[j].x,h._array[u+1]=m[j].y,h._array[u+2]=m[j].z,h._array[u+3]=m[j].w;t.uniform4fv(Q,h._array)}else if("m4"===j)void 0===h._array&&(h._array=new Float32Array(16)),m.flattenToArray(h._array),t.uniformMatrix4fv(Q,h._array);else if("m4v"===j){void 0===h._array&&(h._array=
+new Float32Array(16*m.length));j=0;for(l=m.length;j<l;j++)m[j].flattenToArrayOffset(h._array,16*j);t.uniformMatrix4fv(Q,h._array)}else if("t"===j)u=q(),t.uniform1i(Q,u),m&&(m.image instanceof Array&&6===m.image.length?t.setCubeTexture(m,u):m instanceof THREE.WebGLRenderTargetCube?t.setCubeTextureDynamic(m,u):t.setTexture(m,u));else if("tv"===j){void 0===h._array&&(h._array=[]);j=0;for(l=h.value.length;j<l;j++)h._array[j]=q();t.uniform1iv(Q,h._array);j=0;for(l=h.value.length;j<l;j++)m=h.value[j],u=
+h._array[j],m&&t.setTexture(m,u)}if((d instanceof THREE.ShaderMaterial||d instanceof THREE.MeshPhongMaterial||d.envMap)&&null!==i.cameraPosition)K.getPositionFromMatrix(a.matrixWorld),t.uniform3f(i.cameraPosition,K.x,K.y,K.z);(d instanceof THREE.MeshPhongMaterial||d instanceof THREE.MeshLambertMaterial||d instanceof THREE.ShaderMaterial||d.skinning)&&null!==i.viewMatrix&&t.uniformMatrix4fv(i.viewMatrix,a.matrixWorldInverse.elements)}t.uniformMatrix4fv(i.modelViewMatrix,e._modelViewMatrix.elements);
+i.normalMatrix&&t.uniformMatrix3fv(i.normalMatrix,e._normalMatrix.elements);null!==i.modelMatrix&&t.uniformMatrix4fv(i.modelMatrix,e.matrixWorld.elements);return g}function q(){var a=s;a>=t.maxTextures&&console.warn("WebGLRenderer: trying to use "+a+" texture units while this GPU supports only "+t.maxTextures);s+=1;return a}function w(a,b){a._modelViewMatrix.multiplyMatrices(b.matrixWorldInverse,a.matrixWorld);a._normalMatrix.getInverse(a._modelViewMatrix);a._normalMatrix.transpose()}function v(a,
+b,c,d){a[b]=c.r*c.r*d;a[b+1]=c.g*c.g*d;a[b+2]=c.b*c.b*d}function z(a,b,c,d){a[b]=c.r*d;a[b+1]=c.g*d;a[b+2]=c.b*d}console.log("THREE.WebGLRenderer",THREE.REVISION);var a=a||{},y={memory:{programs:0,geometries:0,textures:0},render:{calls:0,vertices:0,faces:0,points:0}},t=new THREE.WebGLRenderer.LowLevelRenderer(a),D=new THREE.WebGLRenderer.MeshRenderer(t,y),C=new THREE.WebGLRenderer.ParticleRenderer(t,y),k=new THREE.WebGLRenderer.LineRenderer(t,y),I=new THREE.WebGLRenderer.RibbonRenderer(t,y),J=new THREE.WebGLRenderer.ShaderBuilder(t,
+y);this.autoUpdateScene=this.autoUpdateObjects=this.sortObjects=this.autoClearStencil=this.autoClearDepth=this.autoClearColor=this.autoClear=!0;this.shadowMapEnabled=this.physicallyBasedShading=this.gammaOutput=this.gammaInput=!1;this.shadowMapAutoUpdate=!0;this.shadowMapType=THREE.PCFShadowMap;this.shadowMapCullFace=THREE.CullFaceFront;this.shadowMapCascade=this.shadowMapDebug=!1;this.maxMorphTargets=8;this.maxMorphNormals=4;this.autoScaleCubemaps=!0;this.renderPluginsPre=[];this.renderPluginsPost=
+[];this.info=y;var B=this,P=null,A=-1,G=null,E=null,F=0,s=0,H=new THREE.Frustum,O=new THREE.Matrix4;new THREE.Matrix4;var K=new THREE.Vector3,x=new THREE.Vector3,N=!0,R={ambient:[0,0,0],directional:{length:0,colors:[],positions:[]},point:{length:0,colors:[],positions:[],distances:[]},spot:{length:0,colors:[],positions:[],distances:[],directions:[],anglesCos:[],exponents:[]},hemi:{length:0,skyColors:[],groundColors:[],positions:[]}};this.context=t.getContext();this.domElement=t.getDomElement();this.getPrecision=
+this.getPrecision=t.getPrecision;this.getContext=t.getContext;this.supportsVertexTextures=t.supportsVertexTextures;this.supportsFloatTextures=t.supportsFloatTextures;this.supportsStandardDerivatives=t.supportsStandardDerivatives;this.supportsCompressedTextureS3TC=t.supportsCompressedTextureS3TC;this.getMaxAnisotropy=t.getMaxAnisotropy;this.setSize=t.setSize;this.setViewport=t.setViewport;this.setScissor=t.setScissor;this.enableScissorTest=t.enableScissorTest;this.setDepthWrite=t.setDepthWrite;this.setDepthTest=
+t.setDepthTest;this.setRenderTarget=t.setRenderTarget;this.setBlending=t.setBlending;this.setTexture=t.setTexture;this.setMaterialFaces=t.setMaterialFaces;this.setFaceCulling=t.setFaceCulling;this.setClearColorHex=t.setClearColorHex;this.setClearColor=t.setClearColor;this.getClearColor=t.getClearColor;this.getClearAlpha=t.getClearAlpha;this.clear=t.clear;this.clearTarget=t.clearTarget;this.addPostPlugin=function(a){a.init(this);this.renderPluginsPost.push(a)};this.addPrePlugin=function(a){a.init(this);
+this.renderPluginsPre.push(a)};this.updateShadowMap=function(a,b){P=null;A=G=-1;N=!0;t.resetState();this.shadowMapPlugin.update(a,b)};var $=function(a){a=a.target;a.removeEventListener("dispose",$);var c,d;a.__webglInit=void 0;void 0!==a.__webglVertexBuffer&&t.deleteBuffer(a.__webglVertexBuffer);void 0!==a.__webglNormalBuffer&&t.deleteBuffer(a.__webglNormalBuffer);void 0!==a.__webglTangentBuffer&&t.deleteBuffer(a.__webglTangentBuffer);void 0!==a.__webglColorBuffer&&t.deleteBuffer(a.__webglColorBuffer);
+void 0!==a.__webglUVBuffer&&t.deleteBuffer(a.__webglUVBuffer);void 0!==a.__webglUV2Buffer&&t.deleteBuffer(a.__webglUV2Buffer);void 0!==a.__webglSkinIndicesBuffer&&t.deleteBuffer(a.__webglSkinIndicesBuffer);void 0!==a.__webglSkinWeightsBuffer&&t.deleteBuffer(a.__webglSkinWeightsBuffer);void 0!==a.__webglFaceBuffer&&t.deleteBuffer(a.__webglFaceBuffer);void 0!==a.__webglLineBuffer&&t.deleteBuffer(a.__webglLineBuffer);void 0!==a.__webglLineDistanceBuffer&&t.deleteBuffer(a.__webglLineDistanceBuffer);if(void 0!==
+a.geometryGroups)for(var e in a.geometryGroups){var f=a.geometryGroups[e];if(void 0!==f.numMorphTargets){c=0;for(d=f.numMorphTargets;c<d;c++)t.deleteBuffer(f.__webglMorphTargetsBuffers[c])}if(void 0!==f.numMorphNormals){c=0;for(d=f.numMorphNormals;c<d;c++)t.deleteBuffer(f.__webglMorphNormalsBuffers[c])}b(f)}b(a);B.info.memory.geometries--},Y=function(a){a=a.target;a.removeEventListener("dispose",Y);W(a)},W=function(a){var b=a.program;void 0!==b&&(a.program=void 0,J.removeProgram(b))};this.renderBufferImmediate=
+function(a,b,c){a.hasPositions&&!a.__webglVertexBuffer&&(a.__webglVertexBuffer=t.createBuffer());a.hasNormals&&!a.__webglNormalBuffer&&(a.__webglNormalBuffer=t.createBuffer());a.hasUvs&&!a.__webglUvBuffer&&(a.__webglUvBuffer=t.createBuffer());a.hasColors&&!a.__webglColorBuffer&&(a.__webglColorBuffer=t.createBuffer());a.hasPositions&&(t.setDynamicArrayBuffer(a.__webglVertexBuffer,a.positionArray),t.setFloatAttribute(b.attributes.position,a.__webglVertexBuffer,3,0));if(a.hasNormals){if(c.shading===
+THREE.FlatShading){var d,e,f,g,h,i,j,k,l,m,n,p=3*a.count;for(n=0;n<p;n+=9)m=a.normalArray,d=m[n],e=m[n+1],f=m[n+2],g=m[n+3],i=m[n+4],k=m[n+5],h=m[n+6],j=m[n+7],l=m[n+8],d=(d+g+h)/3,e=(e+i+j)/3,f=(f+k+l)/3,m[n]=d,m[n+1]=e,m[n+2]=f,m[n+3]=d,m[n+4]=e,m[n+5]=f,m[n+6]=d,m[n+7]=e,m[n+8]=f}t.setDynamicArrayBuffer(a.__webglNormalBuffer,a.normalArray);t.setFloatAttribute(b.attributes.normal,a.__webglNormalBuffer,3,0)}a.hasUvs&&c.map&&(t.setDynamicArrayBuffer(a.__webglUvBuffer,a.uvArray),t.setFloatAttribute(b.attributes.uv,
+a.__webglUvBuffer,2,0));a.hasColors&&c.vertexColors!==THREE.NoColors&&(t.setDynamicArrayBuffer(a.__webglColorBuffer,a.colorArray),t.setFloatAttribute(b.attributes.color,a.__webglColorBuffer,3,0));t.drawTriangles(a.count);a.count=0};this.renderBufferDirect=function(a,b,c,d,e,f){if(!1!==d.visible){var g,h,i;g=p(a,b,c,d,f);a=g.attributes;b=e.attributes;c=!1;g=16777215*e.id+2*g.id+(d.wireframe?1:0);g!==G&&(G=g,c=!0);c&&t.disableAttributes();if(f instanceof THREE.Mesh)if(d=b.index){e=e.offsets;1<e.length&&
+(c=!0);for(var j=0,k=e.length;j<k;j++){var l=e[j].index;if(c)for(h in b)"index"!==h&&(g=a[h],f=b[h],i=f.itemSize,0<=g&&t.setFloatAttribute(g,f.buffer,i,4*l*i));t.drawTriangleElements(d.buffer,e[j].count,2*e[j].start);B.info.render.calls++;B.info.render.vertices+=e[j].count;B.info.render.faces+=e[j].count/3}}else{if(c)for(h in b)g=a[h],f=b[h],i=f.itemSize,0<=g&&t.setFloatAttribute(g,f.buffer,i,0);h=e.attributes.position;t.drawTriangles(h.numItems/3);B.info.render.calls++;B.info.render.vertices+=h.numItems/
+3;B.info.render.faces+=h.numItems/3/3}else if(f instanceof THREE.ParticleSystem){if(c){for(h in b)g=a[h],f=b[h],i=f.itemSize,0<=g&&t.setFloatAttribute(g,f.buffer,i,0);h=b.position;t.drawPoints(h.numItems/3);B.info.render.calls++;B.info.render.points+=h.numItems/3}}else if(f instanceof THREE.Line&&c){for(h in b)g=a[h],f=b[h],i=f.itemSize,0<=g&&t.setFloatAttribute(g,f.buffer,i,0);h=b.position;t.setLineWidth(d.linewidth);t.drawLineStrip(h.numItems/3);B.info.render.calls++;B.info.render.points+=h.numItems}}};
+this.renderBuffer=function(a,b,c,d,e,f){if(!1!==d.visible){var h,c=p(a,b,c,d,f),a=c.attributes,b=!1,c=16777215*e.id+2*c.id+(d.wireframe?1:0);c!==G&&(G=c,b=!0);b&&t.disableAttributes();if(!d.morphTargets&&0<=a.position)b&&t.setFloatAttribute(a.position,e.__webglVertexBuffer,3,0);else if(f.morphTargetBase){c=d.program.attributes;-1!==f.morphTargetBase&&0<=c.position?t.setFloatAttribute(c.position,e.__webglMorphTargetsBuffers[f.morphTargetBase],3,0):0<=c.position&&t.setFloatAttribute(c.position,e.__webglVertexBuffer,
+3,0);if(f.morphTargetForcedOrder.length){var i=0,j=f.morphTargetForcedOrder;for(h=f.morphTargetInfluences;i<d.numSupportedMorphTargets&&i<j.length;)0<=c["morphTarget"+i]&&t.setFloatAttribute(c["morphTarget"+i],e.__webglMorphTargetsBuffers[j[i]],3,0),0<=c["morphNormal"+i]&&d.morphNormals&&t.setFloatAttribute(c["morphNormal"+i],e.__webglMorphNormalsBuffers[j[i]],3,0),f.__webglMorphTargetInfluences[i]=h[j[i]],i++}else{j=[];h=f.morphTargetInfluences;var k,l=h.length;for(k=0;k<l;k++)i=h[k],0<i&&j.push([i,
+k]);j.length>d.numSupportedMorphTargets?(j.sort(g),j.length=d.numSupportedMorphTargets):j.length>d.numSupportedMorphNormals?j.sort(g):0===j.length&&j.push([0,0]);for(i=0;i<d.numSupportedMorphTargets;)j[i]?(k=j[i][1],0<=c["morphTarget"+i]&&t.setFloatAttribute(c["morphTarget"+i],e.__webglMorphTargetsBuffers[k],3,0),0<=c["morphNormal"+i]&&d.morphNormals&&t.setFloatAttribute(c["morphNormal"+i],e.__webglMorphNormalsBuffers[k],3,0),f.__webglMorphTargetInfluences[i]=h[k]):f.__webglMorphTargetInfluences[i]=
+0,i++}null!==d.program.uniforms.morphTargetInfluences&&t.uniform1fv(d.program.uniforms.morphTargetInfluences,f.__webglMorphTargetInfluences)}if(b){if(e.__webglCustomAttributesList){c=0;for(h=e.__webglCustomAttributesList.length;c<h;c++)b=e.__webglCustomAttributesList[c],0<=a[b.buffer.belongsToAttribute]&&t.setFloatAttribute(a[b.buffer.belongsToAttribute],b.buffer,b.size,0)}0<=a.color&&t.setFloatAttribute(a.color,e.__webglColorBuffer,3,0);0<=a.normal&&t.setFloatAttribute(a.normal,e.__webglNormalBuffer,
+3,0);0<=a.tangent&&t.setFloatAttribute(a.tangent,e.__webglTangentBuffer,4,0);0<=a.uv&&t.setFloatAttribute(a.uv,e.__webglUVBuffer,2,0);0<=a.uv2&&t.setFloatAttribute(a.uv2,e.__webglUV2Buffer,2,0);d.skinning&&(0<=a.skinIndex&&0<=a.skinWeight)&&(t.setFloatAttribute(a.skinIndex,e.__webglSkinIndicesBuffer,4,0),t.setFloatAttribute(a.skinWeight,e.__webglSkinWeightsBuffer,4,0));0<=a.lineDistance&&t.setFloatAttribute(a.lineDistance,e.__webglLineDistanceBuffer,1,0)}f instanceof THREE.Mesh?(d.wireframe?(t.setLineWidth(d.wireframeLinewidth),
+t.drawLineElements(e.__webglLineBuffer,e.__webglLineCount,0)):t.drawTriangleElements(e.__webglFaceBuffer,e.__webglFaceCount,0),B.info.render.calls++,B.info.render.vertices+=e.__webglFaceCount,B.info.render.faces+=e.__webglFaceCount/3):f instanceof THREE.Line?(t.setLineWidth(d.linewidth),f.type===THREE.LineStrip?t.drawLineStrip(e.__webglLineCount):t.drawLines(e.__webglLineCount),B.info.render.calls++):f instanceof THREE.ParticleSystem?(t.drawPoints(e.__webglParticleCount),B.info.render.calls++,B.info.render.points+=
+e.__webglParticleCount):f instanceof THREE.Ribbon&&(t.drawTriangleStrip(e.__webglVertexCount),B.info.render.calls++)}};this.render=function(a,b,c,d){if(!1===b instanceof THREE.Camera)console.error("THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.");else{var e,g,k,l,m=a.__lights,n=a.fog;A=-1;N=!0;this.autoUpdateScene&&a.updateMatrixWorld();void 0===b.parent&&b.updateMatrixWorld();b.matrixWorldInverse.getInverse(b.matrixWorld);O.multiplyMatrices(b.projectionMatrix,b.matrixWorldInverse);
+H.setFromMatrix(O);this.autoUpdateObjects&&this.initWebGLObjects(a);h(this.renderPluginsPre,a,b);B.info.render.calls=0;B.info.render.vertices=0;B.info.render.faces=0;B.info.render.points=0;t.setRenderTarget(c);(this.autoClear||d)&&this.clear(this.autoClearColor,this.autoClearDepth,this.autoClearStencil);l=a.__webglObjects;d=0;for(e=l.length;d<e;d++)if(g=l[d],k=g.object,g.id=d,g.render=!1,k.visible&&(!(k instanceof THREE.Mesh||k instanceof THREE.ParticleSystem)||!k.frustumCulled||H.intersectsObject(k))){w(k,
+b);var p=g,r=p.buffer,q=void 0,s=q=void 0,s=p.object.material;if(s instanceof THREE.MeshFaceMaterial)q=r.materialIndex,q=s.materials[q],q.transparent?(p.transparent=q,p.opaque=null):(p.opaque=q,p.transparent=null);else if(q=s)q.transparent?(p.transparent=q,p.opaque=null):(p.opaque=q,p.transparent=null);g.render=!0;!0===this.sortObjects&&(null!==k.renderDepth?g.z=k.renderDepth:(K.getPositionFromMatrix(k.matrixWorld),K.applyProjection(O),g.z=K.z))}this.sortObjects&&l.sort(f);l=a.__webglObjectsImmediate;
+d=0;for(e=l.length;d<e;d++)g=l[d],k=g.object,k.visible&&(w(k,b),k=g.object.material,k.transparent?(g.transparent=k,g.opaque=null):(g.opaque=k,g.transparent=null));a.overrideMaterial?(d=a.overrideMaterial,t.setBlending(d.blending,d.blendEquation,d.blendSrc,d.blendDst),t.setDepthTest(d.depthTest),t.setDepthWrite(d.depthWrite),t.setPolygonOffset(d.polygonOffset,d.polygonOffsetFactor,d.polygonOffsetUnits),i(a.__webglObjects,!1,"",b,m,n,!0,d),j(a.__webglObjectsImmediate,"",b,m,n,!1,d)):(d=null,t.setBlending(THREE.NoBlending),
+i(a.__webglObjects,!0,"opaque",b,m,n,!1,d),j(a.__webglObjectsImmediate,"opaque",b,m,n,!1,d),i(a.__webglObjects,!1,"transparent",b,m,n,!0,d),j(a.__webglObjectsImmediate,"transparent",b,m,n,!0,d));h(this.renderPluginsPost,a,b);c&&(c.generateMipmaps&&c.minFilter!==THREE.NearestFilter&&c.minFilter!==THREE.LinearFilter)&&t.updateRenderTargetMipmap(c);t.setDepthTest(!0);t.setDepthWrite(!0)}};this.renderImmediateObject=function(a,b,c,d,e){var f=p(a,b,c,d,e);G=-1;t.setMaterialFaces(d);e.immediateRenderCallback?
+e.immediateRenderCallback(f,t.getContext(),H):e.render(function(a){B.renderBufferImmediate(a,f,d)})};this.initWebGLObjects=function(a){a.__webglObjects||(a.__webglObjects=[],a.__webglObjectsImmediate=[],a.__webglSprites=[],a.__webglFlares=[]);for(;a.__objectsAdded.length;){var b=a.__objectsAdded[0],f=a,g=void 0,h=void 0,i=void 0,j=void 0;if(!b.__webglInit)if(b.__webglInit=!0,b._modelViewMatrix=new THREE.Matrix4,b._normalMatrix=new THREE.Matrix3,void 0!==b.geometry&&void 0===b.geometry.__webglInit&&
+(b.geometry.__webglInit=!0,b.geometry.addEventListener("dispose",$)),b instanceof THREE.Mesh)if(h=b.geometry,i=b.material,h instanceof THREE.Geometry){if(void 0===h.geometryGroups){var j=h,p=void 0,q=void 0,L=void 0,s=void 0,t=void 0,v=void 0,w={},x=j.morphTargets.length,y=j.morphNormals.length,i=i instanceof THREE.MeshFaceMaterial;j.geometryGroups={};p=0;for(q=j.faces.length;p<q;p++)L=j.faces[p],s=i?L.materialIndex:0,void 0===w[s]&&(w[s]={hash:s,counter:0}),v=w[s].hash+"_"+w[s].counter,void 0===
+j.geometryGroups[v]&&(j.geometryGroups[v]={faces3:[],faces4:[],materialIndex:s,vertices:0,numMorphTargets:x,numMorphNormals:y}),t=L instanceof THREE.Face3?3:4,65535<j.geometryGroups[v].vertices+t&&(w[s].counter+=1,v=w[s].hash+"_"+w[s].counter,void 0===j.geometryGroups[v]&&(j.geometryGroups[v]={faces3:[],faces4:[],materialIndex:s,vertices:0,numMorphTargets:x,numMorphNormals:y})),L instanceof THREE.Face3?j.geometryGroups[v].faces3.push(p):j.geometryGroups[v].faces4.push(p),j.geometryGroups[v].vertices+=
+t;j.geometryGroupsList=[];p=void 0;for(p in j.geometryGroups)j.geometryGroups[p].id=F++,j.geometryGroupsList.push(j.geometryGroups[p])}for(g in h.geometryGroups)j=h.geometryGroups[g],j.__webglVertexBuffer||(D.createBuffers(j),D.initBuffers(j,b),h.verticesNeedUpdate=!0,h.morphTargetsNeedUpdate=!0,h.elementsNeedUpdate=!0,h.uvsNeedUpdate=!0,h.normalsNeedUpdate=!0,h.tangentsNeedUpdate=!0,h.colorsNeedUpdate=!0)}else h instanceof THREE.BufferGeometry&&d(h);else b instanceof THREE.Ribbon?(h=b.geometry,h.__webglVertexBuffer||
+(I.createBuffers(h),I.initBuffers(h,b),h.verticesNeedUpdate=!0,h.colorsNeedUpdate=!0,h.normalsNeedUpdate=!0)):b instanceof THREE.Line?(h=b.geometry,h.__webglVertexBuffer||(h instanceof THREE.Geometry?(k.createBuffers(h),k.initBuffers(h,b),h.verticesNeedUpdate=!0,h.colorsNeedUpdate=!0,h.lineDistancesNeedUpdate=!0):h instanceof THREE.BufferGeometry&&d(h))):b instanceof THREE.ParticleSystem&&(h=b.geometry,h.__webglVertexBuffer||(h instanceof THREE.Geometry?(C.createBuffers(h),C.initBuffers(h,b),h.verticesNeedUpdate=
+!0,h.colorsNeedUpdate=!0):h instanceof THREE.BufferGeometry&&d(h)));if(!b.__webglActive){if(b instanceof THREE.Mesh)if(h=b.geometry,h instanceof THREE.BufferGeometry)l(f.__webglObjects,h,b);else{if(h instanceof THREE.Geometry)for(g in h.geometryGroups)j=h.geometryGroups[g],l(f.__webglObjects,j,b)}else b instanceof THREE.Ribbon||b instanceof THREE.Line||b instanceof THREE.ParticleSystem?(h=b.geometry,l(f.__webglObjects,h,b)):b instanceof THREE.ImmediateRenderObject||b.immediateRenderCallback?f.__webglObjectsImmediate.push({object:b,
+opaque:null,transparent:null}):b instanceof THREE.Sprite?f.__webglSprites.push(b):b instanceof THREE.LensFlare&&f.__webglFlares.push(b);b.__webglActive=!0}a.__objectsAdded.splice(0,1)}for(;a.__objectsRemoved.length;)b=a.__objectsRemoved[0],f=a,b instanceof THREE.Mesh||b instanceof THREE.ParticleSystem||b instanceof THREE.Ribbon||b instanceof THREE.Line?r(f.__webglObjects,b):b instanceof THREE.Sprite?u(f.__webglSprites,b):b instanceof THREE.LensFlare?u(f.__webglFlares,b):(b instanceof THREE.ImmediateRenderObject||
+b.immediateRenderCallback)&&r(f.__webglObjectsImmediate,b),b.__webglActive=!1,a.__objectsRemoved.splice(0,1);b=0;for(f=a.__webglObjects.length;b<f;b++)if(g=a.__webglObjects[b].object,h=g.geometry,q=p=j=void 0,g instanceof THREE.Mesh)if(h instanceof THREE.BufferGeometry)(h.verticesNeedUpdate||h.elementsNeedUpdate||h.uvsNeedUpdate||h.normalsNeedUpdate||h.colorsNeedUpdate||h.tangentsNeedUpdate)&&e(h,!h.dynamic),h.verticesNeedUpdate=!1,h.elementsNeedUpdate=!1,h.uvsNeedUpdate=!1,h.normalsNeedUpdate=!1,
+h.colorsNeedUpdate=!1,h.tangentsNeedUpdate=!1;else{L=0;for(s=h.geometryGroupsList.length;L<s;L++)j=h.geometryGroupsList[L],q=c(g,j),h.buffersNeedUpdate&&D.initBuffers(j,g),p=q.attributes&&n(q),(h.verticesNeedUpdate||h.morphTargetsNeedUpdate||h.elementsNeedUpdate||h.uvsNeedUpdate||h.normalsNeedUpdate||h.colorsNeedUpdate||h.tangentsNeedUpdate||p)&&D.setBuffers(j,g,!h.dynamic,q);h.verticesNeedUpdate=!1;h.morphTargetsNeedUpdate=!1;h.elementsNeedUpdate=!1;h.uvsNeedUpdate=!1;h.normalsNeedUpdate=!1;h.colorsNeedUpdate=
+!1;h.tangentsNeedUpdate=!1;h.buffersNeedUpdate=!1;q.attributes&&m(q)}else g instanceof THREE.Ribbon?(q=c(g,h),p=q.attributes&&n(q),(h.verticesNeedUpdate||h.colorsNeedUpdate||h.normalsNeedUpdate||p)&&I.setBuffers(h),h.verticesNeedUpdate=!1,h.colorsNeedUpdate=!1,h.normalsNeedUpdate=!1,q.attributes&&m(q)):g instanceof THREE.Line?h instanceof THREE.BufferGeometry?((h.verticesNeedUpdate||h.colorsNeedUpdate)&&e(h,!h.dynamic),h.verticesNeedUpdate=!1,h.colorsNeedUpdate=!1):(q=c(g,h),p=q.attributes&&n(q),
+(h.verticesNeedUpdate||h.colorsNeedUpdate||h.lineDistancesNeedUpdate||p)&&k.setBuffers(h),h.verticesNeedUpdate=!1,h.colorsNeedUpdate=!1,h.lineDistancesNeedUpdate=!1,q.attributes&&m(q)):g instanceof THREE.ParticleSystem&&(h instanceof THREE.BufferGeometry?((h.verticesNeedUpdate||h.colorsNeedUpdate)&&e(h,!h.dynamic),h.verticesNeedUpdate=!1,h.colorsNeedUpdate=!1):(q=c(g,h),p=q.attributes&&n(q),(h.verticesNeedUpdate||h.colorsNeedUpdate||g.sortParticles||p)&&C.setBuffers(h,g,O),h.verticesNeedUpdate=!1,
+h.colorsNeedUpdate=!1,q.attributes&&m(q)))};this.initMaterial=function(a,b,c,d){var e,f,g,h;a.addEventListener("dispose",Y);var i,j,k;a instanceof THREE.MeshDepthMaterial?k="depth":a instanceof THREE.MeshNormalMaterial?k="normal":a instanceof THREE.MeshBasicMaterial?k="basic":a instanceof THREE.MeshLambertMaterial?k="lambert":a instanceof THREE.MeshPhongMaterial?k="phong":a instanceof THREE.LineBasicMaterial?k="basic":a instanceof THREE.LineDashedMaterial?k="dashed":a instanceof THREE.ParticleBasicMaterial&&
+(k="particle_basic");k&&(e=THREE.ShaderLib[k],a.uniforms=THREE.UniformsUtils.clone(e.uniforms),a.vertexShader=e.vertexShader,a.fragmentShader=e.fragmentShader);var l,m;e=m=f=g=h=0;for(j=b.length;e<j;e++)l=b[e],l.onlyShadow||(l instanceof THREE.DirectionalLight&&m++,l instanceof THREE.PointLight&&f++,l instanceof THREE.SpotLight&&g++,l instanceof THREE.HemisphereLight&&h++);e=m;var n=0;j=0;for(l=b.length;j<l;j++)m=b[j],m.castShadow&&(m instanceof THREE.SpotLight&&n++,m instanceof THREE.DirectionalLight&&
+!m.shadowCascade&&n++);b=n;t.supportsBoneTextures&&d&&d.useVertexTexture?j=1024:(j=Math.floor((t.maxVertexUniformVectors-20)/4),void 0!==d&&d instanceof THREE.SkinnedMesh&&(j=Math.min(d.bones.length,j),j<d.bones.length&&console.warn("WebGLRenderer: too many bones - "+d.bones.length+", this GPU supports just "+j+" (try OpenGL instead of ANGLE)")));a.program=J.buildProgram(k,a.fragmentShader,a.vertexShader,a.uniforms,a.attributes,a.defines,{map:!!a.map,envMap:!!a.envMap,lightMap:!!a.lightMap,bumpMap:!!a.bumpMap,
+normalMap:!!a.normalMap,specularMap:!!a.specularMap,vertexColors:a.vertexColors,fog:c,useFog:a.fog,fogExp:c instanceof THREE.FogExp2,sizeAttenuation:a.sizeAttenuation,skinning:a.skinning,maxBones:j,useVertexTexture:t.supportsBoneTextures&&d&&d.useVertexTexture,boneTextureWidth:d&&d.boneTextureWidth,boneTextureHeight:d&&d.boneTextureHeight,morphTargets:a.morphTargets,morphNormals:a.morphNormals,maxMorphTargets:this.maxMorphTargets,maxMorphNormals:this.maxMorphNormals,maxDirLights:e,maxPointLights:f,
+maxSpotLights:g,maxHemiLights:h,maxShadows:b,shadowMapEnabled:this.shadowMapEnabled&&d.receiveShadow,shadowMapType:this.shadowMapType,shadowMapDebug:this.shadowMapDebug,shadowMapCascade:this.shadowMapCascade,alphaTest:a.alphaTest,metal:a.metal,perPixel:a.perPixel,wrapAround:a.wrapAround,doubleSided:a.side===THREE.DoubleSide,flipSided:a.side===THREE.BackSide,gammaInput:this.gammaInput,gammaOutput:this.gammaOutput,physicallyBasedShading:this.physicallyBasedShading});d=a.program.attributes;if(a.morphTargets){a.numSupportedMorphTargets=
+0;b="morphTarget";for(c=0;c<this.maxMorphTargets;c++)k=b+c,0<=d[k]&&a.numSupportedMorphTargets++}if(a.morphNormals){a.numSupportedMorphNormals=0;b="morphNormal";for(c=0;c<this.maxMorphNormals;c++)k=b+c,0<=d[k]&&a.numSupportedMorphNormals++}a.uniformsList=[];for(i in a.uniforms)a.uniformsList.push([a.uniforms[i],i])};this.shadowMapPlugin=new THREE.ShadowMapPlugin;this.addPrePlugin(this.shadowMapPlugin);this.addPostPlugin(new THREE.SpritePlugin);this.addPostPlugin(new THREE.LensFlarePlugin)};THREE.WebGLRenderer.LowLevelRenderer=function(a){function b(a){return a===THREE.NearestFilter||a===THREE.NearestMipMapNearestFilter||a===THREE.NearestMipMapLinearFilter?k.NEAREST:k.LINEAR}function c(a,b,c,d){M=void 0!==a?a:0;la=void 0!==b?b:0;na=void 0!==c?c:r.width;qa=void 0!==d?d:r.height;k.viewport(M,la,na,qa)}function d(a,b,c){var d=0;if(void 0===a||a)d|=k.COLOR_BUFFER_BIT;if(void 0===b||b)d|=k.DEPTH_BUFFER_BIT;if(void 0===c||c)d|=k.STENCIL_BUFFER_BIT;k.clear(d)}function e(a){aa!=a&&(k.bindBuffer(k.ARRAY_BUFFER,
+a),aa=a)}function f(a){aa!=a&&(k.bindBuffer(k.ELEMENT_ARRAY_BUFFER,a),aa=a)}function g(a){s[a]||(k.enableVertexAttribArray(a),s[a]=!0)}function h(a,c,d){d?(k.texParameteri(a,k.TEXTURE_WRAP_S,l(c.wrapS)),k.texParameteri(a,k.TEXTURE_WRAP_T,l(c.wrapT)),k.texParameteri(a,k.TEXTURE_MAG_FILTER,l(c.magFilter)),k.texParameteri(a,k.TEXTURE_MIN_FILTER,l(c.minFilter))):(k.texParameteri(a,k.TEXTURE_WRAP_S,k.CLAMP_TO_EDGE),k.texParameteri(a,k.TEXTURE_WRAP_T,k.CLAMP_TO_EDGE),k.texParameteri(a,k.TEXTURE_MAG_FILTER,
+b(c.magFilter)),k.texParameteri(a,k.TEXTURE_MIN_FILTER,b(c.minFilter)));if(B&&c.type!==THREE.FloatType&&(1<c.anisotropy||c.__oldAnisotropy))k.texParameterf(a,B.TEXTURE_MAX_ANISOTROPY_EXT,Math.min(c.anisotropy,E)),c.__oldAnisotropy=c.anisotropy}function i(a,b){k.bindRenderbuffer(k.RENDERBUFFER,a);b.depthBuffer&&!b.stencilBuffer?(k.renderbufferStorage(k.RENDERBUFFER,k.DEPTH_COMPONENT16,b.width,b.height),k.framebufferRenderbuffer(k.FRAMEBUFFER,k.DEPTH_ATTACHMENT,k.RENDERBUFFER,a)):b.depthBuffer&&b.stencilBuffer?
+(k.renderbufferStorage(k.RENDERBUFFER,k.DEPTH_STENCIL,b.width,b.height),k.framebufferRenderbuffer(k.FRAMEBUFFER,k.DEPTH_STENCIL_ATTACHMENT,k.RENDERBUFFER,a)):k.renderbufferStorage(k.RENDERBUFFER,k.RGBA4,b.width,b.height)}function j(a){var b=a instanceof THREE.WebGLRenderTargetCube;if(a&&!a.__webglFramebuffer){void 0===a.depthBuffer&&(a.depthBuffer=!0);void 0===a.stencilBuffer&&(a.stencilBuffer=!0);a.__webglTexture=k.createTexture();var c=0===(a.width&a.width-1)&&0===(a.height&a.height-1),d=l(a.format),
+e=l(a.type);if(b){a.__webglFramebuffer=[];a.__webglRenderbuffer=[];k.bindTexture(k.TEXTURE_CUBE_MAP,a.__webglTexture);h(k.TEXTURE_CUBE_MAP,a,c);for(var f=0;6>f;f++){a.__webglFramebuffer[f]=k.createFramebuffer();a.__webglRenderbuffer[f]=k.createRenderbuffer();k.texImage2D(k.TEXTURE_CUBE_MAP_POSITIVE_X+f,0,d,a.width,a.height,0,d,e,null);var g=a,j=k.TEXTURE_CUBE_MAP_POSITIVE_X+f;k.bindFramebuffer(k.FRAMEBUFFER,a.__webglFramebuffer[f]);k.framebufferTexture2D(k.FRAMEBUFFER,k.COLOR_ATTACHMENT0,j,g.__webglTexture,
+0);i(a.__webglRenderbuffer[f],a)}c&&k.generateMipmap(k.TEXTURE_CUBE_MAP)}else a.__webglFramebuffer=k.createFramebuffer(),a.__webglRenderbuffer=a.shareDepthFrom?a.shareDepthFrom.__webglRenderbuffer:k.createRenderbuffer(),k.bindTexture(k.TEXTURE_2D,a.__webglTexture),h(k.TEXTURE_2D,a,c),k.texImage2D(k.TEXTURE_2D,0,d,a.width,a.height,0,d,e,null),d=k.TEXTURE_2D,k.bindFramebuffer(k.FRAMEBUFFER,a.__webglFramebuffer),k.framebufferTexture2D(k.FRAMEBUFFER,k.COLOR_ATTACHMENT0,d,a.__webglTexture,0),a.shareDepthFrom?
+a.depthBuffer&&!a.stencilBuffer?k.framebufferRenderbuffer(k.FRAMEBUFFER,k.DEPTH_ATTACHMENT,k.RENDERBUFFER,a.__webglRenderbuffer):a.depthBuffer&&a.stencilBuffer&&k.framebufferRenderbuffer(k.FRAMEBUFFER,k.DEPTH_STENCIL_ATTACHMENT,k.RENDERBUFFER,a.__webglRenderbuffer):i(a.__webglRenderbuffer,a),c&&k.generateMipmap(k.TEXTURE_2D);b?k.bindTexture(k.TEXTURE_CUBE_MAP,null):k.bindTexture(k.TEXTURE_2D,null);k.bindRenderbuffer(k.RENDERBUFFER,null);k.bindFramebuffer(k.FRAMEBUFFER,null)}a?(b=b?a.__webglFramebuffer[a.activeCubeFace]:
+a.__webglFramebuffer,c=a.width,a=a.height,e=d=0):(b=null,c=na,a=qa,d=M,e=la);b!==T&&(k.bindFramebuffer(k.FRAMEBUFFER,b),k.viewport(d,e,c,a),T=b);D=c;C=a}function l(a){if(a===THREE.RepeatWrapping)return k.REPEAT;if(a===THREE.ClampToEdgeWrapping)return k.CLAMP_TO_EDGE;if(a===THREE.MirroredRepeatWrapping)return k.MIRRORED_REPEAT;if(a===THREE.NearestFilter)return k.NEAREST;if(a===THREE.NearestMipMapNearestFilter)return k.NEAREST_MIPMAP_NEAREST;if(a===THREE.NearestMipMapLinearFilter)return k.NEAREST_MIPMAP_LINEAR;
+if(a===THREE.LinearFilter)return k.LINEAR;if(a===THREE.LinearMipMapNearestFilter)return k.LINEAR_MIPMAP_NEAREST;if(a===THREE.LinearMipMapLinearFilter)return k.LINEAR_MIPMAP_LINEAR;if(a===THREE.UnsignedByteType)return k.UNSIGNED_BYTE;if(a===THREE.UnsignedShort4444Type)return k.UNSIGNED_SHORT_4_4_4_4;if(a===THREE.UnsignedShort5551Type)return k.UNSIGNED_SHORT_5_5_5_1;if(a===THREE.UnsignedShort565Type)return k.UNSIGNED_SHORT_5_6_5;if(a===THREE.ByteType)return k.BYTE;if(a===THREE.ShortType)return k.SHORT;
+if(a===THREE.UnsignedShortType)return k.UNSIGNED_SHORT;if(a===THREE.IntType)return k.INT;if(a===THREE.UnsignedIntType)return k.UNSIGNED_INT;if(a===THREE.FloatType)return k.FLOAT;if(a===THREE.AlphaFormat)return k.ALPHA;if(a===THREE.RGBFormat)return k.RGB;if(a===THREE.RGBAFormat)return k.RGBA;if(a===THREE.LuminanceFormat)return k.LUMINANCE;if(a===THREE.LuminanceAlphaFormat)return k.LUMINANCE_ALPHA;if(a===THREE.AddEquation)return k.FUNC_ADD;if(a===THREE.SubtractEquation)return k.FUNC_SUBTRACT;if(a===
+THREE.ReverseSubtractEquation)return k.FUNC_REVERSE_SUBTRACT;if(a===THREE.ZeroFactor)return k.ZERO;if(a===THREE.OneFactor)return k.ONE;if(a===THREE.SrcColorFactor)return k.SRC_COLOR;if(a===THREE.OneMinusSrcColorFactor)return k.ONE_MINUS_SRC_COLOR;if(a===THREE.SrcAlphaFactor)return k.SRC_ALPHA;if(a===THREE.OneMinusSrcAlphaFactor)return k.ONE_MINUS_SRC_ALPHA;if(a===THREE.DstAlphaFactor)return k.DST_ALPHA;if(a===THREE.OneMinusDstAlphaFactor)return k.ONE_MINUS_DST_ALPHA;if(a===THREE.DstColorFactor)return k.DST_COLOR;
+if(a===THREE.OneMinusDstColorFactor)return k.ONE_MINUS_DST_COLOR;if(a===THREE.SrcAlphaSaturateFactor)return k.SRC_ALPHA_SATURATE;if(void 0!==P){if(a===THREE.RGB_S3TC_DXT1_Format)return P.COMPRESSED_RGB_S3TC_DXT1_EXT;if(a===THREE.RGBA_S3TC_DXT1_Format)return P.COMPRESSED_RGBA_S3TC_DXT1_EXT;if(a===THREE.RGBA_S3TC_DXT3_Format)return P.COMPRESSED_RGBA_S3TC_DXT3_EXT;if(a===THREE.RGBA_S3TC_DXT5_Format)return P.COMPRESSED_RGBA_S3TC_DXT5_EXT}return 0}function n(a,b){var c;"fragment"===a?c=k.createShader(k.FRAGMENT_SHADER):
+"vertex"===a&&(c=k.createShader(k.VERTEX_SHADER));k.shaderSource(c,b);k.compileShader(c);return!k.getShaderParameter(c,k.COMPILE_STATUS)?(console.error(k.getShaderInfoLog(c)),console.error(m(b)),null):c}function m(a){for(var a=a.split("\n"),b=0,c=a.length;b<c;b++)a[b]=b+1+": "+a[b];return a.join("\n")}var a=a||{},r=void 0!==a.canvas?a.canvas:document.createElement("canvas"),u=void 0!==a.precision?a.precision:"highp",p=void 0!==a.alpha?a.alpha:!0,q=void 0!==a.premultipliedAlpha?a.premultipliedAlpha:
+!0,w=void 0!==a.antialias?a.antialias:!1,v=void 0!==a.stencil?a.stencil:!0,z=void 0!==a.preserveDrawingBuffer?a.preserveDrawingBuffer:!1,y=void 0!==a.clearColor?new THREE.Color(a.clearColor):new THREE.Color(0),t=void 0!==a.clearAlpha?a.clearAlpha:0;this.devicePixelRatio=void 0!==a.devicePixelRatio?a.devicePixelRatio:void 0!==window.devicePixelRatio?window.devicePixelRatio:1;var D=0,C=0,k,I,J,B,P;try{if(!(k=r.getContext("experimental-webgl",{alpha:p,premultipliedAlpha:q,antialias:w,stencil:v,preserveDrawingBuffer:z})))throw"Error creating WebGL context.";
+}catch(A){console.error(A)}I=k.getExtension("OES_texture_float");J=k.getExtension("OES_standard_derivatives");B=k.getExtension("EXT_texture_filter_anisotropic")||k.getExtension("MOZ_EXT_texture_filter_anisotropic")||k.getExtension("WEBKIT_EXT_texture_filter_anisotropic");P=k.getExtension("WEBGL_compressed_texture_s3tc")||k.getExtension("MOZ_WEBGL_compressed_texture_s3tc")||k.getExtension("WEBKIT_WEBGL_compressed_texture_s3tc");I||console.log("THREE.WebGLRenderer: Float textures not supported.");J||
+console.log("THREE.WebGLRenderer: Standard derivatives not supported.");B||console.log("THREE.WebGLRenderer: Anisotropic texture filtering not supported.");P||console.log("THREE.WebGLRenderer: S3TC compressed textures not supported.");void 0===k.getShaderPrecisionFormat&&(k.getShaderPrecisionFormat=function(){return{rangeMin:1,rangeMax:1,precision:1}});k.clearColor(0,0,0,1);k.clearDepth(1);k.clearStencil(0);k.enable(k.DEPTH_TEST);k.depthFunc(k.LEQUAL);k.frontFace(k.CCW);k.cullFace(k.BACK);k.enable(k.CULL_FACE);
+k.enable(k.BLEND);k.blendEquation(k.FUNC_ADD);k.blendFunc(k.SRC_ALPHA,k.ONE_MINUS_SRC_ALPHA);k.clearColor(y.r,y.g,y.b,t);k.getParameter(k.MAX_TEXTURE_IMAGE_UNITS);a=k.getParameter(k.MAX_VERTEX_TEXTURE_IMAGE_UNITS);k.getParameter(k.MAX_TEXTURE_SIZE);var G=k.getParameter(k.MAX_CUBE_MAP_TEXTURE_SIZE),E=B?k.getParameter(B.MAX_TEXTURE_MAX_ANISOTROPY_EXT):0,F=0<a,a=F&&I;P&&k.getParameter(k.COMPRESSED_TEXTURE_FORMATS);w=k.getShaderPrecisionFormat(k.VERTEX_SHADER,k.HIGH_FLOAT);p=k.getShaderPrecisionFormat(k.VERTEX_SHADER,
+k.MEDIUM_FLOAT);k.getShaderPrecisionFormat(k.VERTEX_SHADER,k.LOW_FLOAT);v=k.getShaderPrecisionFormat(k.FRAGMENT_SHADER,k.HIGH_FLOAT);q=k.getShaderPrecisionFormat(k.FRAGMENT_SHADER,k.MEDIUM_FLOAT);k.getShaderPrecisionFormat(k.FRAGMENT_SHADER,k.LOW_FLOAT);k.getShaderPrecisionFormat(k.VERTEX_SHADER,k.HIGH_INT);k.getShaderPrecisionFormat(k.VERTEX_SHADER,k.MEDIUM_INT);k.getShaderPrecisionFormat(k.VERTEX_SHADER,k.LOW_INT);k.getShaderPrecisionFormat(k.FRAGMENT_SHADER,k.HIGH_INT);k.getShaderPrecisionFormat(k.FRAGMENT_SHADER,
+k.MEDIUM_INT);k.getShaderPrecisionFormat(k.FRAGMENT_SHADER,k.LOW_INT);w=0<w.precision&&0<v.precision;p=0<p.precision&&0<q.precision;"highp"===u&&!w&&(p?(u="mediump",console.warn("WebGLRenderer: highp not supported, using mediump")):(u="lowp",console.warn("WebGLRenderer: highp and mediump not supported, using lowp")));"mediump"===u&&!p&&(u="lowp",console.warn("WebGLRenderer: mediump not supported, using lowp"));var s={},H,O,K,x,N=-1,R=-1,$=-1,Y=-1,W=-1,M=0,la=0,na=0,qa=0,X=null,S=null,Z=null,T=null,
+aa;return{context:k,autoScaleCubemaps:!0,supportsBoneTextures:a,precision:u,maxVertexUniformVectors:k.getParameter(k.MAX_VERTEX_UNIFORM_VECTORS),getContext:function(){return k},getDomElement:function(){return r},getPrecision:function(){return u},getCurrentWidth:function(){return D},getCurrentHeight:function(){return C},supportsVertexTextures:function(){return F},supportsFloatTextures:function(){return I},supportsStandardDerivatives:function(){return J},supportsCompressedTextureS3TC:function(){return P},
+getMaxAnisotropy:function(){return E},setRenderTarget:j,setSize:function(a,b){r.width=a;r.height=b;c(0,0,r.width,r.height)},setViewport:c,setScissor:function(a,b,c,d){k.scissor(a,b,c,d)},enableScissorTest:function(a){a?k.enable(k.SCISSOR_TEST):k.disable(k.SCISSOR_TEST)},setClearColorHex:function(a,b){y.setHex(a);t=b;k.clearColor(y.r,y.g,y.b,t)},setClearColor:function(a,b){y.copy(a);t=b;k.clearColor(y.r,y.g,y.b,t)},getClearColor:function(){return y},getClearAlpha:function(){return t},clear:d,clearTarget:function(a,
+b,c,e){j(a);d(b,c,e)},deleteBuffer:function(a){k.deleteBuffer(a)},deleteTexture:function(a){k.deleteTexture(a)},deleteFramebuffer:function(a){k.deleteFramebuffer(a)},deleteRenderbuffer:function(a){k.deleteRenderbuffer(a)},deleteProgram:function(a){k.deleteProgram(a)},createBuffer:function(){return k.createBuffer()},setStaticArrayBuffer:function(a,b){e(a);k.bufferData(k.ARRAY_BUFFER,b,k.STATIC_DRAW)},setStaticIndexBuffer:function(a,b){f(a);k.bufferData(k.ELEMENT_ARRAY_BUFFER,b,k.STATIC_DRAW)},setDynamicArrayBuffer:function(a,
+b){e(a);k.bufferData(k.ARRAY_BUFFER,b,k.DYNAMIC_DRAW)},setDynamicIndexBuffer:function(a,b){f(a);k.bufferData(k.ELEMENT_ARRAY_BUFFER,b,k.DYNAMIC_DRAW)},drawTriangles:function(a){k.drawArrays(k.TRIANGLES,0,a)},drawTriangleStrip:function(a){k.drawArrays(k.TRIANGLE_STRIP,0,a)},drawLines:function(a){k.drawArrays(k.LINES,0,a)},drawLineStrip:function(a){k.drawArrays(k.LINE_STRIP,0,a)},drawPoints:function(a){k.drawArrays(k.POINTS,0,a)},drawTriangleElements:function(a,b,c){f(a);k.drawElements(k.TRIANGLES,
+b,k.UNSIGNED_SHORT,c)},drawLineElements:function(a,b,c){f(a);k.drawElements(k.LINES,b,k.UNSIGNED_SHORT,c)},bindArrayBuffer:e,bindElementArrayBuffer:f,enableAttribute:g,disableAttributes:function(){for(var a in s)s[a]&&(k.disableVertexAttribArray(a),s[a]=!1)},getAttribLocation:function(a,b){return k.getAttribLocation(a,b)},setFloatAttribute:function(a,b,c,d){e(b);g(a);k.vertexAttribPointer(a,c,k.FLOAT,!1,0,d)},getUniformLocation:function(a,b){return k.getUniformLocation(a,b)},uniform1i:function(a,
+b){k.uniform1i(a,b)},uniform1f:function(a,b){k.uniform1f(a,b)},uniform2f:function(a,b,c){k.uniform2f(a,b,c)},uniform3f:function(a,b,c,d){k.uniform3f(a,b,c,d)},uniform4f:function(a,b,c,d,e){k.uniform4f(a,b,c,d,e)},uniform1iv:function(a,b){k.uniform1iv(a,b)},uniform2iv:function(a,b){k.uniform2iv(a,b)},uniform3iv:function(a,b){k.uniform3iv(a,b)},uniform1fv:function(a,b){k.uniform1fv(a,b)},uniform2fv:function(a,b){k.uniform2fv(a,b)},uniform3fv:function(a,b){k.uniform3fv(a,b)},uniform4fv:function(a,b){k.uniform3fv(a,
+b)},uniformMatrix3fv:function(a,b){k.uniformMatrix3fv(a,!1,b)},uniformMatrix4fv:function(a,b){k.uniformMatrix4fv(a,!1,b)},useProgram:function(a){k.useProgram(a)},compileShader:function(a,b){var c=k.createProgram(),d=n("fragment",b),e=n("vertex",a);k.attachShader(c,e);k.attachShader(c,d);k.linkProgram(c);k.getProgramParameter(c,k.LINK_STATUS)||console.error("Could not initialise shader\nVALIDATE_STATUS: "+k.getProgramParameter(c,k.VALIDATE_STATUS)+", gl error ["+k.getError()+"]");k.deleteShader(d);
+k.deleteShader(e);return c},setFaceCulling:function(a,b){a===THREE.CullFaceNone?k.disable(k.CULL_FACE):(b===THREE.FrontFaceDirectionCW?k.frontFace(k.CW):k.frontFace(k.CCW),a===THREE.CullFaceBack?k.cullFace(k.BACK):a===THREE.CullFaceFront?k.cullFace(k.FRONT):k.cullFace(k.FRONT_AND_BACK),k.enable(k.CULL_FACE))},setMaterialFaces:function(a){var b=a.side===THREE.DoubleSide,a=a.side===THREE.BackSide;N!==b&&(b?k.disable(k.CULL_FACE):k.enable(k.CULL_FACE),N=b);R!==a&&(a?k.frontFace(k.CW):k.frontFace(k.CCW),
+R=a)},setPolygonOffset:function(a,b,c){X!==a&&(a?k.enable(k.POLYGON_OFFSET_FILL):k.disable(k.POLYGON_OFFSET_FILL),X=a);if(a&&(S!==b||Z!==c))k.polygonOffset(b,c),S=b,Z=c},setBlending:function(a,b,c,d){a!==H&&(a===THREE.NoBlending?k.disable(k.BLEND):a===THREE.AdditiveBlending?(k.enable(k.BLEND),k.blendEquation(k.FUNC_ADD),k.blendFunc(k.SRC_ALPHA,k.ONE)):a===THREE.SubtractiveBlending?(k.enable(k.BLEND),k.blendEquation(k.FUNC_ADD),k.blendFunc(k.ZERO,k.ONE_MINUS_SRC_COLOR)):a===THREE.MultiplyBlending?
+(k.enable(k.BLEND),k.blendEquation(k.FUNC_ADD),k.blendFunc(k.ZERO,k.SRC_COLOR)):a===THREE.CustomBlending?k.enable(k.BLEND):(k.enable(k.BLEND),k.blendEquationSeparate(k.FUNC_ADD,k.FUNC_ADD),k.blendFuncSeparate(k.SRC_ALPHA,k.ONE_MINUS_SRC_ALPHA,k.ONE,k.ONE_MINUS_SRC_ALPHA)),H=a);if(a===THREE.CustomBlending){if(b!==O&&(k.blendEquation(l(b)),O=b),c!==K||d!==x)k.blendFunc(l(c),l(d)),K=c,x=d}else x=K=O=null},setDepthTest:function(a){$!==a&&(a?k.enable(k.DEPTH_TEST):k.disable(k.DEPTH_TEST),$=a)},setDepthWrite:function(a){Y!==
+a&&(k.depthMask(a),Y=a)},setTexture:function(a,b){if(a.needsUpdate){a.__webglInit||(a.__webglInit=!0,a.__webglTexture=k.createTexture());k.activeTexture(k.TEXTURE0+b);k.bindTexture(k.TEXTURE_2D,a.__webglTexture);k.pixelStorei(k.UNPACK_FLIP_Y_WEBGL,a.flipY);k.pixelStorei(k.UNPACK_PREMULTIPLY_ALPHA_WEBGL,a.premultiplyAlpha);k.pixelStorei(k.UNPACK_ALIGNMENT,a.unpackAlignment);var c=a.image,d=0===(c.width&c.width-1)&&0===(c.height&c.height-1),e=l(a.format),f=l(a.type);h(k.TEXTURE_2D,a,d);var g=a.mipmaps;
+if(a instanceof THREE.DataTexture)if(0<g.length&&d){for(var i=0,j=g.length;i<j;i++)c=g[i],k.texImage2D(k.TEXTURE_2D,i,e,c.width,c.height,0,e,f,c.data);a.generateMipmaps=!1}else k.texImage2D(k.TEXTURE_2D,0,e,c.width,c.height,0,e,f,c.data);else if(a instanceof THREE.CompressedTexture){i=0;for(j=g.length;i<j;i++)c=g[i],k.compressedTexImage2D(k.TEXTURE_2D,i,e,c.width,c.height,0,c.data)}else if(0<g.length&&d){i=0;for(j=g.length;i<j;i++)c=g[i],k.texImage2D(k.TEXTURE_2D,i,e,e,f,c);a.generateMipmaps=!1}else k.texImage2D(k.TEXTURE_2D,
+0,e,e,f,a.image);a.generateMipmaps&&d&&k.generateMipmap(k.TEXTURE_2D);a.needsUpdate=!1;if(a.onUpdate)a.onUpdate()}else k.activeTexture(k.TEXTURE0+b),k.bindTexture(k.TEXTURE_2D,a.__webglTexture)},setCubeTexture:function(a,b){if(6===a.image.length)if(a.needsUpdate){a.image.__webglTextureCube||(a.image.__webglTextureCube=k.createTexture());k.activeTexture(k.TEXTURE0+b);k.bindTexture(k.TEXTURE_CUBE_MAP,a.image.__webglTextureCube);k.pixelStorei(k.UNPACK_FLIP_Y_WEBGL,a.flipY);for(var c=a instanceof THREE.CompressedTexture,
+d=[],e=0;6>e;e++)if(c)d[e]=a.image[e];else{var f=d,g=e,i;i=a.image[e];var j=G;if(!(i.width<=j&&i.height<=j)){var m=Math.max(i.width,i.height),n=Math.floor(i.width*j/m),j=Math.floor(i.height*j/m),m=document.createElement("canvas");m.width=n;m.height=j;m.getContext("2d").drawImage(i,0,0,i.width,i.height,0,0,n,j);i=m}f[g]=i}e=d[0];f=0===(e.width&e.width-1)&&0===(e.height&e.height-1);g=l(a.format);i=l(a.type);h(k.TEXTURE_CUBE_MAP,a,f);for(e=0;6>e;e++)if(c)for(var j=d[e].mipmaps,m=0,p=j.length;m<p;m++)n=
+j[m],k.compressedTexImage2D(k.TEXTURE_CUBE_MAP_POSITIVE_X+e,m,g,n.width,n.height,0,n.data);else k.texImage2D(k.TEXTURE_CUBE_MAP_POSITIVE_X+e,0,g,g,i,d[e]);a.generateMipmaps&&f&&k.generateMipmap(k.TEXTURE_CUBE_MAP);a.needsUpdate=!1;if(a.onUpdate)a.onUpdate()}else k.activeTexture(k.TEXTURE0+b),k.bindTexture(k.TEXTURE_CUBE_MAP,a.image.__webglTextureCube)},updateRenderTargetMipmap:function(a){a instanceof THREE.WebGLRenderTargetCube?(k.bindTexture(k.TEXTURE_CUBE_MAP,a.__webglTexture),k.generateMipmap(k.TEXTURE_CUBE_MAP),
+k.bindTexture(k.TEXTURE_CUBE_MAP,null)):(k.bindTexture(k.TEXTURE_2D,a.__webglTexture),k.generateMipmap(k.TEXTURE_2D),k.bindTexture(k.TEXTURE_2D,null))},setCubeTextureDynamic:function(a,b){k.activeTexture(k.TEXTURE0+b);k.bindTexture(k.TEXTURE_CUBE_MAP,a.__webglTexture)},paramThreeToGL:l,setLineWidth:function(a){a!==W&&(k.lineWidth(a),W=a)},resetState:function(){R=N=Y=$=H=-1}}};THREE.WebGLRenderer.ShaderBuilder=function(a,b){this.renderer=a;this.info=b;this.programs=[];this.programs_counter=0};
+THREE.extend(THREE.WebGLRenderer.ShaderBuilder.prototype,{buildProgram:function(a,b,c,d,e,f,g){var h=this.renderer,i,j,l=[];a?l.push(a):(l.push(b),l.push(c));for(j in f)l.push(j),l.push(f[j]);for(i in g)l.push(i),l.push(g[i]);a=l.join();i=0;for(j=this.programs.length;i<j;i++)if(l=this.programs[i],l.code===a)return l.usedTimes++,l.program;i="SHADOWMAP_TYPE_BASIC";g.shadowMapType===THREE.PCFShadowMap?i="SHADOWMAP_TYPE_PCF":g.shadowMapType===THREE.PCFSoftShadowMap&&(i="SHADOWMAP_TYPE_PCF_SOFT");j=this.generateDefines(f);
+f=["precision "+h.precision+" float;",j,h.supportsVertexTextures?"#define VERTEX_TEXTURES":"",g.gammaInput?"#define GAMMA_INPUT":"",g.gammaOutput?"#define GAMMA_OUTPUT":"",g.physicallyBasedShading?"#define PHYSICALLY_BASED_SHADING":"","#define MAX_DIR_LIGHTS "+g.maxDirLights,"#define MAX_POINT_LIGHTS "+g.maxPointLights,"#define MAX_SPOT_LIGHTS "+g.maxSpotLights,"#define MAX_HEMI_LIGHTS "+g.maxHemiLights,"#define MAX_SHADOWS "+g.maxShadows,"#define MAX_BONES "+g.maxBones,g.map?"#define USE_MAP":"",
+g.envMap?"#define USE_ENVMAP":"",g.lightMap?"#define USE_LIGHTMAP":"",g.bumpMap?"#define USE_BUMPMAP":"",g.normalMap?"#define USE_NORMALMAP":"",g.specularMap?"#define USE_SPECULARMAP":"",g.vertexColors?"#define USE_COLOR":"",g.skinning?"#define USE_SKINNING":"",g.useVertexTexture?"#define BONE_TEXTURE":"",g.boneTextureWidth?"#define N_BONE_PIXEL_X "+g.boneTextureWidth.toFixed(1):"",g.boneTextureHeight?"#define N_BONE_PIXEL_Y "+g.boneTextureHeight.toFixed(1):"",g.morphTargets?"#define USE_MORPHTARGETS":
+"",g.morphNormals?"#define USE_MORPHNORMALS":"",g.perPixel?"#define PHONG_PER_PIXEL":"",g.wrapAround?"#define WRAP_AROUND":"",g.doubleSided?"#define DOUBLE_SIDED":"",g.flipSided?"#define FLIP_SIDED":"",g.shadowMapEnabled?"#define USE_SHADOWMAP":"",g.shadowMapEnabled?"#define "+i:"",g.shadowMapDebug?"#define SHADOWMAP_DEBUG":"",g.shadowMapCascade?"#define SHADOWMAP_CASCADE":"",g.sizeAttenuation?"#define USE_SIZEATTENUATION":"","uniform mat4 modelMatrix;\nuniform mat4 modelViewMatrix;\nuniform mat4 projectionMatrix;\nuniform mat4 viewMatrix;\nuniform mat3 normalMatrix;\nuniform vec3 cameraPosition;\nattribute vec3 position;\nattribute vec3 normal;\nattribute vec2 uv;\nattribute vec2 uv2;\n#ifdef USE_COLOR\nattribute vec3 color;\n#endif\n#ifdef USE_MORPHTARGETS\nattribute vec3 morphTarget0;\nattribute vec3 morphTarget1;\nattribute vec3 morphTarget2;\nattribute vec3 morphTarget3;\n#ifdef USE_MORPHNORMALS\nattribute vec3 morphNormal0;\nattribute vec3 morphNormal1;\nattribute vec3 morphNormal2;\nattribute vec3 morphNormal3;\n#else\nattribute vec3 morphTarget4;\nattribute vec3 morphTarget5;\nattribute vec3 morphTarget6;\nattribute vec3 morphTarget7;\n#endif\n#endif\n#ifdef USE_SKINNING\nattribute vec4 skinIndex;\nattribute vec4 skinWeight;\n#endif\n"].join("\n");
+i=["precision "+h.precision+" float;",g.bumpMap||g.normalMap?"#extension GL_OES_standard_derivatives : enable":"",j,"#define MAX_DIR_LIGHTS "+g.maxDirLights,"#define MAX_POINT_LIGHTS "+g.maxPointLights,"#define MAX_SPOT_LIGHTS "+g.maxSpotLights,"#define MAX_HEMI_LIGHTS "+g.maxHemiLights,"#define MAX_SHADOWS "+g.maxShadows,g.alphaTest?"#define ALPHATEST "+g.alphaTest:"",g.gammaInput?"#define GAMMA_INPUT":"",g.gammaOutput?"#define GAMMA_OUTPUT":"",g.physicallyBasedShading?"#define PHYSICALLY_BASED_SHADING":
+"",g.useFog&&g.fog?"#define USE_FOG":"",g.useFog&&g.fogExp?"#define FOG_EXP2":"",g.map?"#define USE_MAP":"",g.envMap?"#define USE_ENVMAP":"",g.lightMap?"#define USE_LIGHTMAP":"",g.bumpMap?"#define USE_BUMPMAP":"",g.normalMap?"#define USE_NORMALMAP":"",g.specularMap?"#define USE_SPECULARMAP":"",g.vertexColors?"#define USE_COLOR":"",g.metal?"#define METAL":"",g.perPixel?"#define PHONG_PER_PIXEL":"",g.wrapAround?"#define WRAP_AROUND":"",g.doubleSided?"#define DOUBLE_SIDED":"",g.flipSided?"#define FLIP_SIDED":
+"",g.shadowMapEnabled?"#define USE_SHADOWMAP":"",g.shadowMapEnabled?"#define "+i:"",g.shadowMapDebug?"#define SHADOWMAP_DEBUG":"",g.shadowMapCascade?"#define SHADOWMAP_CASCADE":"","uniform mat4 viewMatrix;\nuniform vec3 cameraPosition;\n"].join("\n");b=h.compileShader(f+c,i+b);b.uniforms={};b.attributes={};var n,m,c="viewMatrix modelViewMatrix projectionMatrix normalMatrix modelMatrix cameraPosition morphTargetInfluences".split(" ");g.useVertexTexture?c.push("boneTexture"):c.push("boneGlobalMatrices");
+for(n in d)c.push(n);this.cacheUniformLocations(b,c);c="position normal uv uv2 tangent color skinIndex skinWeight lineDistance".split(" ");for(d=0;d<g.maxMorphTargets;d++)c.push("morphTarget"+d);for(d=0;d<g.maxMorphNormals;d++)c.push("morphNormal"+d);for(m in e)c.push(m);this.cacheAttributeLocations(b,c);b.id=this.programs_counter++;this.programs.push({program:b,code:a,usedTimes:1});this.info.memory.programs=this.programs.length;return b},generateDefines:function(a){var b,c=[],d;for(d in a)b=a[d],
+!1!==b&&(b="#define "+d+" "+b,c.push(b));return c.join("\n")},cacheUniformLocations:function(a,b){var c,d,e,f=this.renderer;c=0;for(d=b.length;c<d;c++)e=b[c],a.uniforms[e]=f.getUniformLocation(a,e)},cacheAttributeLocations:function(a,b){var c,d,e,f=this.renderer;c=0;for(d=b.length;c<d;c++)e=b[c],a.attributes[e]=f.getAttribLocation(a,e)},removeProgram:function(a){var b,c,d,e=!1,f=this.programs;b=0;for(c=f.length;b<c;b++)if(d=f[b],d.program===a){d.usedTimes--;0===d.usedTimes&&(e=!0);break}if(!0===e){e=
+[];b=0;for(c=f.length;b<c;b++)d=f[b],d.program!==a&&e.push(d);this.programs=e;this.renderer.deleteProgram(a);this.info.memory.programs--}}});THREE.WebGLRenderer.Object3DRenderer=function(a,b){this.renderer=a;this.info=b};
+THREE.extend(THREE.WebGLRenderer.Object3DRenderer.prototype,{getBufferMaterial:function(a,b){return a.material instanceof THREE.MeshFaceMaterial?a.material.materials[b.materialIndex]:a.material},bufferGuessUVType:function(a){return a.map||a.lightMap||a.bumpMap||a.normalMap||a.specularMap||a instanceof THREE.ShaderMaterial?!0:!1},bufferGuessNormalType:function(a){return a instanceof THREE.MeshBasicMaterial&&!a.envMap||a instanceof THREE.MeshDepthMaterial?!1:this.materialNeedsSmoothNormals(a)?THREE.SmoothShading:
+THREE.FlatShading},materialNeedsSmoothNormals:function(a){return a&&void 0!==a.shading&&a.shading===THREE.SmoothShading},bufferGuessVertexColorType:function(a){return a.vertexColors?a.vertexColors:!1},initCustomAttributes:function(a,b){var c=a.vertices.length,d=b.material;if(d.attributes){void 0===a.__webglCustomAttributesList&&(a.__webglCustomAttributesList=[]);for(var e in d.attributes){var f=d.attributes[e];if(!f.__webglInitialized||f.createUniqueBuffers){f.__webglInitialized=!0;var g=1;"v2"===
+f.type?g=2:"v3"===f.type?g=3:"v4"===f.type?g=4:"c"===f.type&&(g=3);f.size=g;f.array=new Float32Array(c*g);f.buffer=this.renderer.createBuffer();f.buffer.belongsToAttribute=e;f.needsUpdate=!0}a.__webglCustomAttributesList.push(f)}}},numericalSort:function(a,b){return b[0]-a[0]}});THREE.WebGLRenderer.MeshRenderer=function(a,b){THREE.WebGLRenderer.Object3DRenderer.call(this,a,b)};THREE.WebGLRenderer.MeshRenderer.prototype=Object.create(THREE.WebGLRenderer.Object3DRenderer.prototype);
+THREE.extend(THREE.WebGLRenderer.MeshRenderer.prototype,{createBuffers:function(a){var b=this.renderer;a.__webglVertexBuffer=b.createBuffer();a.__webglNormalBuffer=b.createBuffer();a.__webglTangentBuffer=b.createBuffer();a.__webglColorBuffer=b.createBuffer();a.__webglUVBuffer=b.createBuffer();a.__webglUV2Buffer=b.createBuffer();a.__webglSkinIndicesBuffer=b.createBuffer();a.__webglSkinWeightsBuffer=b.createBuffer();a.__webglFaceBuffer=b.createBuffer();a.__webglLineBuffer=b.createBuffer();var c,d;if(a.numMorphTargets){a.__webglMorphTargetsBuffers=
+[];c=0;for(d=a.numMorphTargets;c<d;c++)a.__webglMorphTargetsBuffers.push(b.createBuffer())}if(a.numMorphNormals){a.__webglMorphNormalsBuffers=[];c=0;for(d=a.numMorphNormals;c<d;c++)a.__webglMorphNormalsBuffers.push(b.createBuffer())}this.info.memory.geometries++},initBuffers:function(a,b){var c=b.geometry,d=a.faces3,e=a.faces4,f=3*d.length+4*e.length,g=1*d.length+2*e.length,e=3*d.length+4*e.length,d=this.getBufferMaterial(b,a),h=this.bufferGuessUVType(d),i=this.bufferGuessNormalType(d),j=this.bufferGuessVertexColorType(d);
+a.__vertexArray=new Float32Array(3*f);i&&(a.__normalArray=new Float32Array(3*f));c.hasTangents&&(a.__tangentArray=new Float32Array(4*f));j&&(a.__colorArray=new Float32Array(3*f));if(h){if(0<c.faceUvs.length||0<c.faceVertexUvs.length)a.__uvArray=new Float32Array(2*f);if(1<c.faceUvs.length||1<c.faceVertexUvs.length)a.__uv2Array=new Float32Array(2*f)}b.geometry.skinWeights.length&&b.geometry.skinIndices.length&&(a.__skinIndexArray=new Float32Array(4*f),a.__skinWeightArray=new Float32Array(4*f));a.__faceArray=
+new Uint16Array(3*g);a.__lineArray=new Uint16Array(2*e);if(a.numMorphTargets){a.__morphTargetsArrays=[];c=0;for(h=a.numMorphTargets;c<h;c++)a.__morphTargetsArrays.push(new Float32Array(3*f))}if(a.numMorphNormals){a.__morphNormalsArrays=[];c=0;for(h=a.numMorphNormals;c<h;c++)a.__morphNormalsArrays.push(new Float32Array(3*f))}a.__webglFaceCount=3*g;a.__webglLineCount=2*e;if(d.attributes){void 0===a.__webglCustomAttributesList&&(a.__webglCustomAttributesList=[]);for(var l in d.attributes){var g=d.attributes[l],
+c={},n;for(n in g)c[n]=g[n];if(!c.__webglInitialized||c.createUniqueBuffers)c.__webglInitialized=!0,e=1,"v2"===c.type?e=2:"v3"===c.type?e=3:"v4"===c.type?e=4:"c"===c.type&&(e=3),c.size=e,c.array=new Float32Array(f*e),c.buffer=this.renderer.createBuffer(),c.buffer.belongsToAttribute=l,g.needsUpdate=!0,c.__original=g;a.__webglCustomAttributesList.push(c)}}a.__inittedArrays=!0},setBuffers:function(a,b,c,d){if(a.__inittedArrays){var e=this.renderer,f=this.bufferGuessNormalType(d),g=this.bufferGuessVertexColorType(d),
+h=this.bufferGuessUVType(d),i=f===THREE.SmoothShading,j,l,n,m,r,u,p,q,w,v,z,y,t,D,C,k,I,J,B,P,A,G,E,F,s=P=A=J=0,H=0,O=n=B=0,K=r=z=0,x=0,K=a.__vertexArray,N=a.__uvArray,x=a.__uv2Array,R=a.__normalArray;m=a.__tangentArray;y=a.__colorArray;t=a.__skinIndexArray;D=a.__skinWeightArray;k=a.__morphTargetsArrays;I=a.__morphNormalsArrays;var $=a.__webglCustomAttributesList,Y=a.__faceArray,W=a.__lineArray;p=b.geometry;var M=p.elementsNeedUpdate,la=p.uvsNeedUpdate,na=p.normalsNeedUpdate,qa=p.tangentsNeedUpdate;
+C=p.colorsNeedUpdate;G=p.morphTargetsNeedUpdate;F=p.vertices;var X=a.faces3,S=a.faces4,Z=p.faces,T=p.faceVertexUvs[0],aa=p.faceVertexUvs[1];u=p.skinIndices;var L=p.skinWeights,U=p.morphTargets,ba=p.morphNormals;if(p.verticesNeedUpdate){b=0;for(j=X.length;b<j;b++)l=Z[X[b]],q=F[l.a],w=F[l.b],v=F[l.c],K[A]=q.x,K[A+1]=q.y,K[A+2]=q.z,K[A+3]=w.x,K[A+4]=w.y,K[A+5]=w.z,K[A+6]=v.x,K[A+7]=v.y,K[A+8]=v.z,A+=9;b=0;for(j=S.length;b<j;b++)l=Z[S[b]],q=F[l.a],w=F[l.b],v=F[l.c],l=F[l.d],K[A]=q.x,K[A+1]=q.y,K[A+2]=
+q.z,K[A+3]=w.x,K[A+4]=w.y,K[A+5]=w.z,K[A+6]=v.x,K[A+7]=v.y,K[A+8]=v.z,K[A+9]=l.x,K[A+10]=l.y,K[A+11]=l.z,A+=12;e.setDynamicArrayBuffer(a.__webglVertexBuffer,K)}if(G){A=0;for(G=U.length;A<G;A++){b=K=0;for(j=X.length;b<j;b++)F=X[b],l=Z[F],q=U[A].vertices[l.a],w=U[A].vertices[l.b],v=U[A].vertices[l.c],E=k[A],E[K]=q.x,E[K+1]=q.y,E[K+2]=q.z,E[K+3]=w.x,E[K+4]=w.y,E[K+5]=w.z,E[K+6]=v.x,E[K+7]=v.y,E[K+8]=v.z,d.morphNormals&&(i?(v=ba[A].vertexNormals[F],l=v.a,q=v.b,w=v.c):w=q=l=ba[A].faceNormals[F],F=I[A],
+F[K]=l.x,F[K+1]=l.y,F[K+2]=l.z,F[K+3]=q.x,F[K+4]=q.y,F[K+5]=q.z,F[K+6]=w.x,F[K+7]=w.y,F[K+8]=w.z),K+=9;b=0;for(j=S.length;b<j;b++)F=S[b],l=Z[F],q=U[A].vertices[l.a],w=U[A].vertices[l.b],v=U[A].vertices[l.c],l=U[A].vertices[l.d],E=k[A],E[K]=q.x,E[K+1]=q.y,E[K+2]=q.z,E[K+3]=w.x,E[K+4]=w.y,E[K+5]=w.z,E[K+6]=v.x,E[K+7]=v.y,E[K+8]=v.z,E[K+9]=l.x,E[K+10]=l.y,E[K+11]=l.z,d.morphNormals&&(i?(v=ba[A].vertexNormals[F],l=v.a,q=v.b,w=v.c,v=v.d):v=w=q=l=ba[A].faceNormals[F],F=I[A],F[K]=l.x,F[K+1]=l.y,F[K+2]=l.z,
+F[K+3]=q.x,F[K+4]=q.y,F[K+5]=q.z,F[K+6]=w.x,F[K+7]=w.y,F[K+8]=w.z,F[K+9]=v.x,F[K+10]=v.y,F[K+11]=v.z),K+=12;this.renderer.setDynamicArrayBuffer(a.__webglMorphTargetsBuffers[A],k[A]);d.morphNormals&&this.renderer.setDynamicArrayBuffer(a.__webglMorphNormalsBuffers[A],I[A])}}if(L.length){b=0;for(j=X.length;b<j;b++)l=Z[X[b]],d=L[l.a],k=L[l.b],I=L[l.c],D[r]=d.x,D[r+1]=d.y,D[r+2]=d.z,D[r+3]=d.w,D[r+4]=k.x,D[r+5]=k.y,D[r+6]=k.z,D[r+7]=k.w,D[r+8]=I.x,D[r+9]=I.y,D[r+10]=I.z,D[r+11]=I.w,d=u[l.a],k=u[l.b],I=
+u[l.c],t[r]=d.x,t[r+1]=d.y,t[r+2]=d.z,t[r+3]=d.w,t[r+4]=k.x,t[r+5]=k.y,t[r+6]=k.z,t[r+7]=k.w,t[r+8]=I.x,t[r+9]=I.y,t[r+10]=I.z,t[r+11]=I.w,r+=12;b=0;for(j=S.length;b<j;b++)l=Z[S[b]],d=L[l.a],k=L[l.b],I=L[l.c],q=L[l.d],D[r]=d.x,D[r+1]=d.y,D[r+2]=d.z,D[r+3]=d.w,D[r+4]=k.x,D[r+5]=k.y,D[r+6]=k.z,D[r+7]=k.w,D[r+8]=I.x,D[r+9]=I.y,D[r+10]=I.z,D[r+11]=I.w,D[r+12]=q.x,D[r+13]=q.y,D[r+14]=q.z,D[r+15]=q.w,d=u[l.a],k=u[l.b],I=u[l.c],l=u[l.d],t[r]=d.x,t[r+1]=d.y,t[r+2]=d.z,t[r+3]=d.w,t[r+4]=k.x,t[r+5]=k.y,t[r+
+6]=k.z,t[r+7]=k.w,t[r+8]=I.x,t[r+9]=I.y,t[r+10]=I.z,t[r+11]=I.w,t[r+12]=l.x,t[r+13]=l.y,t[r+14]=l.z,t[r+15]=l.w,r+=16;0<r&&(e.setDynamicArrayBuffer(a.__webglSkinIndicesBuffer,t),e.setDynamicArrayBuffer(a.__webglSkinWeightsBuffer,D))}if(C&&g){b=0;for(j=X.length;b<j;b++)l=Z[X[b]],r=l.vertexColors,u=l.color,3===r.length&&g===THREE.VertexColors?(t=r[0],D=r[1],C=r[2]):C=D=t=u,y[z]=t.r,y[z+1]=t.g,y[z+2]=t.b,y[z+3]=D.r,y[z+4]=D.g,y[z+5]=D.b,y[z+6]=C.r,y[z+7]=C.g,y[z+8]=C.b,z+=9;b=0;for(j=S.length;b<j;b++)l=
+Z[S[b]],r=l.vertexColors,u=l.color,4===r.length&&g===THREE.VertexColors?(t=r[0],D=r[1],C=r[2],r=r[3]):r=C=D=t=u,y[z]=t.r,y[z+1]=t.g,y[z+2]=t.b,y[z+3]=D.r,y[z+4]=D.g,y[z+5]=D.b,y[z+6]=C.r,y[z+7]=C.g,y[z+8]=C.b,y[z+9]=r.r,y[z+10]=r.g,y[z+11]=r.b,z+=12;0<z&&e.setDynamicArrayBuffer(a.__webglColorBuffer,y)}if(qa&&p.hasTangents){b=0;for(j=X.length;b<j;b++)l=Z[X[b]],p=l.vertexTangents,g=p[0],z=p[1],y=p[2],m[n]=g.x,m[n+1]=g.y,m[n+2]=g.z,m[n+3]=g.w,m[n+4]=z.x,m[n+5]=z.y,m[n+6]=z.z,m[n+7]=z.w,m[n+8]=y.x,m[n+
+9]=y.y,m[n+10]=y.z,m[n+11]=y.w,n+=12;b=0;for(j=S.length;b<j;b++)l=Z[S[b]],p=l.vertexTangents,g=p[0],z=p[1],y=p[2],p=p[3],m[n]=g.x,m[n+1]=g.y,m[n+2]=g.z,m[n+3]=g.w,m[n+4]=z.x,m[n+5]=z.y,m[n+6]=z.z,m[n+7]=z.w,m[n+8]=y.x,m[n+9]=y.y,m[n+10]=y.z,m[n+11]=y.w,m[n+12]=p.x,m[n+13]=p.y,m[n+14]=p.z,m[n+15]=p.w,n+=16;e.setDynamicArrayBuffer(a.__webglTangentBuffer,m)}if(na&&f){b=0;for(j=X.length;b<j;b++)if(l=Z[X[b]],n=l.vertexNormals,m=l.normal,3===n.length&&i)for(f=0;3>f;f++)m=n[f],R[B]=m.x,R[B+1]=m.y,R[B+2]=
+m.z,B+=3;else for(f=0;3>f;f++)R[B]=m.x,R[B+1]=m.y,R[B+2]=m.z,B+=3;b=0;for(j=S.length;b<j;b++)if(l=Z[S[b]],n=l.vertexNormals,m=l.normal,4===n.length&&i)for(f=0;4>f;f++)m=n[f],R[B]=m.x,R[B+1]=m.y,R[B+2]=m.z,B+=3;else for(f=0;4>f;f++)R[B]=m.x,R[B+1]=m.y,R[B+2]=m.z,B+=3;e.setDynamicArrayBuffer(a.__webglNormalBuffer,R)}if(la&&T&&h){b=0;for(j=X.length;b<j;b++)if(i=X[b],i=T[i],void 0!==i)for(f=0;3>f;f++)B=i[f],N[P]=B.x,N[P+1]=B.y,P+=2;b=0;for(j=S.length;b<j;b++)if(i=S[b],i=T[i],void 0!==i)for(f=0;4>f;f++)B=
+i[f],N[P]=B.x,N[P+1]=B.y,P+=2;0<P&&e.setDynamicArrayBuffer(a.__webglUVBuffer,N)}if(la&&aa&&h){b=0;for(j=X.length;b<j;b++)if(i=X[b],h=aa[i],void 0!==h)for(f=0;3>f;f++)P=h[f],x[s]=P.x,x[s+1]=P.y,s+=2;b=0;for(j=S.length;b<j;b++)if(i=S[b],h=aa[i],void 0!==h)for(f=0;4>f;f++)P=h[f],x[s]=P.x,x[s+1]=P.y,s+=2;0<s&&e.setDynamicArrayBuffer(a.__webglUV2Buffer,x)}if(M){b=0;for(j=X.length;b<j;b++)Y[H]=J,Y[H+1]=J+1,Y[H+2]=J+2,H+=3,W[O]=J,W[O+1]=J+1,W[O+2]=J,W[O+3]=J+2,W[O+4]=J+1,W[O+5]=J+2,O+=6,J+=3;b=0;for(j=S.length;b<
+j;b++)Y[H]=J,Y[H+1]=J+1,Y[H+2]=J+3,Y[H+3]=J+1,Y[H+4]=J+2,Y[H+5]=J+3,H+=6,W[O]=J,W[O+1]=J+1,W[O+2]=J,W[O+3]=J+3,W[O+4]=J+1,W[O+5]=J+2,W[O+6]=J+2,W[O+7]=J+3,O+=8,J+=4;e.setDynamicIndexBuffer(a.__webglFaceBuffer,Y);e.setDynamicIndexBuffer(a.__webglLineBuffer,W)}if($){f=0;for(J=$.length;f<J;f++)if(s=$[f],s.__original.needsUpdate){x=0;if(1===s.size)if(void 0===s.boundTo||"vertices"===s.boundTo){b=0;for(j=X.length;b<j;b++)l=Z[X[b]],s.array[x]=s.value[l.a],s.array[x+1]=s.value[l.b],s.array[x+2]=s.value[l.c],
+x+=3;b=0;for(j=S.length;b<j;b++)l=Z[S[b]],s.array[x]=s.value[l.a],s.array[x+1]=s.value[l.b],s.array[x+2]=s.value[l.c],s.array[x+3]=s.value[l.d],x+=4}else{if("faces"===s.boundTo){b=0;for(j=X.length;b<j;b++)O=s.value[X[b]],s.array[x]=O,s.array[x+1]=O,s.array[x+2]=O,x+=3;b=0;for(j=S.length;b<j;b++)O=s.value[S[b]],s.array[x]=O,s.array[x+1]=O,s.array[x+2]=O,s.array[x+3]=O,x+=4}}else if(2===s.size)if(void 0===s.boundTo||"vertices"===s.boundTo){b=0;for(j=X.length;b<j;b++)l=Z[X[b]],q=s.value[l.a],w=s.value[l.b],
+v=s.value[l.c],s.array[x]=q.x,s.array[x+1]=q.y,s.array[x+2]=w.x,s.array[x+3]=w.y,s.array[x+4]=v.x,s.array[x+5]=v.y,x+=6;b=0;for(j=S.length;b<j;b++)l=Z[S[b]],q=s.value[l.a],w=s.value[l.b],v=s.value[l.c],l=s.value[l.d],s.array[x]=q.x,s.array[x+1]=q.y,s.array[x+2]=w.x,s.array[x+3]=w.y,s.array[x+4]=v.x,s.array[x+5]=v.y,s.array[x+6]=l.x,s.array[x+7]=l.y,x+=8}else{if("faces"===s.boundTo){b=0;for(j=X.length;b<j;b++)v=w=q=O=s.value[X[b]],s.array[x]=q.x,s.array[x+1]=q.y,s.array[x+2]=w.x,s.array[x+3]=w.y,s.array[x+
+4]=v.x,s.array[x+5]=v.y,x+=6;b=0;for(j=S.length;b<j;b++)l=v=w=q=O=s.value[S[b]],s.array[x]=q.x,s.array[x+1]=q.y,s.array[x+2]=w.x,s.array[x+3]=w.y,s.array[x+4]=v.x,s.array[x+5]=v.y,s.array[x+6]=l.x,s.array[x+7]=l.y,x+=8}}else if(3===s.size)if(H="c"===s.type?["r","g","b"]:["x","y","z"],void 0===s.boundTo||"vertices"===s.boundTo){b=0;for(j=X.length;b<j;b++)l=Z[X[b]],q=s.value[l.a],w=s.value[l.b],v=s.value[l.c],s.array[x]=q[H[0]],s.array[x+1]=q[H[1]],s.array[x+2]=q[H[2]],s.array[x+3]=w[H[0]],s.array[x+
+4]=w[H[1]],s.array[x+5]=w[H[2]],s.array[x+6]=v[H[0]],s.array[x+7]=v[H[1]],s.array[x+8]=v[H[2]],x+=9;b=0;for(j=S.length;b<j;b++)l=Z[S[b]],q=s.value[l.a],w=s.value[l.b],v=s.value[l.c],l=s.value[l.d],s.array[x]=q[H[0]],s.array[x+1]=q[H[1]],s.array[x+2]=q[H[2]],s.array[x+3]=w[H[0]],s.array[x+4]=w[H[1]],s.array[x+5]=w[H[2]],s.array[x+6]=v[H[0]],s.array[x+7]=v[H[1]],s.array[x+8]=v[H[2]],s.array[x+9]=l[H[0]],s.array[x+10]=l[H[1]],s.array[x+11]=l[H[2]],x+=12}else if("faces"===s.boundTo){b=0;for(j=X.length;b<
+j;b++)v=w=q=O=s.value[X[b]],s.array[x]=q[H[0]],s.array[x+1]=q[H[1]],s.array[x+2]=q[H[2]],s.array[x+3]=w[H[0]],s.array[x+4]=w[H[1]],s.array[x+5]=w[H[2]],s.array[x+6]=v[H[0]],s.array[x+7]=v[H[1]],s.array[x+8]=v[H[2]],x+=9;b=0;for(j=S.length;b<j;b++)l=v=w=q=O=s.value[S[b]],s.array[x]=q[H[0]],s.array[x+1]=q[H[1]],s.array[x+2]=q[H[2]],s.array[x+3]=w[H[0]],s.array[x+4]=w[H[1]],s.array[x+5]=w[H[2]],s.array[x+6]=v[H[0]],s.array[x+7]=v[H[1]],s.array[x+8]=v[H[2]],s.array[x+9]=l[H[0]],s.array[x+10]=l[H[1]],
+s.array[x+11]=l[H[2]],x+=12}else{if("faceVertices"===s.boundTo){b=0;for(j=X.length;b<j;b++)O=s.value[X[b]],q=O[0],w=O[1],v=O[2],s.array[x]=q[H[0]],s.array[x+1]=q[H[1]],s.array[x+2]=q[H[2]],s.array[x+3]=w[H[0]],s.array[x+4]=w[H[1]],s.array[x+5]=w[H[2]],s.array[x+6]=v[H[0]],s.array[x+7]=v[H[1]],s.array[x+8]=v[H[2]],x+=9;b=0;for(j=S.length;b<j;b++)O=s.value[S[b]],q=O[0],w=O[1],v=O[2],l=O[3],s.array[x]=q[H[0]],s.array[x+1]=q[H[1]],s.array[x+2]=q[H[2]],s.array[x+3]=w[H[0]],s.array[x+4]=w[H[1]],s.array[x+
+5]=w[H[2]],s.array[x+6]=v[H[0]],s.array[x+7]=v[H[1]],s.array[x+8]=v[H[2]],s.array[x+9]=l[H[0]],s.array[x+10]=l[H[1]],s.array[x+11]=l[H[2]],x+=12}}else if(4===s.size)if(void 0===s.boundTo||"vertices"===s.boundTo){b=0;for(j=X.length;b<j;b++)l=Z[X[b]],q=s.value[l.a],w=s.value[l.b],v=s.value[l.c],s.array[x]=q.x,s.array[x+1]=q.y,s.array[x+2]=q.z,s.array[x+3]=q.w,s.array[x+4]=w.x,s.array[x+5]=w.y,s.array[x+6]=w.z,s.array[x+7]=w.w,s.array[x+8]=v.x,s.array[x+9]=v.y,s.array[x+10]=v.z,s.array[x+11]=v.w,x+=
+12;b=0;for(j=S.length;b<j;b++)l=Z[S[b]],q=s.value[l.a],w=s.value[l.b],v=s.value[l.c],l=s.value[l.d],s.array[x]=q.x,s.array[x+1]=q.y,s.array[x+2]=q.z,s.array[x+3]=q.w,s.array[x+4]=w.x,s.array[x+5]=w.y,s.array[x+6]=w.z,s.array[x+7]=w.w,s.array[x+8]=v.x,s.array[x+9]=v.y,s.array[x+10]=v.z,s.array[x+11]=v.w,s.array[x+12]=l.x,s.array[x+13]=l.y,s.array[x+14]=l.z,s.array[x+15]=l.w,x+=16}else if("faces"===s.boundTo){b=0;for(j=X.length;b<j;b++)v=w=q=O=s.value[X[b]],s.array[x]=q.x,s.array[x+1]=q.y,s.array[x+
+2]=q.z,s.array[x+3]=q.w,s.array[x+4]=w.x,s.array[x+5]=w.y,s.array[x+6]=w.z,s.array[x+7]=w.w,s.array[x+8]=v.x,s.array[x+9]=v.y,s.array[x+10]=v.z,s.array[x+11]=v.w,x+=12;b=0;for(j=S.length;b<j;b++)l=v=w=q=O=s.value[S[b]],s.array[x]=q.x,s.array[x+1]=q.y,s.array[x+2]=q.z,s.array[x+3]=q.w,s.array[x+4]=w.x,s.array[x+5]=w.y,s.array[x+6]=w.z,s.array[x+7]=w.w,s.array[x+8]=v.x,s.array[x+9]=v.y,s.array[x+10]=v.z,s.array[x+11]=v.w,s.array[x+12]=l.x,s.array[x+13]=l.y,s.array[x+14]=l.z,s.array[x+15]=l.w,x+=16}else if("faceVertices"===
+s.boundTo){b=0;for(j=X.length;b<j;b++)O=s.value[X[b]],q=O[0],w=O[1],v=O[2],s.array[x]=q.x,s.array[x+1]=q.y,s.array[x+2]=q.z,s.array[x+3]=q.w,s.array[x+4]=w.x,s.array[x+5]=w.y,s.array[x+6]=w.z,s.array[x+7]=w.w,s.array[x+8]=v.x,s.array[x+9]=v.y,s.array[x+10]=v.z,s.array[x+11]=v.w,x+=12;b=0;for(j=S.length;b<j;b++)O=s.value[S[b]],q=O[0],w=O[1],v=O[2],l=O[3],s.array[x]=q.x,s.array[x+1]=q.y,s.array[x+2]=q.z,s.array[x+3]=q.w,s.array[x+4]=w.x,s.array[x+5]=w.y,s.array[x+6]=w.z,s.array[x+7]=w.w,s.array[x+8]=
+v.x,s.array[x+9]=v.y,s.array[x+10]=v.z,s.array[x+11]=v.w,s.array[x+12]=l.x,s.array[x+13]=l.y,s.array[x+14]=l.z,s.array[x+15]=l.w,x+=16}e.setDynamicArrayBuffer(s.buffer,s.array)}}c&&(delete a.__inittedArrays,delete a.__colorArray,delete a.__normalArray,delete a.__tangentArray,delete a.__uvArray,delete a.__uv2Array,delete a.__faceArray,delete a.__vertexArray,delete a.__lineArray,delete a.__skinIndexArray,delete a.__skinWeightArray)}}});THREE.WebGLRenderer.ParticleRenderer=function(a,b){THREE.WebGLRenderer.Object3DRenderer.call(this,a,b)};THREE.WebGLRenderer.ParticleRenderer.prototype=Object.create(THREE.WebGLRenderer.Object3DRenderer.prototype);
+THREE.extend(THREE.WebGLRenderer.ParticleRenderer.prototype,{createBuffers:function(a){var b=this.renderer;a.__webglVertexBuffer=b.createBuffer();a.__webglColorBuffer=b.createBuffer();this.info.memory.geometries++},initBuffers:function(a,b){var c=a.vertices.length;a.__vertexArray=new Float32Array(3*c);a.__colorArray=new Float32Array(3*c);a.__sortArray=[];a.__webglParticleCount=c;this.initCustomAttributes(a,b)},setBuffers:function(a,b,c){var d=this.renderer,e,f,g,h;e=a.vertices;h=e.length;var i=a.colors,
+j=i.length,l=a.__vertexArray,n=a.__colorArray,m=a.__sortArray,r=a.verticesNeedUpdate,u=a.colorsNeedUpdate,p=a.__webglCustomAttributesList;g=THREE.WebGLRenderer.ParticleRenderer._m1;var q=THREE.WebGLRenderer.ParticleRenderer._v1;if(b.sortParticles){g.multiplyMatrices(c,b.matrixWorld);for(c=0;c<h;c++)f=e[c],q.copy(f),q.applyProjection(g),m[c]=[q.z,c];m.sort(this.numericalSort);for(c=0;c<h;c++)f=e[m[c][1]],g=3*c,l[g]=f.x,l[g+1]=f.y,l[g+2]=f.z;for(e=0;e<j;e++)g=3*e,h=i[m[e][1]],n[g]=h.r,n[g+1]=h.g,n[g+
+2]=h.b;if(p){i=0;for(j=p.length;i<j;i++)if(c=p[i],void 0===c.boundTo||"vertices"===c.boundTo)if(g=0,h=c.value.length,1===c.size)for(e=0;e<h;e++)f=m[e][1],c.array[e]=c.value[f];else if(2===c.size)for(e=0;e<h;e++)f=m[e][1],f=c.value[f],c.array[g]=f.x,c.array[g+1]=f.y,g+=2;else if(3===c.size)if("c"===c.type)for(e=0;e<h;e++)f=m[e][1],f=c.value[f],c.array[g]=f.r,c.array[g+1]=f.g,c.array[g+2]=f.b,g+=3;else for(e=0;e<h;e++)f=m[e][1],f=c.value[f],c.array[g]=f.x,c.array[g+1]=f.y,c.array[g+2]=f.z,g+=3;else if(4===
+c.size)for(e=0;e<h;e++)f=m[e][1],f=c.value[f],c.array[g]=f.x,c.array[g+1]=f.y,c.array[g+2]=f.z,c.array[g+3]=f.w,g+=4}}else{if(r)for(c=0;c<h;c++)f=e[c],g=3*c,l[g]=f.x,l[g+1]=f.y,l[g+2]=f.z;if(u)for(e=0;e<j;e++)h=i[e],g=3*e,n[g]=h.r,n[g+1]=h.g,n[g+2]=h.b;if(p){i=0;for(j=p.length;i<j;i++)if(c=p[i],c.needsUpdate&&(void 0===c.boundTo||"vertices"===c.boundTo))if(h=c.value.length,g=0,1===c.size)for(e=0;e<h;e++)c.array[e]=c.value[e];else if(2===c.size)for(e=0;e<h;e++)f=c.value[e],c.array[g]=f.x,c.array[g+
+1]=f.y,g+=2;else if(3===c.size)if("c"===c.type)for(e=0;e<h;e++)f=c.value[e],c.array[g]=f.r,c.array[g+1]=f.g,c.array[g+2]=f.b,g+=3;else for(e=0;e<h;e++)f=c.value[e],c.array[g]=f.x,c.array[g+1]=f.y,c.array[g+2]=f.z,g+=3;else if(4===c.size)for(e=0;e<h;e++)f=c.value[e],c.array[g]=f.x,c.array[g+1]=f.y,c.array[g+2]=f.z,c.array[g+3]=f.w,g+=4}}(r||b.sortParticles)&&d.setDynamicArrayBuffer(a.__webglVertexBuffer,l);(u||b.sortParticles)&&d.setDynamicArrayBuffer(a.__webglColorBuffer,n);if(p){i=0;for(j=p.length;i<
+j;i++)c=p[i],(c.needsUpdate||b.sortParticles)&&d.setDynamicArrayBuffer(c.buffer,c.array)}}});THREE.WebGLRenderer.ParticleRenderer._m1=new THREE.Matrix4;THREE.WebGLRenderer.ParticleRenderer._v1=new THREE.Vector3;THREE.WebGLRenderer.LineRenderer=function(a,b){THREE.WebGLRenderer.Object3DRenderer.call(this,a,b)};THREE.WebGLRenderer.LineRenderer.prototype=Object.create(THREE.WebGLRenderer.Object3DRenderer.prototype);
+THREE.extend(THREE.WebGLRenderer.LineRenderer.prototype,{createBuffers:function(a){var b=this.renderer;a.__webglVertexBuffer=b.createBuffer();a.__webglColorBuffer=b.createBuffer();a.__webglLineDistanceBuffer=b.createBuffer();this.info.memory.geometries++},initBuffers:function(a,b){var c=a.vertices.length;a.__vertexArray=new Float32Array(3*c);a.__colorArray=new Float32Array(3*c);a.__lineDistanceArray=new Float32Array(1*c);a.__webglLineCount=c;this.initCustomAttributes(a,b)},setBuffers:function(a){var b=
+this.renderer,c,d,e,f=a.vertices,g=a.colors,h=a.lineDistances,i=f.length,j=g.length,l=h.length,n=a.__vertexArray,m=a.__colorArray,r=a.__lineDistanceArray,u=a.colorsNeedUpdate,p=a.lineDistancesNeedUpdate,q=a.__webglCustomAttributesList;if(a.verticesNeedUpdate){for(c=0;c<i;c++)e=f[c],d=3*c,n[d]=e.x,n[d+1]=e.y,n[d+2]=e.z;b.setDynamicArrayBuffer(a.__webglVertexBuffer,n)}if(u){for(c=0;c<j;c++)e=g[c],d=3*c,m[d]=e.r,m[d+1]=e.g,m[d+2]=e.b;b.setDynamicArrayBuffer(a.__webglColorBuffer,m)}if(p){for(d=0;d<l;d++)r[d]=
+h[d];b.setDynamicArrayBuffer(a.__webglLineDistanceBuffer,r)}if(q){a=0;for(h=q.length;a<h;a++)if(j=q[a],j.needsUpdate&&(void 0===j.boundTo||"vertices"===j.boundTo)){d=0;r=j.value.length;if(1===j.size)for(l=0;l<r;l++)j.array[l]=j.value[l];else if(2===j.size)for(l=0;l<r;l++)g=j.value[l],j.array[d]=g.x,j.array[d+1]=g.y,d+=2;else if(3===j.size)if("c"===j.type)for(l=0;l<r;l++)g=j.value[l],j.array[d]=g.r,j.array[d+1]=g.g,j.array[d+2]=g.b,d+=3;else for(l=0;l<r;l++)g=j.value[l],j.array[d]=g.x,j.array[d+1]=
+g.y,j.array[d+2]=g.z,d+=3;else if(4===j.size)for(l=0;l<r;l++)g=j.value[l],j.array[d]=g.x,j.array[d+1]=g.y,j.array[d+2]=g.z,j.array[d+3]=g.w,d+=4;b.setDynamicArrayBuffer(j.buffer,j.array)}}}});THREE.WebGLRenderer.RibbonRenderer=function(a,b){THREE.WebGLRenderer.Object3DRenderer.call(this,a,b)};THREE.WebGLRenderer.RibbonRenderer.prototype=Object.create(THREE.WebGLRenderer.Object3DRenderer.prototype);
+THREE.extend(THREE.WebGLRenderer.RibbonRenderer.prototype,{createBuffers:function(a){var b=this.renderer;a.__webglVertexBuffer=b.createBuffer();a.__webglColorBuffer=b.createBuffer();a.__webglNormalBuffer=b.createBuffer();this.info.memory.geometries++},initBuffers:function(a,b){var c=a.vertices.length;a.__vertexArray=new Float32Array(3*c);a.__colorArray=new Float32Array(3*c);a.__normalArray=new Float32Array(3*c);a.__webglVertexCount=c;this.initCustomAttributes(a,b)},setBuffers:function(a){var b=this.renderer,
+c,d,e,f,g,h,i,j,l=a.vertices;d=a.colors;h=a.normals;var n=l.length;g=d.length;i=h.length;var m=a.__vertexArray,r=a.__colorArray;j=a.__normalArray;var u=a.colorsNeedUpdate,p=a.normalsNeedUpdate,q=a.__webglCustomAttributesList;if(a.verticesNeedUpdate){for(c=0;c<n;c++)e=l[c],f=3*c,m[f]=e.x,m[f+1]=e.y,m[f+2]=e.z;b.setDynamicArrayBuffer(a.__webglVertexBuffer,m)}if(u){for(c=0;c<g;c++)e=d[c],f=3*c,r[f]=e.r,r[f+1]=e.g,r[f+2]=e.b;b.setDynamicArrayBuffer(a.__webglColorBuffer,r)}if(p){for(d=0;d<i;d++)g=h[d],
+f=3*d,j[f]=g.x,j[f+1]=g.y,j[f+2]=g.z;b.setDynamicArrayBuffer(a.__webglNormalBuffer,j)}if(q){a=0;for(h=q.length;a<h;a++)if(d=q[a],d.needsUpdate&&(void 0===d.boundTo||"vertices"===d.boundTo)){f=0;j=d.value.length;if(1===d.size)for(i=0;i<j;i++)d.array[i]=d.value[i];else if(2===d.size)for(i=0;i<j;i++)g=d.value[i],d.array[f]=g.x,d.array[f+1]=g.y,f+=2;else if(3===d.size)if("c"===d.type)for(i=0;i<j;i++)g=d.value[i],d.array[f]=g.r,d.array[f+1]=g.g,d.array[f+2]=g.b,f+=3;else for(i=0;i<j;i++)g=d.value[i],d.array[f]=
+g.x,d.array[f+1]=g.y,d.array[f+2]=g.z,f+=3;else if(4===d.size)for(i=0;i<j;i++)g=d.value[i],d.array[f]=g.x,d.array[f+1]=g.y,d.array[f+2]=g.z,d.array[f+3]=g.w,f+=4;b.setDynamicArrayBuffer(d.buffer,d.array)}}}});THREE.WebGLRenderTarget=function(a,b,c){THREE.EventDispatcher.call(this);this.width=a;this.height=b;c=c||{};this.wrapS=void 0!==c.wrapS?c.wrapS:THREE.ClampToEdgeWrapping;this.wrapT=void 0!==c.wrapT?c.wrapT:THREE.ClampToEdgeWrapping;this.magFilter=void 0!==c.magFilter?c.magFilter:THREE.LinearFilter;this.minFilter=void 0!==c.minFilter?c.minFilter:THREE.LinearMipMapLinearFilter;this.anisotropy=void 0!==c.anisotropy?c.anisotropy:1;this.offset=new THREE.Vector2(0,0);this.repeat=new THREE.Vector2(1,1);
 this.format=void 0!==c.format?c.format:THREE.RGBAFormat;this.type=void 0!==c.type?c.type:THREE.UnsignedByteType;this.depthBuffer=void 0!==c.depthBuffer?c.depthBuffer:!0;this.stencilBuffer=void 0!==c.stencilBuffer?c.stencilBuffer:!0;this.generateMipmaps=!0;this.shareDepthFrom=null};
 this.format=void 0!==c.format?c.format:THREE.RGBAFormat;this.type=void 0!==c.type?c.type:THREE.UnsignedByteType;this.depthBuffer=void 0!==c.depthBuffer?c.depthBuffer:!0;this.stencilBuffer=void 0!==c.stencilBuffer?c.stencilBuffer:!0;this.generateMipmaps=!0;this.shareDepthFrom=null};
 THREE.WebGLRenderTarget.prototype.clone=function(){var a=new THREE.WebGLRenderTarget(this.width,this.height);a.wrapS=this.wrapS;a.wrapT=this.wrapT;a.magFilter=this.magFilter;a.minFilter=this.minFilter;a.anisotropy=this.anisotropy;a.offset.copy(this.offset);a.repeat.copy(this.repeat);a.format=this.format;a.type=this.type;a.depthBuffer=this.depthBuffer;a.stencilBuffer=this.stencilBuffer;a.generateMipmaps=this.generateMipmaps;a.shareDepthFrom=this.shareDepthFrom;return a};
 THREE.WebGLRenderTarget.prototype.clone=function(){var a=new THREE.WebGLRenderTarget(this.width,this.height);a.wrapS=this.wrapS;a.wrapT=this.wrapT;a.magFilter=this.magFilter;a.minFilter=this.minFilter;a.anisotropy=this.anisotropy;a.offset.copy(this.offset);a.repeat.copy(this.repeat);a.format=this.format;a.type=this.type;a.depthBuffer=this.depthBuffer;a.stencilBuffer=this.stencilBuffer;a.generateMipmaps=this.generateMipmaps;a.shareDepthFrom=this.shareDepthFrom;return a};
 THREE.WebGLRenderTarget.prototype.dispose=function(){this.dispatchEvent({type:"dispose"})};THREE.WebGLRenderTargetCube=function(a,b,c){THREE.WebGLRenderTarget.call(this,a,b,c);this.activeCubeFace=0};THREE.WebGLRenderTargetCube.prototype=Object.create(THREE.WebGLRenderTarget.prototype);THREE.RenderableVertex=function(){this.positionWorld=new THREE.Vector3;this.positionScreen=new THREE.Vector4;this.visible=!0};THREE.RenderableVertex.prototype.copy=function(a){this.positionWorld.copy(a.positionWorld);this.positionScreen.copy(a.positionScreen)};THREE.RenderableFace3=function(){this.v1=new THREE.RenderableVertex;this.v2=new THREE.RenderableVertex;this.v3=new THREE.RenderableVertex;this.centroidModel=new THREE.Vector3;this.normalModel=new THREE.Vector3;this.normalModelView=new THREE.Vector3;this.vertexNormalsLength=0;this.vertexNormalsModel=[new THREE.Vector3,new THREE.Vector3,new THREE.Vector3];this.vertexNormalsModelView=[new THREE.Vector3,new THREE.Vector3,new THREE.Vector3];this.material=this.color=null;this.uvs=[[]];this.z=null};THREE.RenderableFace4=function(){this.v1=new THREE.RenderableVertex;this.v2=new THREE.RenderableVertex;this.v3=new THREE.RenderableVertex;this.v4=new THREE.RenderableVertex;this.centroidModel=new THREE.Vector3;this.normalModel=new THREE.Vector3;this.normalModelView=new THREE.Vector3;this.vertexNormalsLength=0;this.vertexNormalsModel=[new THREE.Vector3,new THREE.Vector3,new THREE.Vector3,new THREE.Vector3];this.vertexNormalsModelView=[new THREE.Vector3,new THREE.Vector3,new THREE.Vector3,new THREE.Vector3];
 THREE.WebGLRenderTarget.prototype.dispose=function(){this.dispatchEvent({type:"dispose"})};THREE.WebGLRenderTargetCube=function(a,b,c){THREE.WebGLRenderTarget.call(this,a,b,c);this.activeCubeFace=0};THREE.WebGLRenderTargetCube.prototype=Object.create(THREE.WebGLRenderTarget.prototype);THREE.RenderableVertex=function(){this.positionWorld=new THREE.Vector3;this.positionScreen=new THREE.Vector4;this.visible=!0};THREE.RenderableVertex.prototype.copy=function(a){this.positionWorld.copy(a.positionWorld);this.positionScreen.copy(a.positionScreen)};THREE.RenderableFace3=function(){this.v1=new THREE.RenderableVertex;this.v2=new THREE.RenderableVertex;this.v3=new THREE.RenderableVertex;this.centroidModel=new THREE.Vector3;this.normalModel=new THREE.Vector3;this.normalModelView=new THREE.Vector3;this.vertexNormalsLength=0;this.vertexNormalsModel=[new THREE.Vector3,new THREE.Vector3,new THREE.Vector3];this.vertexNormalsModelView=[new THREE.Vector3,new THREE.Vector3,new THREE.Vector3];this.material=this.color=null;this.uvs=[[]];this.z=null};THREE.RenderableFace4=function(){this.v1=new THREE.RenderableVertex;this.v2=new THREE.RenderableVertex;this.v3=new THREE.RenderableVertex;this.v4=new THREE.RenderableVertex;this.centroidModel=new THREE.Vector3;this.normalModel=new THREE.Vector3;this.normalModelView=new THREE.Vector3;this.vertexNormalsLength=0;this.vertexNormalsModel=[new THREE.Vector3,new THREE.Vector3,new THREE.Vector3,new THREE.Vector3];this.vertexNormalsModelView=[new THREE.Vector3,new THREE.Vector3,new THREE.Vector3,new THREE.Vector3];
-this.material=this.color=null;this.uvs=[[]];this.z=null};THREE.RenderableObject=function(){this.z=this.object=null};THREE.RenderableParticle=function(){this.rotation=this.z=this.y=this.x=this.object=null;this.scale=new THREE.Vector2;this.material=null};THREE.RenderableLine=function(){this.z=null;this.v1=new THREE.RenderableVertex;this.v2=new THREE.RenderableVertex;this.material=null};THREE.GeometryUtils={merge:function(a,b){var c,d,e=a.vertices.length,f=b instanceof THREE.Mesh?b.geometry:b,g=a.vertices,h=f.vertices,i=a.faces,k=f.faces,l=a.faceVertexUvs[0],f=f.faceVertexUvs[0];b instanceof THREE.Mesh&&(b.matrixAutoUpdate&&b.updateMatrix(),c=b.matrix,d=new THREE.Matrix3,d.getInverse(c),d.transpose());for(var n=0,m=h.length;n<m;n++){var t=h[n].clone();c&&t.applyMatrix4(c);g.push(t)}n=0;for(m=k.length;n<m;n++){var t=k[n],r,p,q=t.vertexNormals,y=t.vertexColors;t instanceof THREE.Face3?
-r=new THREE.Face3(t.a+e,t.b+e,t.c+e):t instanceof THREE.Face4&&(r=new THREE.Face4(t.a+e,t.b+e,t.c+e,t.d+e));r.normal.copy(t.normal);d&&r.normal.applyMatrix3(d).normalize();g=0;for(h=q.length;g<h;g++)p=q[g].clone(),d&&p.applyMatrix3(d).normalize(),r.vertexNormals.push(p);r.color.copy(t.color);g=0;for(h=y.length;g<h;g++)p=y[g],r.vertexColors.push(p.clone());r.materialIndex=t.materialIndex;r.centroid.copy(t.centroid);c&&r.centroid.applyMatrix4(c);i.push(r)}n=0;for(m=f.length;n<m;n++){c=f[n];d=[];g=0;
+this.material=this.color=null;this.uvs=[[]];this.z=null};THREE.RenderableObject=function(){this.z=this.object=null};THREE.RenderableParticle=function(){this.rotation=this.z=this.y=this.x=this.object=null;this.scale=new THREE.Vector2;this.material=null};THREE.RenderableLine=function(){this.z=null;this.v1=new THREE.RenderableVertex;this.v2=new THREE.RenderableVertex;this.material=null};THREE.GeometryUtils={merge:function(a,b){var c,d,e=a.vertices.length,f=b instanceof THREE.Mesh?b.geometry:b,g=a.vertices,h=f.vertices,i=a.faces,j=f.faces,l=a.faceVertexUvs[0],f=f.faceVertexUvs[0];b instanceof THREE.Mesh&&(b.matrixAutoUpdate&&b.updateMatrix(),c=b.matrix,d=new THREE.Matrix3,d.getInverse(c),d.transpose());for(var n=0,m=h.length;n<m;n++){var r=h[n].clone();c&&r.applyMatrix4(c);g.push(r)}n=0;for(m=j.length;n<m;n++){var r=j[n],u,p,q=r.vertexNormals,w=r.vertexColors;r instanceof THREE.Face3?
+u=new THREE.Face3(r.a+e,r.b+e,r.c+e):r instanceof THREE.Face4&&(u=new THREE.Face4(r.a+e,r.b+e,r.c+e,r.d+e));u.normal.copy(r.normal);d&&u.normal.applyMatrix3(d).normalize();g=0;for(h=q.length;g<h;g++)p=q[g].clone(),d&&p.applyMatrix3(d).normalize(),u.vertexNormals.push(p);u.color.copy(r.color);g=0;for(h=w.length;g<h;g++)p=w[g],u.vertexColors.push(p.clone());u.materialIndex=r.materialIndex;u.centroid.copy(r.centroid);c&&u.centroid.applyMatrix4(c);i.push(u)}n=0;for(m=f.length;n<m;n++){c=f[n];d=[];g=0;
 for(h=c.length;g<h;g++)d.push(new THREE.Vector2(c[g].x,c[g].y));l.push(d)}},removeMaterials:function(a,b){for(var c={},d=0,e=b.length;d<e;d++)c[b[d]]=!0;for(var f,g=[],d=0,e=a.faces.length;d<e;d++)f=a.faces[d],f.materialIndex in c||g.push(f);a.faces=g},randomPointInTriangle:function(a,b,c){var d,e,f,g=new THREE.Vector3,h=THREE.GeometryUtils.__v1;d=THREE.GeometryUtils.random();e=THREE.GeometryUtils.random();1<d+e&&(d=1-d,e=1-e);f=1-d-e;g.copy(a);g.multiplyScalar(d);h.copy(b);h.multiplyScalar(e);g.add(h);
 for(h=c.length;g<h;g++)d.push(new THREE.Vector2(c[g].x,c[g].y));l.push(d)}},removeMaterials:function(a,b){for(var c={},d=0,e=b.length;d<e;d++)c[b[d]]=!0;for(var f,g=[],d=0,e=a.faces.length;d<e;d++)f=a.faces[d],f.materialIndex in c||g.push(f);a.faces=g},randomPointInTriangle:function(a,b,c){var d,e,f,g=new THREE.Vector3,h=THREE.GeometryUtils.__v1;d=THREE.GeometryUtils.random();e=THREE.GeometryUtils.random();1<d+e&&(d=1-d,e=1-e);f=1-d-e;g.copy(a);g.multiplyScalar(d);h.copy(b);h.multiplyScalar(e);g.add(h);
 h.copy(c);h.multiplyScalar(f);g.add(h);return g},randomPointInFace:function(a,b,c){var d,e,f;if(a instanceof THREE.Face3)return d=b.vertices[a.a],e=b.vertices[a.b],f=b.vertices[a.c],THREE.GeometryUtils.randomPointInTriangle(d,e,f);if(a instanceof THREE.Face4){d=b.vertices[a.a];e=b.vertices[a.b];f=b.vertices[a.c];var b=b.vertices[a.d],g;c?a._area1&&a._area2?(c=a._area1,g=a._area2):(c=THREE.GeometryUtils.triangleArea(d,e,b),g=THREE.GeometryUtils.triangleArea(e,f,b),a._area1=c,a._area2=g):(c=THREE.GeometryUtils.triangleArea(d,
 h.copy(c);h.multiplyScalar(f);g.add(h);return g},randomPointInFace:function(a,b,c){var d,e,f;if(a instanceof THREE.Face3)return d=b.vertices[a.a],e=b.vertices[a.b],f=b.vertices[a.c],THREE.GeometryUtils.randomPointInTriangle(d,e,f);if(a instanceof THREE.Face4){d=b.vertices[a.a];e=b.vertices[a.b];f=b.vertices[a.c];var b=b.vertices[a.d],g;c?a._area1&&a._area2?(c=a._area1,g=a._area2):(c=THREE.GeometryUtils.triangleArea(d,e,b),g=THREE.GeometryUtils.triangleArea(e,f,b),a._area1=c,a._area2=g):(c=THREE.GeometryUtils.triangleArea(d,
-e,b),g=THREE.GeometryUtils.triangleArea(e,f,b));return THREE.GeometryUtils.random()*(c+g)<c?THREE.GeometryUtils.randomPointInTriangle(d,e,b):THREE.GeometryUtils.randomPointInTriangle(e,f,b)}},randomPointsInGeometry:function(a,b){function c(a){function b(c,d){if(d<c)return c;var e=c+Math.floor((d-c)/2);return k[e]>a?b(c,e-1):k[e]<a?b(e+1,d):e}return b(0,k.length-1)}var d,e,f=a.faces,g=a.vertices,h=f.length,i=0,k=[],l,n,m,t;for(e=0;e<h;e++)d=f[e],d instanceof THREE.Face3?(l=g[d.a],n=g[d.b],m=g[d.c],
-d._area=THREE.GeometryUtils.triangleArea(l,n,m)):d instanceof THREE.Face4&&(l=g[d.a],n=g[d.b],m=g[d.c],t=g[d.d],d._area1=THREE.GeometryUtils.triangleArea(l,n,t),d._area2=THREE.GeometryUtils.triangleArea(n,m,t),d._area=d._area1+d._area2),i+=d._area,k[e]=i;d=[];for(e=0;e<b;e++)g=THREE.GeometryUtils.random()*i,g=c(g),d[e]=THREE.GeometryUtils.randomPointInFace(f[g],a,!0);return d},triangleArea:function(a,b,c){var d=THREE.GeometryUtils.__v1,e=THREE.GeometryUtils.__v2;d.subVectors(b,a);e.subVectors(c,a);
+e,b),g=THREE.GeometryUtils.triangleArea(e,f,b));return THREE.GeometryUtils.random()*(c+g)<c?THREE.GeometryUtils.randomPointInTriangle(d,e,b):THREE.GeometryUtils.randomPointInTriangle(e,f,b)}},randomPointsInGeometry:function(a,b){function c(a){function b(c,d){if(d<c)return c;var e=c+Math.floor((d-c)/2);return j[e]>a?b(c,e-1):j[e]<a?b(e+1,d):e}return b(0,j.length-1)}var d,e,f=a.faces,g=a.vertices,h=f.length,i=0,j=[],l,n,m,r;for(e=0;e<h;e++)d=f[e],d instanceof THREE.Face3?(l=g[d.a],n=g[d.b],m=g[d.c],
+d._area=THREE.GeometryUtils.triangleArea(l,n,m)):d instanceof THREE.Face4&&(l=g[d.a],n=g[d.b],m=g[d.c],r=g[d.d],d._area1=THREE.GeometryUtils.triangleArea(l,n,r),d._area2=THREE.GeometryUtils.triangleArea(n,m,r),d._area=d._area1+d._area2),i+=d._area,j[e]=i;d=[];for(e=0;e<b;e++)g=THREE.GeometryUtils.random()*i,g=c(g),d[e]=THREE.GeometryUtils.randomPointInFace(f[g],a,!0);return d},triangleArea:function(a,b,c){var d=THREE.GeometryUtils.__v1,e=THREE.GeometryUtils.__v2;d.subVectors(b,a);e.subVectors(c,a);
 d.cross(e);return 0.5*d.length()},center:function(a){a.computeBoundingBox();var b=a.boundingBox,c=new THREE.Vector3;c.addVectors(b.min,b.max);c.multiplyScalar(-0.5);a.applyMatrix((new THREE.Matrix4).makeTranslation(c.x,c.y,c.z));a.computeBoundingBox();return c},normalizeUVs:function(a){for(var a=a.faceVertexUvs[0],b=0,c=a.length;b<c;b++)for(var d=a[b],e=0,f=d.length;e<f;e++)1!==d[e].x&&(d[e].x-=Math.floor(d[e].x)),1!==d[e].y&&(d[e].y-=Math.floor(d[e].y))},triangulateQuads:function(a){var b,c,d,e,
 d.cross(e);return 0.5*d.length()},center:function(a){a.computeBoundingBox();var b=a.boundingBox,c=new THREE.Vector3;c.addVectors(b.min,b.max);c.multiplyScalar(-0.5);a.applyMatrix((new THREE.Matrix4).makeTranslation(c.x,c.y,c.z));a.computeBoundingBox();return c},normalizeUVs:function(a){for(var a=a.faceVertexUvs[0],b=0,c=a.length;b<c;b++)for(var d=a[b],e=0,f=d.length;e<f;e++)1!==d[e].x&&(d[e].x-=Math.floor(d[e].x)),1!==d[e].y&&(d[e].y-=Math.floor(d[e].y))},triangulateQuads:function(a){var b,c,d,e,
-f=[],g=[],h=[];b=0;for(c=a.faceUvs.length;b<c;b++)g[b]=[];b=0;for(c=a.faceVertexUvs.length;b<c;b++)h[b]=[];b=0;for(c=a.faces.length;b<c;b++)if(d=a.faces[b],d instanceof THREE.Face4){e=d.a;var i=d.b,k=d.c,l=d.d,n=new THREE.Face3,m=new THREE.Face3;n.color.copy(d.color);m.color.copy(d.color);n.materialIndex=d.materialIndex;m.materialIndex=d.materialIndex;n.a=e;n.b=i;n.c=l;m.a=i;m.b=k;m.c=l;4===d.vertexColors.length&&(n.vertexColors[0]=d.vertexColors[0].clone(),n.vertexColors[1]=d.vertexColors[1].clone(),
-n.vertexColors[2]=d.vertexColors[3].clone(),m.vertexColors[0]=d.vertexColors[1].clone(),m.vertexColors[1]=d.vertexColors[2].clone(),m.vertexColors[2]=d.vertexColors[3].clone());f.push(n,m);d=0;for(e=a.faceVertexUvs.length;d<e;d++)a.faceVertexUvs[d].length&&(n=a.faceVertexUvs[d][b],i=n[1],k=n[2],l=n[3],n=[n[0].clone(),i.clone(),l.clone()],i=[i.clone(),k.clone(),l.clone()],h[d].push(n,i));d=0;for(e=a.faceUvs.length;d<e;d++)a.faceUvs[d].length&&(i=a.faceUvs[d][b],g[d].push(i,i))}else{f.push(d);d=0;for(e=
+f=[],g=[],h=[];b=0;for(c=a.faceUvs.length;b<c;b++)g[b]=[];b=0;for(c=a.faceVertexUvs.length;b<c;b++)h[b]=[];b=0;for(c=a.faces.length;b<c;b++)if(d=a.faces[b],d instanceof THREE.Face4){e=d.a;var i=d.b,j=d.c,l=d.d,n=new THREE.Face3,m=new THREE.Face3;n.color.copy(d.color);m.color.copy(d.color);n.materialIndex=d.materialIndex;m.materialIndex=d.materialIndex;n.a=e;n.b=i;n.c=l;m.a=i;m.b=j;m.c=l;4===d.vertexColors.length&&(n.vertexColors[0]=d.vertexColors[0].clone(),n.vertexColors[1]=d.vertexColors[1].clone(),
+n.vertexColors[2]=d.vertexColors[3].clone(),m.vertexColors[0]=d.vertexColors[1].clone(),m.vertexColors[1]=d.vertexColors[2].clone(),m.vertexColors[2]=d.vertexColors[3].clone());f.push(n,m);d=0;for(e=a.faceVertexUvs.length;d<e;d++)a.faceVertexUvs[d].length&&(n=a.faceVertexUvs[d][b],i=n[1],j=n[2],l=n[3],n=[n[0].clone(),i.clone(),l.clone()],i=[i.clone(),j.clone(),l.clone()],h[d].push(n,i));d=0;for(e=a.faceUvs.length;d<e;d++)a.faceUvs[d].length&&(i=a.faceUvs[d][b],g[d].push(i,i))}else{f.push(d);d=0;for(e=
 a.faceUvs.length;d<e;d++)g[d].push(a.faceUvs[d][b]);d=0;for(e=a.faceVertexUvs.length;d<e;d++)h[d].push(a.faceVertexUvs[d][b])}a.faces=f;a.faceUvs=g;a.faceVertexUvs=h;a.computeCentroids();a.computeFaceNormals();a.computeVertexNormals();a.hasTangents&&a.computeTangents()},setMaterialIndex:function(a,b,c,d){a=a.faces;d=d||a.length-1;for(c=c||0;c<=d;c++)a[c].materialIndex=b}};THREE.GeometryUtils.random=THREE.Math.random16;THREE.GeometryUtils.__v1=new THREE.Vector3;THREE.GeometryUtils.__v2=new THREE.Vector3;THREE.ImageUtils={crossOrigin:"anonymous",loadTexture:function(a,b,c,d){var e=new Image,f=new THREE.Texture(e,b),b=new THREE.ImageLoader;b.addEventListener("load",function(a){f.image=a.content;f.needsUpdate=!0;c&&c(f)});b.addEventListener("error",function(a){d&&d(a.message)});b.crossOrigin=this.crossOrigin;b.load(a,e);f.sourceFile=a;return f},loadCompressedTexture:function(a,b,c,d){var e=new THREE.CompressedTexture;e.mapping=b;var f=new XMLHttpRequest;f.onload=function(){var a=THREE.ImageUtils.parseDDS(f.response,
 a.faceUvs.length;d<e;d++)g[d].push(a.faceUvs[d][b]);d=0;for(e=a.faceVertexUvs.length;d<e;d++)h[d].push(a.faceVertexUvs[d][b])}a.faces=f;a.faceUvs=g;a.faceVertexUvs=h;a.computeCentroids();a.computeFaceNormals();a.computeVertexNormals();a.hasTangents&&a.computeTangents()},setMaterialIndex:function(a,b,c,d){a=a.faces;d=d||a.length-1;for(c=c||0;c<=d;c++)a[c].materialIndex=b}};THREE.GeometryUtils.random=THREE.Math.random16;THREE.GeometryUtils.__v1=new THREE.Vector3;THREE.GeometryUtils.__v2=new THREE.Vector3;THREE.ImageUtils={crossOrigin:"anonymous",loadTexture:function(a,b,c,d){var e=new Image,f=new THREE.Texture(e,b),b=new THREE.ImageLoader;b.addEventListener("load",function(a){f.image=a.content;f.needsUpdate=!0;c&&c(f)});b.addEventListener("error",function(a){d&&d(a.message)});b.crossOrigin=this.crossOrigin;b.load(a,e);f.sourceFile=a;return f},loadCompressedTexture:function(a,b,c,d){var e=new THREE.CompressedTexture;e.mapping=b;var f=new XMLHttpRequest;f.onload=function(){var a=THREE.ImageUtils.parseDDS(f.response,
 !0);e.format=a.format;e.mipmaps=a.mipmaps;e.image.width=a.width;e.image.height=a.height;e.generateMipmaps=!1;e.needsUpdate=!0;c&&c(e)};f.onerror=d;f.open("GET",a,!0);f.responseType="arraybuffer";f.send(null);return e},loadTextureCube:function(a,b,c,d){var e=[];e.loadCount=0;var f=new THREE.Texture;f.image=e;void 0!==b&&(f.mapping=b);f.flipY=!1;for(var b=0,g=a.length;b<g;++b){var h=new Image;e[b]=h;h.onload=function(){e.loadCount+=1;6===e.loadCount&&(f.needsUpdate=!0,c&&c(f))};h.onerror=d;h.crossOrigin=
 !0);e.format=a.format;e.mipmaps=a.mipmaps;e.image.width=a.width;e.image.height=a.height;e.generateMipmaps=!1;e.needsUpdate=!0;c&&c(e)};f.onerror=d;f.open("GET",a,!0);f.responseType="arraybuffer";f.send(null);return e},loadTextureCube:function(a,b,c,d){var e=[];e.loadCount=0;var f=new THREE.Texture;f.image=e;void 0!==b&&(f.mapping=b);f.flipY=!1;for(var b=0,g=a.length;b<g;++b){var h=new Image;e[b]=h;h.onload=function(){e.loadCount+=1;6===e.loadCount&&(f.needsUpdate=!0,c&&c(f))};h.onerror=d;h.crossOrigin=
 this.crossOrigin;h.src=a[b]}return f},loadCompressedTextureCube:function(a,b,c,d){var e=[];e.loadCount=0;var f=new THREE.CompressedTexture;f.image=e;void 0!==b&&(f.mapping=b);f.flipY=!1;f.generateMipmaps=!1;b=function(a,b){return function(){var d=THREE.ImageUtils.parseDDS(a.response,!0);b.format=d.format;b.mipmaps=d.mipmaps;b.width=d.width;b.height=d.height;e.loadCount+=1;6===e.loadCount&&(f.format=d.format,f.needsUpdate=!0,c&&c(f))}};if(a instanceof Array)for(var g=0,h=a.length;g<h;++g){var i={};
 this.crossOrigin;h.src=a[b]}return f},loadCompressedTextureCube:function(a,b,c,d){var e=[];e.loadCount=0;var f=new THREE.CompressedTexture;f.image=e;void 0!==b&&(f.mapping=b);f.flipY=!1;f.generateMipmaps=!1;b=function(a,b){return function(){var d=THREE.ImageUtils.parseDDS(a.response,!0);b.format=d.format;b.mipmaps=d.mipmaps;b.width=d.width;b.height=d.height;e.loadCount+=1;6===e.loadCount&&(f.format=d.format,f.needsUpdate=!0,c&&c(f))}};if(a instanceof Array)for(var g=0,h=a.length;g<h;++g){var i={};
-e[g]=i;var k=new XMLHttpRequest;k.onload=b(k,i);k.onerror=d;i=a[g];k.open("GET",i,!0);k.responseType="arraybuffer";k.send(null)}else k=new XMLHttpRequest,k.onload=function(){var a=THREE.ImageUtils.parseDDS(k.response,!0);if(a.isCubemap){for(var b=a.mipmaps.length/a.mipmapCount,d=0;d<b;d++){e[d]={mipmaps:[]};for(var g=0;g<a.mipmapCount;g++)e[d].mipmaps.push(a.mipmaps[d*a.mipmapCount+g]),e[d].format=a.format,e[d].width=a.width,e[d].height=a.height}f.format=a.format;f.needsUpdate=!0;c&&c(f)}},k.onerror=
-d,k.open("GET",a,!0),k.responseType="arraybuffer",k.send(null);return f},parseDDS:function(a,b){function c(a){return a.charCodeAt(0)+(a.charCodeAt(1)<<8)+(a.charCodeAt(2)<<16)+(a.charCodeAt(3)<<24)}var d={mipmaps:[],width:0,height:0,format:null,mipmapCount:1},e=c("DXT1"),f=c("DXT3"),g=c("DXT5"),h=new Int32Array(a,0,31);if(542327876!==h[0])return console.error("ImageUtils.parseDDS(): Invalid magic number in DDS header"),d;if(!h[20]&4)return console.error("ImageUtils.parseDDS(): Unsupported format, must contain a FourCC code"),
+e[g]=i;var j=new XMLHttpRequest;j.onload=b(j,i);j.onerror=d;i=a[g];j.open("GET",i,!0);j.responseType="arraybuffer";j.send(null)}else j=new XMLHttpRequest,j.onload=function(){var a=THREE.ImageUtils.parseDDS(j.response,!0);if(a.isCubemap){for(var b=a.mipmaps.length/a.mipmapCount,d=0;d<b;d++){e[d]={mipmaps:[]};for(var g=0;g<a.mipmapCount;g++)e[d].mipmaps.push(a.mipmaps[d*a.mipmapCount+g]),e[d].format=a.format,e[d].width=a.width,e[d].height=a.height}f.format=a.format;f.needsUpdate=!0;c&&c(f)}},j.onerror=
+d,j.open("GET",a,!0),j.responseType="arraybuffer",j.send(null);return f},parseDDS:function(a,b){function c(a){return a.charCodeAt(0)+(a.charCodeAt(1)<<8)+(a.charCodeAt(2)<<16)+(a.charCodeAt(3)<<24)}var d={mipmaps:[],width:0,height:0,format:null,mipmapCount:1},e=c("DXT1"),f=c("DXT3"),g=c("DXT5"),h=new Int32Array(a,0,31);if(542327876!==h[0])return console.error("ImageUtils.parseDDS(): Invalid magic number in DDS header"),d;if(!h[20]&4)return console.error("ImageUtils.parseDDS(): Unsupported format, must contain a FourCC code"),
 d;var i=h[21];switch(i){case e:e=8;d.format=THREE.RGB_S3TC_DXT1_Format;break;case f:e=16;d.format=THREE.RGBA_S3TC_DXT3_Format;break;case g:e=16;d.format=THREE.RGBA_S3TC_DXT5_Format;break;default:return console.error("ImageUtils.parseDDS(): Unsupported FourCC code: ",String.fromCharCode(i&255,i>>8&255,i>>16&255,i>>24&255)),d}d.mipmapCount=1;h[2]&131072&&!1!==b&&(d.mipmapCount=Math.max(1,h[7]));d.isCubemap=h[28]&512?!0:!1;d.width=h[4];d.height=h[3];for(var h=h[1]+4,f=d.width,g=d.height,i=d.isCubemap?
 d;var i=h[21];switch(i){case e:e=8;d.format=THREE.RGB_S3TC_DXT1_Format;break;case f:e=16;d.format=THREE.RGBA_S3TC_DXT3_Format;break;case g:e=16;d.format=THREE.RGBA_S3TC_DXT5_Format;break;default:return console.error("ImageUtils.parseDDS(): Unsupported FourCC code: ",String.fromCharCode(i&255,i>>8&255,i>>16&255,i>>24&255)),d}d.mipmapCount=1;h[2]&131072&&!1!==b&&(d.mipmapCount=Math.max(1,h[7]));d.isCubemap=h[28]&512?!0:!1;d.width=h[4];d.height=h[3];for(var h=h[1]+4,f=d.width,g=d.height,i=d.isCubemap?
-6:1,k=0;k<i;k++){for(var l=0;l<d.mipmapCount;l++){var n=Math.max(4,f)/4*Math.max(4,g)/4*e,m={data:new Uint8Array(a,h,n),width:f,height:g};d.mipmaps.push(m);h+=n;f=Math.max(0.5*f,1);g=Math.max(0.5*g,1)}f=d.width;g=d.height}return d},getNormalMap:function(a,b){var c=function(a){var b=Math.sqrt(a[0]*a[0]+a[1]*a[1]+a[2]*a[2]);return[a[0]/b,a[1]/b,a[2]/b]},b=b|1,d=a.width,e=a.height,f=document.createElement("canvas");f.width=d;f.height=e;var g=f.getContext("2d");g.drawImage(a,0,0);for(var h=g.getImageData(0,
-0,d,e).data,i=g.createImageData(d,e),k=i.data,l=0;l<d;l++)for(var n=0;n<e;n++){var m=0>n-1?0:n-1,t=n+1>e-1?e-1:n+1,r=0>l-1?0:l-1,p=l+1>d-1?d-1:l+1,q=[],y=[0,0,h[4*(n*d+l)]/255*b];q.push([-1,0,h[4*(n*d+r)]/255*b]);q.push([-1,-1,h[4*(m*d+r)]/255*b]);q.push([0,-1,h[4*(m*d+l)]/255*b]);q.push([1,-1,h[4*(m*d+p)]/255*b]);q.push([1,0,h[4*(n*d+p)]/255*b]);q.push([1,1,h[4*(t*d+p)]/255*b]);q.push([0,1,h[4*(t*d+l)]/255*b]);q.push([-1,1,h[4*(t*d+r)]/255*b]);m=[];r=q.length;for(t=0;t<r;t++){var p=q[t],v=q[(t+1)%
-r],p=[p[0]-y[0],p[1]-y[1],p[2]-y[2]],v=[v[0]-y[0],v[1]-y[1],v[2]-y[2]];m.push(c([p[1]*v[2]-p[2]*v[1],p[2]*v[0]-p[0]*v[2],p[0]*v[1]-p[1]*v[0]]))}q=[0,0,0];for(t=0;t<m.length;t++)q[0]+=m[t][0],q[1]+=m[t][1],q[2]+=m[t][2];q[0]/=m.length;q[1]/=m.length;q[2]/=m.length;y=4*(n*d+l);k[y]=255*((q[0]+1)/2)|0;k[y+1]=255*((q[1]+1)/2)|0;k[y+2]=255*q[2]|0;k[y+3]=255}g.putImageData(i,0,0);return f},generateDataTexture:function(a,b,c){for(var d=a*b,e=new Uint8Array(3*d),f=Math.floor(255*c.r),g=Math.floor(255*c.g),
+6:1,j=0;j<i;j++){for(var l=0;l<d.mipmapCount;l++){var n=Math.max(4,f)/4*Math.max(4,g)/4*e,m={data:new Uint8Array(a,h,n),width:f,height:g};d.mipmaps.push(m);h+=n;f=Math.max(0.5*f,1);g=Math.max(0.5*g,1)}f=d.width;g=d.height}return d},getNormalMap:function(a,b){var c=function(a){var b=Math.sqrt(a[0]*a[0]+a[1]*a[1]+a[2]*a[2]);return[a[0]/b,a[1]/b,a[2]/b]},b=b|1,d=a.width,e=a.height,f=document.createElement("canvas");f.width=d;f.height=e;var g=f.getContext("2d");g.drawImage(a,0,0);for(var h=g.getImageData(0,
+0,d,e).data,i=g.createImageData(d,e),j=i.data,l=0;l<d;l++)for(var n=0;n<e;n++){var m=0>n-1?0:n-1,r=n+1>e-1?e-1:n+1,u=0>l-1?0:l-1,p=l+1>d-1?d-1:l+1,q=[],w=[0,0,h[4*(n*d+l)]/255*b];q.push([-1,0,h[4*(n*d+u)]/255*b]);q.push([-1,-1,h[4*(m*d+u)]/255*b]);q.push([0,-1,h[4*(m*d+l)]/255*b]);q.push([1,-1,h[4*(m*d+p)]/255*b]);q.push([1,0,h[4*(n*d+p)]/255*b]);q.push([1,1,h[4*(r*d+p)]/255*b]);q.push([0,1,h[4*(r*d+l)]/255*b]);q.push([-1,1,h[4*(r*d+u)]/255*b]);m=[];u=q.length;for(r=0;r<u;r++){var p=q[r],v=q[(r+1)%
+u],p=[p[0]-w[0],p[1]-w[1],p[2]-w[2]],v=[v[0]-w[0],v[1]-w[1],v[2]-w[2]];m.push(c([p[1]*v[2]-p[2]*v[1],p[2]*v[0]-p[0]*v[2],p[0]*v[1]-p[1]*v[0]]))}q=[0,0,0];for(r=0;r<m.length;r++)q[0]+=m[r][0],q[1]+=m[r][1],q[2]+=m[r][2];q[0]/=m.length;q[1]/=m.length;q[2]/=m.length;w=4*(n*d+l);j[w]=255*((q[0]+1)/2)|0;j[w+1]=255*((q[1]+1)/2)|0;j[w+2]=255*q[2]|0;j[w+3]=255}g.putImageData(i,0,0);return f},generateDataTexture:function(a,b,c){for(var d=a*b,e=new Uint8Array(3*d),f=Math.floor(255*c.r),g=Math.floor(255*c.g),
 c=Math.floor(255*c.b),h=0;h<d;h++)e[3*h]=f,e[3*h+1]=g,e[3*h+2]=c;a=new THREE.DataTexture(e,a,b,THREE.RGBFormat);a.needsUpdate=!0;return a}};THREE.SceneUtils={createMultiMaterialObject:function(a,b){for(var c=new THREE.Object3D,d=0,e=b.length;d<e;d++)c.add(new THREE.Mesh(a,b[d]));return c},detach:function(a,b,c){a.applyMatrix(b.matrixWorld);b.remove(a);c.add(a)},attach:function(a,b,c){var d=new THREE.Matrix4;d.getInverse(c.matrixWorld);a.applyMatrix(d);b.remove(a);c.add(a)}};THREE.FontUtils={faces:{},face:"helvetiker",weight:"normal",style:"normal",size:150,divisions:10,getFace:function(){return this.faces[this.face][this.weight][this.style]},loadFace:function(a){var b=a.familyName.toLowerCase();this.faces[b]=this.faces[b]||{};this.faces[b][a.cssFontWeight]=this.faces[b][a.cssFontWeight]||{};this.faces[b][a.cssFontWeight][a.cssFontStyle]=a;return this.faces[b][a.cssFontWeight][a.cssFontStyle]=a},drawText:function(a){for(var b=this.getFace(),c=this.size/b.resolution,d=
 c=Math.floor(255*c.b),h=0;h<d;h++)e[3*h]=f,e[3*h+1]=g,e[3*h+2]=c;a=new THREE.DataTexture(e,a,b,THREE.RGBFormat);a.needsUpdate=!0;return a}};THREE.SceneUtils={createMultiMaterialObject:function(a,b){for(var c=new THREE.Object3D,d=0,e=b.length;d<e;d++)c.add(new THREE.Mesh(a,b[d]));return c},detach:function(a,b,c){a.applyMatrix(b.matrixWorld);b.remove(a);c.add(a)},attach:function(a,b,c){var d=new THREE.Matrix4;d.getInverse(c.matrixWorld);a.applyMatrix(d);b.remove(a);c.add(a)}};THREE.FontUtils={faces:{},face:"helvetiker",weight:"normal",style:"normal",size:150,divisions:10,getFace:function(){return this.faces[this.face][this.weight][this.style]},loadFace:function(a){var b=a.familyName.toLowerCase();this.faces[b]=this.faces[b]||{};this.faces[b][a.cssFontWeight]=this.faces[b][a.cssFontWeight]||{};this.faces[b][a.cssFontWeight][a.cssFontStyle]=a;return this.faces[b][a.cssFontWeight][a.cssFontStyle]=a},drawText:function(a){for(var b=this.getFace(),c=this.size/b.resolution,d=
-0,e=String(a).split(""),f=e.length,g=[],a=0;a<f;a++){var h=new THREE.Path,h=this.extractGlyphPoints(e[a],b,c,d,h),d=d+h.offset;g.push(h.path)}return{paths:g,offset:d/2}},extractGlyphPoints:function(a,b,c,d,e){var f=[],g,h,i,k,l,n,m,t,r,p,q,y=b.glyphs[a]||b.glyphs["?"];if(y){if(y.o){b=y._cachedOutline||(y._cachedOutline=y.o.split(" "));k=b.length;for(a=0;a<k;)switch(i=b[a++],i){case "m":i=b[a++]*c+d;l=b[a++]*c;e.moveTo(i,l);break;case "l":i=b[a++]*c+d;l=b[a++]*c;e.lineTo(i,l);break;case "q":i=b[a++]*
-c+d;l=b[a++]*c;t=b[a++]*c+d;r=b[a++]*c;e.quadraticCurveTo(t,r,i,l);if(g=f[f.length-1]){n=g.x;m=g.y;g=1;for(h=this.divisions;g<=h;g++){var v=g/h;THREE.Shape.Utils.b2(v,n,t,i);THREE.Shape.Utils.b2(v,m,r,l)}}break;case "b":if(i=b[a++]*c+d,l=b[a++]*c,t=b[a++]*c+d,r=b[a++]*-c,p=b[a++]*c+d,q=b[a++]*-c,e.bezierCurveTo(i,l,t,r,p,q),g=f[f.length-1]){n=g.x;m=g.y;g=1;for(h=this.divisions;g<=h;g++)v=g/h,THREE.Shape.Utils.b3(v,n,t,p,i),THREE.Shape.Utils.b3(v,m,r,q,l)}}}return{offset:y.ha*c,path:e}}}};
+0,e=String(a).split(""),f=e.length,g=[],a=0;a<f;a++){var h=new THREE.Path,h=this.extractGlyphPoints(e[a],b,c,d,h),d=d+h.offset;g.push(h.path)}return{paths:g,offset:d/2}},extractGlyphPoints:function(a,b,c,d,e){var f=[],g,h,i,j,l,n,m,r,u,p,q,w=b.glyphs[a]||b.glyphs["?"];if(w){if(w.o){b=w._cachedOutline||(w._cachedOutline=w.o.split(" "));j=b.length;for(a=0;a<j;)switch(i=b[a++],i){case "m":i=b[a++]*c+d;l=b[a++]*c;e.moveTo(i,l);break;case "l":i=b[a++]*c+d;l=b[a++]*c;e.lineTo(i,l);break;case "q":i=b[a++]*
+c+d;l=b[a++]*c;r=b[a++]*c+d;u=b[a++]*c;e.quadraticCurveTo(r,u,i,l);if(g=f[f.length-1]){n=g.x;m=g.y;g=1;for(h=this.divisions;g<=h;g++){var v=g/h;THREE.Shape.Utils.b2(v,n,r,i);THREE.Shape.Utils.b2(v,m,u,l)}}break;case "b":if(i=b[a++]*c+d,l=b[a++]*c,r=b[a++]*c+d,u=b[a++]*-c,p=b[a++]*c+d,q=b[a++]*-c,e.bezierCurveTo(i,l,r,u,p,q),g=f[f.length-1]){n=g.x;m=g.y;g=1;for(h=this.divisions;g<=h;g++)v=g/h,THREE.Shape.Utils.b3(v,n,r,p,i),THREE.Shape.Utils.b3(v,m,u,q,l)}}}return{offset:w.ha*c,path:e}}}};
 THREE.FontUtils.generateShapes=function(a,b){var b=b||{},c=void 0!==b.curveSegments?b.curveSegments:4,d=void 0!==b.font?b.font:"helvetiker",e=void 0!==b.weight?b.weight:"normal",f=void 0!==b.style?b.style:"normal";THREE.FontUtils.size=void 0!==b.size?b.size:100;THREE.FontUtils.divisions=c;THREE.FontUtils.face=d;THREE.FontUtils.weight=e;THREE.FontUtils.style=f;c=THREE.FontUtils.drawText(a).paths;d=[];e=0;for(f=c.length;e<f;e++)Array.prototype.push.apply(d,c[e].toShapes());return d};
 THREE.FontUtils.generateShapes=function(a,b){var b=b||{},c=void 0!==b.curveSegments?b.curveSegments:4,d=void 0!==b.font?b.font:"helvetiker",e=void 0!==b.weight?b.weight:"normal",f=void 0!==b.style?b.style:"normal";THREE.FontUtils.size=void 0!==b.size?b.size:100;THREE.FontUtils.divisions=c;THREE.FontUtils.face=d;THREE.FontUtils.weight=e;THREE.FontUtils.style=f;c=THREE.FontUtils.drawText(a).paths;d=[];e=0;for(f=c.length;e<f;e++)Array.prototype.push.apply(d,c[e].toShapes());return d};
-(function(a){var b=function(a){for(var b=a.length,e=0,f=b-1,g=0;g<b;f=g++)e+=a[f].x*a[g].y-a[g].x*a[f].y;return 0.5*e};a.Triangulate=function(a,d){var e=a.length;if(3>e)return null;var f=[],g=[],h=[],i,k,l;if(0<b(a))for(k=0;k<e;k++)g[k]=k;else for(k=0;k<e;k++)g[k]=e-1-k;var n=2*e;for(k=e-1;2<e;){if(0>=n--){console.log("Warning, unable to triangulate polygon!");break}i=k;e<=i&&(i=0);k=i+1;e<=k&&(k=0);l=k+1;e<=l&&(l=0);var m;a:{var t=m=void 0,r=void 0,p=void 0,q=void 0,y=void 0,v=void 0,z=void 0,s=
-void 0,t=a[g[i]].x,r=a[g[i]].y,p=a[g[k]].x,q=a[g[k]].y,y=a[g[l]].x,v=a[g[l]].y;if(1E-10>(p-t)*(v-r)-(q-r)*(y-t))m=!1;else{var C=void 0,H=void 0,B=void 0,w=void 0,I=void 0,J=void 0,E=void 0,Z=void 0,A=void 0,U=void 0,A=Z=E=s=z=void 0,C=y-p,H=v-q,B=t-y,w=r-v,I=p-t,J=q-r;for(m=0;m<e;m++)if(!(m===i||m===k||m===l))if(z=a[g[m]].x,s=a[g[m]].y,E=z-t,Z=s-r,A=z-p,U=s-q,z-=y,s-=v,A=C*U-H*A,E=I*Z-J*E,Z=B*s-w*z,0<=A&&0<=Z&&0<=E){m=!1;break a}m=!0}}if(m){f.push([a[g[i]],a[g[k]],a[g[l]]]);h.push([g[i],g[k],g[l]]);
-i=k;for(l=k+1;l<e;i++,l++)g[i]=g[l];e--;n=2*e}}return d?h:f};a.Triangulate.area=b;return a})(THREE.FontUtils);self._typeface_js={faces:THREE.FontUtils.faces,loadFace:THREE.FontUtils.loadFace};THREE.Curve=function(){};THREE.Curve.prototype.getPoint=function(){console.log("Warning, getPoint() not implemented!");return null};THREE.Curve.prototype.getPointAt=function(a){a=this.getUtoTmapping(a);return this.getPoint(a)};THREE.Curve.prototype.getPoints=function(a){a||(a=5);var b,c=[];for(b=0;b<=a;b++)c.push(this.getPoint(b/a));return c};THREE.Curve.prototype.getSpacedPoints=function(a){a||(a=5);var b,c=[];for(b=0;b<=a;b++)c.push(this.getPointAt(b/a));return c};
+(function(a){var b=function(a){for(var b=a.length,e=0,f=b-1,g=0;g<b;f=g++)e+=a[f].x*a[g].y-a[g].x*a[f].y;return 0.5*e};a.Triangulate=function(a,d){var e=a.length;if(3>e)return null;var f=[],g=[],h=[],i,j,l;if(0<b(a))for(j=0;j<e;j++)g[j]=j;else for(j=0;j<e;j++)g[j]=e-1-j;var n=2*e;for(j=e-1;2<e;){if(0>=n--){console.log("Warning, unable to triangulate polygon!");break}i=j;e<=i&&(i=0);j=i+1;e<=j&&(j=0);l=j+1;e<=l&&(l=0);var m;a:{var r=m=void 0,u=void 0,p=void 0,q=void 0,w=void 0,v=void 0,z=void 0,y=
+void 0,r=a[g[i]].x,u=a[g[i]].y,p=a[g[j]].x,q=a[g[j]].y,w=a[g[l]].x,v=a[g[l]].y;if(1E-10>(p-r)*(v-u)-(q-u)*(w-r))m=!1;else{var t=void 0,D=void 0,C=void 0,k=void 0,I=void 0,J=void 0,B=void 0,P=void 0,A=void 0,G=void 0,A=P=B=y=z=void 0,t=w-p,D=v-q,C=r-w,k=u-v,I=p-r,J=q-u;for(m=0;m<e;m++)if(!(m===i||m===j||m===l))if(z=a[g[m]].x,y=a[g[m]].y,B=z-r,P=y-u,A=z-p,G=y-q,z-=w,y-=v,A=t*G-D*A,B=I*P-J*B,P=C*y-k*z,0<=A&&0<=P&&0<=B){m=!1;break a}m=!0}}if(m){f.push([a[g[i]],a[g[j]],a[g[l]]]);h.push([g[i],g[j],g[l]]);
+i=j;for(l=j+1;l<e;i++,l++)g[i]=g[l];e--;n=2*e}}return d?h:f};a.Triangulate.area=b;return a})(THREE.FontUtils);self._typeface_js={faces:THREE.FontUtils.faces,loadFace:THREE.FontUtils.loadFace};THREE.Curve=function(){};THREE.Curve.prototype.getPoint=function(){console.log("Warning, getPoint() not implemented!");return null};THREE.Curve.prototype.getPointAt=function(a){a=this.getUtoTmapping(a);return this.getPoint(a)};THREE.Curve.prototype.getPoints=function(a){a||(a=5);var b,c=[];for(b=0;b<=a;b++)c.push(this.getPoint(b/a));return c};THREE.Curve.prototype.getSpacedPoints=function(a){a||(a=5);var b,c=[];for(b=0;b<=a;b++)c.push(this.getPointAt(b/a));return c};
 THREE.Curve.prototype.getLength=function(){var a=this.getLengths();return a[a.length-1]};THREE.Curve.prototype.getLengths=function(a){a||(a=this.__arcLengthDivisions?this.__arcLengthDivisions:200);if(this.cacheArcLengths&&this.cacheArcLengths.length==a+1&&!this.needsUpdate)return this.cacheArcLengths;this.needsUpdate=!1;var b=[],c,d=this.getPoint(0),e,f=0;b.push(0);for(e=1;e<=a;e++)c=this.getPoint(e/a),f+=c.distanceTo(d),b.push(f),d=c;return this.cacheArcLengths=b};
 THREE.Curve.prototype.getLength=function(){var a=this.getLengths();return a[a.length-1]};THREE.Curve.prototype.getLengths=function(a){a||(a=this.__arcLengthDivisions?this.__arcLengthDivisions:200);if(this.cacheArcLengths&&this.cacheArcLengths.length==a+1&&!this.needsUpdate)return this.cacheArcLengths;this.needsUpdate=!1;var b=[],c,d=this.getPoint(0),e,f=0;b.push(0);for(e=1;e<=a;e++)c=this.getPoint(e/a),f+=c.distanceTo(d),b.push(f),d=c;return this.cacheArcLengths=b};
 THREE.Curve.prototype.updateArcLengths=function(){this.needsUpdate=!0;this.getLengths()};THREE.Curve.prototype.getUtoTmapping=function(a,b){var c=this.getLengths(),d=0,e=c.length,f;f=b?b:a*c[e-1];for(var g=0,h=e-1,i;g<=h;)if(d=Math.floor(g+(h-g)/2),i=c[d]-f,0>i)g=d+1;else if(0<i)h=d-1;else{h=d;break}d=h;if(c[d]==f)return d/(e-1);g=c[d];return c=(d+(f-g)/(c[d+1]-g))/(e-1)};THREE.Curve.prototype.getTangent=function(a){var b=a-1E-4,a=a+1E-4;0>b&&(b=0);1<a&&(a=1);b=this.getPoint(b);return this.getPoint(a).clone().sub(b).normalize()};
 THREE.Curve.prototype.updateArcLengths=function(){this.needsUpdate=!0;this.getLengths()};THREE.Curve.prototype.getUtoTmapping=function(a,b){var c=this.getLengths(),d=0,e=c.length,f;f=b?b:a*c[e-1];for(var g=0,h=e-1,i;g<=h;)if(d=Math.floor(g+(h-g)/2),i=c[d]-f,0>i)g=d+1;else if(0<i)h=d-1;else{h=d;break}d=h;if(c[d]==f)return d/(e-1);g=c[d];return c=(d+(f-g)/(c[d+1]-g))/(e-1)};THREE.Curve.prototype.getTangent=function(a){var b=a-1E-4,a=a+1E-4;0>b&&(b=0);1<a&&(a=1);b=this.getPoint(b);return this.getPoint(a).clone().sub(b).normalize()};
 THREE.Curve.prototype.getTangentAt=function(a){a=this.getUtoTmapping(a);return this.getTangent(a)};THREE.LineCurve=function(a,b){this.v1=a;this.v2=b};THREE.LineCurve.prototype=Object.create(THREE.Curve.prototype);THREE.LineCurve.prototype.getPoint=function(a){var b=this.v2.clone().sub(this.v1);b.multiplyScalar(a).add(this.v1);return b};THREE.LineCurve.prototype.getPointAt=function(a){return this.getPoint(a)};THREE.LineCurve.prototype.getTangent=function(){return this.v2.clone().sub(this.v1).normalize()};
 THREE.Curve.prototype.getTangentAt=function(a){a=this.getUtoTmapping(a);return this.getTangent(a)};THREE.LineCurve=function(a,b){this.v1=a;this.v2=b};THREE.LineCurve.prototype=Object.create(THREE.Curve.prototype);THREE.LineCurve.prototype.getPoint=function(a){var b=this.v2.clone().sub(this.v1);b.multiplyScalar(a).add(this.v1);return b};THREE.LineCurve.prototype.getPointAt=function(a){return this.getPoint(a)};THREE.LineCurve.prototype.getTangent=function(){return this.v2.clone().sub(this.v1).normalize()};
@@ -539,7 +539,7 @@ THREE.ClosedSplineCurve3=THREE.Curve.create(function(a){this.points=void 0==a?[]
 d[c[1]].z,d[c[2]].z,d[c[3]].z,e);return b});THREE.CurvePath=function(){this.curves=[];this.bends=[];this.autoClose=!1};THREE.CurvePath.prototype=Object.create(THREE.Curve.prototype);THREE.CurvePath.prototype.add=function(a){this.curves.push(a)};THREE.CurvePath.prototype.checkConnection=function(){};THREE.CurvePath.prototype.closePath=function(){var a=this.curves[0].getPoint(0),b=this.curves[this.curves.length-1].getPoint(1);a.equals(b)||this.curves.push(new THREE.LineCurve(b,a))};
 d[c[1]].z,d[c[2]].z,d[c[3]].z,e);return b});THREE.CurvePath=function(){this.curves=[];this.bends=[];this.autoClose=!1};THREE.CurvePath.prototype=Object.create(THREE.Curve.prototype);THREE.CurvePath.prototype.add=function(a){this.curves.push(a)};THREE.CurvePath.prototype.checkConnection=function(){};THREE.CurvePath.prototype.closePath=function(){var a=this.curves[0].getPoint(0),b=this.curves[this.curves.length-1].getPoint(1);a.equals(b)||this.curves.push(new THREE.LineCurve(b,a))};
 THREE.CurvePath.prototype.getPoint=function(a){for(var b=a*this.getLength(),c=this.getCurveLengths(),a=0;a<c.length;){if(c[a]>=b)return b=c[a]-b,a=this.curves[a],b=1-b/a.getLength(),a.getPointAt(b);a++}return null};THREE.CurvePath.prototype.getLength=function(){var a=this.getCurveLengths();return a[a.length-1]};
 THREE.CurvePath.prototype.getPoint=function(a){for(var b=a*this.getLength(),c=this.getCurveLengths(),a=0;a<c.length;){if(c[a]>=b)return b=c[a]-b,a=this.curves[a],b=1-b/a.getLength(),a.getPointAt(b);a++}return null};THREE.CurvePath.prototype.getLength=function(){var a=this.getCurveLengths();return a[a.length-1]};
 THREE.CurvePath.prototype.getCurveLengths=function(){if(this.cacheLengths&&this.cacheLengths.length==this.curves.length)return this.cacheLengths;var a=[],b=0,c,d=this.curves.length;for(c=0;c<d;c++)b+=this.curves[c].getLength(),a.push(b);return this.cacheLengths=a};
 THREE.CurvePath.prototype.getCurveLengths=function(){if(this.cacheLengths&&this.cacheLengths.length==this.curves.length)return this.cacheLengths;var a=[],b=0,c,d=this.curves.length;for(c=0;c<d;c++)b+=this.curves[c].getLength(),a.push(b);return this.cacheLengths=a};
-THREE.CurvePath.prototype.getBoundingBox=function(){var a=this.getPoints(),b,c,d,e,f,g;b=c=Number.NEGATIVE_INFINITY;e=f=Number.POSITIVE_INFINITY;var h,i,k,l,n=a[0]instanceof THREE.Vector3;l=n?new THREE.Vector3:new THREE.Vector2;i=0;for(k=a.length;i<k;i++)h=a[i],h.x>b?b=h.x:h.x<e&&(e=h.x),h.y>c?c=h.y:h.y<f&&(f=h.y),n&&(h.z>d?d=h.z:h.z<g&&(g=h.z)),l.add(h);a={minX:e,minY:f,maxX:b,maxY:c,centroid:l.divideScalar(k)};n&&(a.maxZ=d,a.minZ=g);return a};
+THREE.CurvePath.prototype.getBoundingBox=function(){var a=this.getPoints(),b,c,d,e,f,g;b=c=Number.NEGATIVE_INFINITY;e=f=Number.POSITIVE_INFINITY;var h,i,j,l,n=a[0]instanceof THREE.Vector3;l=n?new THREE.Vector3:new THREE.Vector2;i=0;for(j=a.length;i<j;i++)h=a[i],h.x>b?b=h.x:h.x<e&&(e=h.x),h.y>c?c=h.y:h.y<f&&(f=h.y),n&&(h.z>d?d=h.z:h.z<g&&(g=h.z)),l.add(h);a={minX:e,minY:f,maxX:b,maxY:c,centroid:l.divideScalar(j)};n&&(a.maxZ=d,a.minZ=g);return a};
 THREE.CurvePath.prototype.createPointsGeometry=function(a){a=this.getPoints(a,!0);return this.createGeometry(a)};THREE.CurvePath.prototype.createSpacedPointsGeometry=function(a){a=this.getSpacedPoints(a,!0);return this.createGeometry(a)};THREE.CurvePath.prototype.createGeometry=function(a){for(var b=new THREE.Geometry,c=0;c<a.length;c++)b.vertices.push(new THREE.Vector3(a[c].x,a[c].y,a[c].z||0));return b};THREE.CurvePath.prototype.addWrapPath=function(a){this.bends.push(a)};
 THREE.CurvePath.prototype.createPointsGeometry=function(a){a=this.getPoints(a,!0);return this.createGeometry(a)};THREE.CurvePath.prototype.createSpacedPointsGeometry=function(a){a=this.getSpacedPoints(a,!0);return this.createGeometry(a)};THREE.CurvePath.prototype.createGeometry=function(a){for(var b=new THREE.Geometry,c=0;c<a.length;c++)b.vertices.push(new THREE.Vector3(a[c].x,a[c].y,a[c].z||0));return b};THREE.CurvePath.prototype.addWrapPath=function(a){this.bends.push(a)};
 THREE.CurvePath.prototype.getTransformedPoints=function(a,b){var c=this.getPoints(a),d,e;b||(b=this.bends);d=0;for(e=b.length;d<e;d++)c=this.getWrapPoints(c,b[d]);return c};THREE.CurvePath.prototype.getTransformedSpacedPoints=function(a,b){var c=this.getSpacedPoints(a),d,e;b||(b=this.bends);d=0;for(e=b.length;d<e;d++)c=this.getWrapPoints(c,b[d]);return c};
 THREE.CurvePath.prototype.getTransformedPoints=function(a,b){var c=this.getPoints(a),d,e;b||(b=this.bends);d=0;for(e=b.length;d<e;d++)c=this.getWrapPoints(c,b[d]);return c};THREE.CurvePath.prototype.getTransformedSpacedPoints=function(a,b){var c=this.getSpacedPoints(a),d,e;b||(b=this.bends);d=0;for(e=b.length;d<e;d++)c=this.getWrapPoints(c,b[d]);return c};
 THREE.CurvePath.prototype.getWrapPoints=function(a,b){var c=this.getBoundingBox(),d,e,f,g,h,i;d=0;for(e=a.length;d<e;d++)f=a[d],g=f.x,h=f.y,i=g/c.maxX,i=b.getUtoTmapping(i,g),g=b.getPoint(i),h=b.getNormalVector(i).multiplyScalar(h),f.x=g.x+h.x,f.y=g.y+h.y;return a};THREE.Gyroscope=function(){THREE.Object3D.call(this)};THREE.Gyroscope.prototype=Object.create(THREE.Object3D.prototype);
 THREE.CurvePath.prototype.getWrapPoints=function(a,b){var c=this.getBoundingBox(),d,e,f,g,h,i;d=0;for(e=a.length;d<e;d++)f=a[d],g=f.x,h=f.y,i=g/c.maxX,i=b.getUtoTmapping(i,g),g=b.getPoint(i),h=b.getNormalVector(i).multiplyScalar(h),f.x=g.x+h.x,f.y=g.y+h.y;return a};THREE.Gyroscope=function(){THREE.Object3D.call(this)};THREE.Gyroscope.prototype=Object.create(THREE.Object3D.prototype);
@@ -551,39 +551,39 @@ THREE.Path.prototype.bezierCurveTo=function(a,b,c,d,e,f){var g=Array.prototype.s
 THREE.Path.prototype.splineThru=function(a){var b=Array.prototype.slice.call(arguments),c=this.actions[this.actions.length-1].args,c=[new THREE.Vector2(c[c.length-2],c[c.length-1])];Array.prototype.push.apply(c,a);c=new THREE.SplineCurve(c);this.curves.push(c);this.actions.push({action:THREE.PathActions.CSPLINE_THRU,args:b})};THREE.Path.prototype.arc=function(a,b,c,d,e,f){var g=this.actions[this.actions.length-1].args;this.absarc(a+g[g.length-2],b+g[g.length-1],c,d,e,f)};
 THREE.Path.prototype.splineThru=function(a){var b=Array.prototype.slice.call(arguments),c=this.actions[this.actions.length-1].args,c=[new THREE.Vector2(c[c.length-2],c[c.length-1])];Array.prototype.push.apply(c,a);c=new THREE.SplineCurve(c);this.curves.push(c);this.actions.push({action:THREE.PathActions.CSPLINE_THRU,args:b})};THREE.Path.prototype.arc=function(a,b,c,d,e,f){var g=this.actions[this.actions.length-1].args;this.absarc(a+g[g.length-2],b+g[g.length-1],c,d,e,f)};
 THREE.Path.prototype.absarc=function(a,b,c,d,e,f){this.absellipse(a,b,c,c,d,e,f)};THREE.Path.prototype.ellipse=function(a,b,c,d,e,f,g){var h=this.actions[this.actions.length-1].args;this.absellipse(a+h[h.length-2],b+h[h.length-1],c,d,e,f,g)};THREE.Path.prototype.absellipse=function(a,b,c,d,e,f,g){var h=Array.prototype.slice.call(arguments),i=new THREE.EllipseCurve(a,b,c,d,e,f,g);this.curves.push(i);i=i.getPoint(g?1:0);h.push(i.x);h.push(i.y);this.actions.push({action:THREE.PathActions.ELLIPSE,args:h})};
 THREE.Path.prototype.absarc=function(a,b,c,d,e,f){this.absellipse(a,b,c,c,d,e,f)};THREE.Path.prototype.ellipse=function(a,b,c,d,e,f,g){var h=this.actions[this.actions.length-1].args;this.absellipse(a+h[h.length-2],b+h[h.length-1],c,d,e,f,g)};THREE.Path.prototype.absellipse=function(a,b,c,d,e,f,g){var h=Array.prototype.slice.call(arguments),i=new THREE.EllipseCurve(a,b,c,d,e,f,g);this.curves.push(i);i=i.getPoint(g?1:0);h.push(i.x);h.push(i.y);this.actions.push({action:THREE.PathActions.ELLIPSE,args:h})};
 THREE.Path.prototype.getSpacedPoints=function(a){a||(a=40);for(var b=[],c=0;c<a;c++)b.push(this.getPoint(c/a));return b};
 THREE.Path.prototype.getSpacedPoints=function(a){a||(a=40);for(var b=[],c=0;c<a;c++)b.push(this.getPoint(c/a));return b};
-THREE.Path.prototype.getPoints=function(a,b){if(this.useSpacedPoints)return console.log("tata"),this.getSpacedPoints(a,b);var a=a||12,c=[],d,e,f,g,h,i,k,l,n,m,t,r,p;d=0;for(e=this.actions.length;d<e;d++)switch(f=this.actions[d],g=f.action,f=f.args,g){case THREE.PathActions.MOVE_TO:c.push(new THREE.Vector2(f[0],f[1]));break;case THREE.PathActions.LINE_TO:c.push(new THREE.Vector2(f[0],f[1]));break;case THREE.PathActions.QUADRATIC_CURVE_TO:h=f[2];i=f[3];n=f[0];m=f[1];0<c.length?(g=c[c.length-1],t=g.x,
-r=g.y):(g=this.actions[d-1].args,t=g[g.length-2],r=g[g.length-1]);for(f=1;f<=a;f++)p=f/a,g=THREE.Shape.Utils.b2(p,t,n,h),p=THREE.Shape.Utils.b2(p,r,m,i),c.push(new THREE.Vector2(g,p));break;case THREE.PathActions.BEZIER_CURVE_TO:h=f[4];i=f[5];n=f[0];m=f[1];k=f[2];l=f[3];0<c.length?(g=c[c.length-1],t=g.x,r=g.y):(g=this.actions[d-1].args,t=g[g.length-2],r=g[g.length-1]);for(f=1;f<=a;f++)p=f/a,g=THREE.Shape.Utils.b3(p,t,n,k,h),p=THREE.Shape.Utils.b3(p,r,m,l,i),c.push(new THREE.Vector2(g,p));break;case THREE.PathActions.CSPLINE_THRU:g=
-this.actions[d-1].args;p=[new THREE.Vector2(g[g.length-2],g[g.length-1])];g=a*f[0].length;p=p.concat(f[0]);p=new THREE.SplineCurve(p);for(f=1;f<=g;f++)c.push(p.getPointAt(f/g));break;case THREE.PathActions.ARC:h=f[0];i=f[1];m=f[2];k=f[3];g=f[4];n=!!f[5];t=g-k;r=2*a;for(f=1;f<=r;f++)p=f/r,n||(p=1-p),p=k+p*t,g=h+m*Math.cos(p),p=i+m*Math.sin(p),c.push(new THREE.Vector2(g,p));break;case THREE.PathActions.ELLIPSE:h=f[0];i=f[1];m=f[2];l=f[3];k=f[4];g=f[5];n=!!f[6];t=g-k;r=2*a;for(f=1;f<=r;f++)p=f/r,n||
-(p=1-p),p=k+p*t,g=h+m*Math.cos(p),p=i+l*Math.sin(p),c.push(new THREE.Vector2(g,p))}d=c[c.length-1];1E-10>Math.abs(d.x-c[0].x)&&1E-10>Math.abs(d.y-c[0].y)&&c.splice(c.length-1,1);b&&c.push(c[0]);return c};
+THREE.Path.prototype.getPoints=function(a,b){if(this.useSpacedPoints)return console.log("tata"),this.getSpacedPoints(a,b);var a=a||12,c=[],d,e,f,g,h,i,j,l,n,m,r,u,p;d=0;for(e=this.actions.length;d<e;d++)switch(f=this.actions[d],g=f.action,f=f.args,g){case THREE.PathActions.MOVE_TO:c.push(new THREE.Vector2(f[0],f[1]));break;case THREE.PathActions.LINE_TO:c.push(new THREE.Vector2(f[0],f[1]));break;case THREE.PathActions.QUADRATIC_CURVE_TO:h=f[2];i=f[3];n=f[0];m=f[1];0<c.length?(g=c[c.length-1],r=g.x,
+u=g.y):(g=this.actions[d-1].args,r=g[g.length-2],u=g[g.length-1]);for(f=1;f<=a;f++)p=f/a,g=THREE.Shape.Utils.b2(p,r,n,h),p=THREE.Shape.Utils.b2(p,u,m,i),c.push(new THREE.Vector2(g,p));break;case THREE.PathActions.BEZIER_CURVE_TO:h=f[4];i=f[5];n=f[0];m=f[1];j=f[2];l=f[3];0<c.length?(g=c[c.length-1],r=g.x,u=g.y):(g=this.actions[d-1].args,r=g[g.length-2],u=g[g.length-1]);for(f=1;f<=a;f++)p=f/a,g=THREE.Shape.Utils.b3(p,r,n,j,h),p=THREE.Shape.Utils.b3(p,u,m,l,i),c.push(new THREE.Vector2(g,p));break;case THREE.PathActions.CSPLINE_THRU:g=
+this.actions[d-1].args;p=[new THREE.Vector2(g[g.length-2],g[g.length-1])];g=a*f[0].length;p=p.concat(f[0]);p=new THREE.SplineCurve(p);for(f=1;f<=g;f++)c.push(p.getPointAt(f/g));break;case THREE.PathActions.ARC:h=f[0];i=f[1];m=f[2];j=f[3];g=f[4];n=!!f[5];r=g-j;u=2*a;for(f=1;f<=u;f++)p=f/u,n||(p=1-p),p=j+p*r,g=h+m*Math.cos(p),p=i+m*Math.sin(p),c.push(new THREE.Vector2(g,p));break;case THREE.PathActions.ELLIPSE:h=f[0];i=f[1];m=f[2];l=f[3];j=f[4];g=f[5];n=!!f[6];r=g-j;u=2*a;for(f=1;f<=u;f++)p=f/u,n||
+(p=1-p),p=j+p*r,g=h+m*Math.cos(p),p=i+l*Math.sin(p),c.push(new THREE.Vector2(g,p))}d=c[c.length-1];1E-10>Math.abs(d.x-c[0].x)&&1E-10>Math.abs(d.y-c[0].y)&&c.splice(c.length-1,1);b&&c.push(c[0]);return c};
 THREE.Path.prototype.toShapes=function(){var a,b,c,d,e=[],f=new THREE.Path;a=0;for(b=this.actions.length;a<b;a++)c=this.actions[a],d=c.args,c=c.action,c==THREE.PathActions.MOVE_TO&&0!=f.actions.length&&(e.push(f),f=new THREE.Path),f[c].apply(f,d);0!=f.actions.length&&e.push(f);if(0==e.length)return[];var g;d=[];a=!THREE.Shape.Utils.isClockWise(e[0].getPoints());if(1==e.length)return f=e[0],g=new THREE.Shape,g.actions=f.actions,g.curves=f.curves,d.push(g),d;if(a){g=new THREE.Shape;a=0;for(b=e.length;a<
 THREE.Path.prototype.toShapes=function(){var a,b,c,d,e=[],f=new THREE.Path;a=0;for(b=this.actions.length;a<b;a++)c=this.actions[a],d=c.args,c=c.action,c==THREE.PathActions.MOVE_TO&&0!=f.actions.length&&(e.push(f),f=new THREE.Path),f[c].apply(f,d);0!=f.actions.length&&e.push(f);if(0==e.length)return[];var g;d=[];a=!THREE.Shape.Utils.isClockWise(e[0].getPoints());if(1==e.length)return f=e[0],g=new THREE.Shape,g.actions=f.actions,g.curves=f.curves,d.push(g),d;if(a){g=new THREE.Shape;a=0;for(b=e.length;a<
 b;a++)f=e[a],THREE.Shape.Utils.isClockWise(f.getPoints())?(g.actions=f.actions,g.curves=f.curves,d.push(g),g=new THREE.Shape):g.holes.push(f)}else{a=0;for(b=e.length;a<b;a++)f=e[a],THREE.Shape.Utils.isClockWise(f.getPoints())?(g&&d.push(g),g=new THREE.Shape,g.actions=f.actions,g.curves=f.curves):g.holes.push(f);d.push(g)}return d};THREE.Shape=function(){THREE.Path.apply(this,arguments);this.holes=[]};THREE.Shape.prototype=Object.create(THREE.Path.prototype);THREE.Shape.prototype.extrude=function(a){return new THREE.ExtrudeGeometry(this,a)};THREE.Shape.prototype.makeGeometry=function(a){return new THREE.ShapeGeometry(this,a)};THREE.Shape.prototype.getPointsHoles=function(a){var b,c=this.holes.length,d=[];for(b=0;b<c;b++)d[b]=this.holes[b].getTransformedPoints(a,this.bends);return d};
 b;a++)f=e[a],THREE.Shape.Utils.isClockWise(f.getPoints())?(g.actions=f.actions,g.curves=f.curves,d.push(g),g=new THREE.Shape):g.holes.push(f)}else{a=0;for(b=e.length;a<b;a++)f=e[a],THREE.Shape.Utils.isClockWise(f.getPoints())?(g&&d.push(g),g=new THREE.Shape,g.actions=f.actions,g.curves=f.curves):g.holes.push(f);d.push(g)}return d};THREE.Shape=function(){THREE.Path.apply(this,arguments);this.holes=[]};THREE.Shape.prototype=Object.create(THREE.Path.prototype);THREE.Shape.prototype.extrude=function(a){return new THREE.ExtrudeGeometry(this,a)};THREE.Shape.prototype.makeGeometry=function(a){return new THREE.ShapeGeometry(this,a)};THREE.Shape.prototype.getPointsHoles=function(a){var b,c=this.holes.length,d=[];for(b=0;b<c;b++)d[b]=this.holes[b].getTransformedPoints(a,this.bends);return d};
 THREE.Shape.prototype.getSpacedPointsHoles=function(a){var b,c=this.holes.length,d=[];for(b=0;b<c;b++)d[b]=this.holes[b].getTransformedSpacedPoints(a,this.bends);return d};THREE.Shape.prototype.extractAllPoints=function(a){return{shape:this.getTransformedPoints(a),holes:this.getPointsHoles(a)}};THREE.Shape.prototype.extractPoints=function(a){return this.useSpacedPoints?this.extractAllSpacedPoints(a):this.extractAllPoints(a)};
 THREE.Shape.prototype.getSpacedPointsHoles=function(a){var b,c=this.holes.length,d=[];for(b=0;b<c;b++)d[b]=this.holes[b].getTransformedSpacedPoints(a,this.bends);return d};THREE.Shape.prototype.extractAllPoints=function(a){return{shape:this.getTransformedPoints(a),holes:this.getPointsHoles(a)}};THREE.Shape.prototype.extractPoints=function(a){return this.useSpacedPoints?this.extractAllSpacedPoints(a):this.extractAllPoints(a)};
 THREE.Shape.prototype.extractAllSpacedPoints=function(a){return{shape:this.getTransformedSpacedPoints(a),holes:this.getSpacedPointsHoles(a)}};
 THREE.Shape.prototype.extractAllSpacedPoints=function(a){return{shape:this.getTransformedSpacedPoints(a),holes:this.getSpacedPointsHoles(a)}};
-THREE.Shape.Utils={removeHoles:function(a,b){var c=a.concat(),d=c.concat(),e,f,g,h,i,k,l,n,m,t,r=[];for(i=0;i<b.length;i++){k=b[i];Array.prototype.push.apply(d,k);f=Number.POSITIVE_INFINITY;for(e=0;e<k.length;e++){m=k[e];t=[];for(n=0;n<c.length;n++)l=c[n],l=m.distanceToSquared(l),t.push(l),l<f&&(f=l,g=e,h=n)}e=0<=h-1?h-1:c.length-1;f=0<=g-1?g-1:k.length-1;var p=[k[g],c[h],c[e]];n=THREE.FontUtils.Triangulate.area(p);var q=[k[g],k[f],c[h]];m=THREE.FontUtils.Triangulate.area(q);t=h;l=g;h+=1;g+=-1;0>
-h&&(h+=c.length);h%=c.length;0>g&&(g+=k.length);g%=k.length;e=0<=h-1?h-1:c.length-1;f=0<=g-1?g-1:k.length-1;p=[k[g],c[h],c[e]];p=THREE.FontUtils.Triangulate.area(p);q=[k[g],k[f],c[h]];q=THREE.FontUtils.Triangulate.area(q);n+m>p+q&&(h=t,g=l,0>h&&(h+=c.length),h%=c.length,0>g&&(g+=k.length),g%=k.length,e=0<=h-1?h-1:c.length-1,f=0<=g-1?g-1:k.length-1);n=c.slice(0,h);m=c.slice(h);t=k.slice(g);l=k.slice(0,g);f=[k[g],k[f],c[h]];r.push([k[g],c[h],c[e]]);r.push(f);c=n.concat(t).concat(l).concat(m)}return{shape:c,
-isolatedPts:r,allpoints:d}},triangulateShape:function(a,b){var c=THREE.Shape.Utils.removeHoles(a,b),d=c.allpoints,e=c.isolatedPts,c=THREE.FontUtils.Triangulate(c.shape,!1),f,g,h,i,k={};f=0;for(g=d.length;f<g;f++)i=d[f].x+":"+d[f].y,void 0!==k[i]&&console.log("Duplicate point",i),k[i]=f;f=0;for(g=c.length;f<g;f++){h=c[f];for(d=0;3>d;d++)i=h[d].x+":"+h[d].y,i=k[i],void 0!==i&&(h[d]=i)}f=0;for(g=e.length;f<g;f++){h=e[f];for(d=0;3>d;d++)i=h[d].x+":"+h[d].y,i=k[i],void 0!==i&&(h[d]=i)}return c.concat(e)},
+THREE.Shape.Utils={removeHoles:function(a,b){var c=a.concat(),d=c.concat(),e,f,g,h,i,j,l,n,m,r,u=[];for(i=0;i<b.length;i++){j=b[i];Array.prototype.push.apply(d,j);f=Number.POSITIVE_INFINITY;for(e=0;e<j.length;e++){m=j[e];r=[];for(n=0;n<c.length;n++)l=c[n],l=m.distanceToSquared(l),r.push(l),l<f&&(f=l,g=e,h=n)}e=0<=h-1?h-1:c.length-1;f=0<=g-1?g-1:j.length-1;var p=[j[g],c[h],c[e]];n=THREE.FontUtils.Triangulate.area(p);var q=[j[g],j[f],c[h]];m=THREE.FontUtils.Triangulate.area(q);r=h;l=g;h+=1;g+=-1;0>
+h&&(h+=c.length);h%=c.length;0>g&&(g+=j.length);g%=j.length;e=0<=h-1?h-1:c.length-1;f=0<=g-1?g-1:j.length-1;p=[j[g],c[h],c[e]];p=THREE.FontUtils.Triangulate.area(p);q=[j[g],j[f],c[h]];q=THREE.FontUtils.Triangulate.area(q);n+m>p+q&&(h=r,g=l,0>h&&(h+=c.length),h%=c.length,0>g&&(g+=j.length),g%=j.length,e=0<=h-1?h-1:c.length-1,f=0<=g-1?g-1:j.length-1);n=c.slice(0,h);m=c.slice(h);r=j.slice(g);l=j.slice(0,g);f=[j[g],j[f],c[h]];u.push([j[g],c[h],c[e]]);u.push(f);c=n.concat(r).concat(l).concat(m)}return{shape:c,
+isolatedPts:u,allpoints:d}},triangulateShape:function(a,b){var c=THREE.Shape.Utils.removeHoles(a,b),d=c.allpoints,e=c.isolatedPts,c=THREE.FontUtils.Triangulate(c.shape,!1),f,g,h,i,j={};f=0;for(g=d.length;f<g;f++)i=d[f].x+":"+d[f].y,void 0!==j[i]&&console.log("Duplicate point",i),j[i]=f;f=0;for(g=c.length;f<g;f++){h=c[f];for(d=0;3>d;d++)i=h[d].x+":"+h[d].y,i=j[i],void 0!==i&&(h[d]=i)}f=0;for(g=e.length;f<g;f++){h=e[f];for(d=0;3>d;d++)i=h[d].x+":"+h[d].y,i=j[i],void 0!==i&&(h[d]=i)}return c.concat(e)},
 isClockWise:function(a){return 0>THREE.FontUtils.Triangulate.area(a)},b2p0:function(a,b){var c=1-a;return c*c*b},b2p1:function(a,b){return 2*(1-a)*a*b},b2p2:function(a,b){return a*a*b},b2:function(a,b,c,d){return this.b2p0(a,b)+this.b2p1(a,c)+this.b2p2(a,d)},b3p0:function(a,b){var c=1-a;return c*c*c*b},b3p1:function(a,b){var c=1-a;return 3*c*c*a*b},b3p2:function(a,b){return 3*(1-a)*a*a*b},b3p3:function(a,b){return a*a*a*b},b3:function(a,b,c,d,e){return this.b3p0(a,b)+this.b3p1(a,c)+this.b3p2(a,d)+
 isClockWise:function(a){return 0>THREE.FontUtils.Triangulate.area(a)},b2p0:function(a,b){var c=1-a;return c*c*b},b2p1:function(a,b){return 2*(1-a)*a*b},b2p2:function(a,b){return a*a*b},b2:function(a,b,c,d){return this.b2p0(a,b)+this.b2p1(a,c)+this.b2p2(a,d)},b3p0:function(a,b){var c=1-a;return c*c*c*b},b3p1:function(a,b){var c=1-a;return 3*c*c*a*b},b3p2:function(a,b){return 3*(1-a)*a*a*b},b3p3:function(a,b){return a*a*a*b},b3:function(a,b,c,d,e){return this.b3p0(a,b)+this.b3p1(a,c)+this.b3p2(a,d)+
 this.b3p3(a,e)}};THREE.AnimationHandler=function(){var a=[],b={},c={update:function(b){for(var c=0;c<a.length;c++)a[c].update(b)},addToUpdate:function(b){-1===a.indexOf(b)&&a.push(b)},removeFromUpdate:function(b){b=a.indexOf(b);-1!==b&&a.splice(b,1)},add:function(a){void 0!==b[a.name]&&console.log("THREE.AnimationHandler.add: Warning! "+a.name+" already exists in library. Overwriting.");b[a.name]=a;if(!0!==a.initialized){for(var c=0;c<a.hierarchy.length;c++){for(var d=0;d<a.hierarchy[c].keys.length;d++)if(0>a.hierarchy[c].keys[d].time&&
 this.b3p3(a,e)}};THREE.AnimationHandler=function(){var a=[],b={},c={update:function(b){for(var c=0;c<a.length;c++)a[c].update(b)},addToUpdate:function(b){-1===a.indexOf(b)&&a.push(b)},removeFromUpdate:function(b){b=a.indexOf(b);-1!==b&&a.splice(b,1)},add:function(a){void 0!==b[a.name]&&console.log("THREE.AnimationHandler.add: Warning! "+a.name+" already exists in library. Overwriting.");b[a.name]=a;if(!0!==a.initialized){for(var c=0;c<a.hierarchy.length;c++){for(var d=0;d<a.hierarchy[c].keys.length;d++)if(0>a.hierarchy[c].keys[d].time&&
-(a.hierarchy[c].keys[d].time=0),void 0!==a.hierarchy[c].keys[d].rot&&!(a.hierarchy[c].keys[d].rot instanceof THREE.Quaternion)){var h=a.hierarchy[c].keys[d].rot;a.hierarchy[c].keys[d].rot=new THREE.Quaternion(h[0],h[1],h[2],h[3])}if(a.hierarchy[c].keys.length&&void 0!==a.hierarchy[c].keys[0].morphTargets){h={};for(d=0;d<a.hierarchy[c].keys.length;d++)for(var i=0;i<a.hierarchy[c].keys[d].morphTargets.length;i++){var k=a.hierarchy[c].keys[d].morphTargets[i];h[k]=-1}a.hierarchy[c].usedMorphTargets=h;
-for(d=0;d<a.hierarchy[c].keys.length;d++){var l={};for(k in h){for(i=0;i<a.hierarchy[c].keys[d].morphTargets.length;i++)if(a.hierarchy[c].keys[d].morphTargets[i]===k){l[k]=a.hierarchy[c].keys[d].morphTargetsInfluences[i];break}i===a.hierarchy[c].keys[d].morphTargets.length&&(l[k]=0)}a.hierarchy[c].keys[d].morphTargetsInfluences=l}}for(d=1;d<a.hierarchy[c].keys.length;d++)a.hierarchy[c].keys[d].time===a.hierarchy[c].keys[d-1].time&&(a.hierarchy[c].keys.splice(d,1),d--);for(d=0;d<a.hierarchy[c].keys.length;d++)a.hierarchy[c].keys[d].index=
+(a.hierarchy[c].keys[d].time=0),void 0!==a.hierarchy[c].keys[d].rot&&!(a.hierarchy[c].keys[d].rot instanceof THREE.Quaternion)){var h=a.hierarchy[c].keys[d].rot;a.hierarchy[c].keys[d].rot=new THREE.Quaternion(h[0],h[1],h[2],h[3])}if(a.hierarchy[c].keys.length&&void 0!==a.hierarchy[c].keys[0].morphTargets){h={};for(d=0;d<a.hierarchy[c].keys.length;d++)for(var i=0;i<a.hierarchy[c].keys[d].morphTargets.length;i++){var j=a.hierarchy[c].keys[d].morphTargets[i];h[j]=-1}a.hierarchy[c].usedMorphTargets=h;
+for(d=0;d<a.hierarchy[c].keys.length;d++){var l={};for(j in h){for(i=0;i<a.hierarchy[c].keys[d].morphTargets.length;i++)if(a.hierarchy[c].keys[d].morphTargets[i]===j){l[j]=a.hierarchy[c].keys[d].morphTargetsInfluences[i];break}i===a.hierarchy[c].keys[d].morphTargets.length&&(l[j]=0)}a.hierarchy[c].keys[d].morphTargetsInfluences=l}}for(d=1;d<a.hierarchy[c].keys.length;d++)a.hierarchy[c].keys[d].time===a.hierarchy[c].keys[d-1].time&&(a.hierarchy[c].keys.splice(d,1),d--);for(d=0;d<a.hierarchy[c].keys.length;d++)a.hierarchy[c].keys[d].index=
 d}d=parseInt(a.length*a.fps,10);a.JIT={};a.JIT.hierarchy=[];for(c=0;c<a.hierarchy.length;c++)a.JIT.hierarchy.push(Array(d));a.initialized=!0}},get:function(a){if("string"===typeof a){if(b[a])return b[a];console.log("THREE.AnimationHandler.get: Couldn't find animation "+a);return null}},parse:function(a){var b=[];if(a instanceof THREE.SkinnedMesh)for(var c=0;c<a.bones.length;c++)b.push(a.bones[c]);else d(a,b);return b}},d=function(a,b){b.push(a);for(var c=0;c<a.children.length;c++)d(a.children[c],
 d}d=parseInt(a.length*a.fps,10);a.JIT={};a.JIT.hierarchy=[];for(c=0;c<a.hierarchy.length;c++)a.JIT.hierarchy.push(Array(d));a.initialized=!0}},get:function(a){if("string"===typeof a){if(b[a])return b[a];console.log("THREE.AnimationHandler.get: Couldn't find animation "+a);return null}},parse:function(a){var b=[];if(a instanceof THREE.SkinnedMesh)for(var c=0;c<a.bones.length;c++)b.push(a.bones[c]);else d(a,b);return b}},d=function(a,b){b.push(a);for(var c=0;c<a.children.length;c++)d(a.children[c],
 b)};c.LINEAR=0;c.CATMULLROM=1;c.CATMULLROM_FORWARD=2;return c}();THREE.Animation=function(a,b,c){this.root=a;this.data=THREE.AnimationHandler.get(b);this.hierarchy=THREE.AnimationHandler.parse(a);this.currentTime=0;this.timeScale=1;this.isPlaying=!1;this.loop=this.isPaused=!0;this.interpolationType=void 0!==c?c:THREE.AnimationHandler.LINEAR;this.points=[];this.target=new THREE.Vector3};
 b)};c.LINEAR=0;c.CATMULLROM=1;c.CATMULLROM_FORWARD=2;return c}();THREE.Animation=function(a,b,c){this.root=a;this.data=THREE.AnimationHandler.get(b);this.hierarchy=THREE.AnimationHandler.parse(a);this.currentTime=0;this.timeScale=1;this.isPlaying=!1;this.loop=this.isPaused=!0;this.interpolationType=void 0!==c?c:THREE.AnimationHandler.LINEAR;this.points=[];this.target=new THREE.Vector3};
 THREE.Animation.prototype.play=function(a,b){if(!1===this.isPlaying){this.isPlaying=!0;this.loop=void 0!==a?a:!0;this.currentTime=void 0!==b?b:0;var c,d=this.hierarchy.length,e;for(c=0;c<d;c++){e=this.hierarchy[c];this.interpolationType!==THREE.AnimationHandler.CATMULLROM_FORWARD&&(e.useQuaternion=!0);e.matrixAutoUpdate=!0;void 0===e.animationCache&&(e.animationCache={},e.animationCache.prevKey={pos:0,rot:0,scl:0},e.animationCache.nextKey={pos:0,rot:0,scl:0},e.animationCache.originalMatrix=e instanceof
 THREE.Animation.prototype.play=function(a,b){if(!1===this.isPlaying){this.isPlaying=!0;this.loop=void 0!==a?a:!0;this.currentTime=void 0!==b?b:0;var c,d=this.hierarchy.length,e;for(c=0;c<d;c++){e=this.hierarchy[c];this.interpolationType!==THREE.AnimationHandler.CATMULLROM_FORWARD&&(e.useQuaternion=!0);e.matrixAutoUpdate=!0;void 0===e.animationCache&&(e.animationCache={},e.animationCache.prevKey={pos:0,rot:0,scl:0},e.animationCache.nextKey={pos:0,rot:0,scl:0},e.animationCache.originalMatrix=e instanceof
 THREE.Bone?e.skinMatrix:e.matrix);var f=e.animationCache.prevKey;e=e.animationCache.nextKey;f.pos=this.data.hierarchy[c].keys[0];f.rot=this.data.hierarchy[c].keys[0];f.scl=this.data.hierarchy[c].keys[0];e.pos=this.getNextKeyWith("pos",c,1);e.rot=this.getNextKeyWith("rot",c,1);e.scl=this.getNextKeyWith("scl",c,1)}this.update(0)}this.isPaused=!1;THREE.AnimationHandler.addToUpdate(this)};
 THREE.Bone?e.skinMatrix:e.matrix);var f=e.animationCache.prevKey;e=e.animationCache.nextKey;f.pos=this.data.hierarchy[c].keys[0];f.rot=this.data.hierarchy[c].keys[0];f.scl=this.data.hierarchy[c].keys[0];e.pos=this.getNextKeyWith("pos",c,1);e.rot=this.getNextKeyWith("rot",c,1);e.scl=this.getNextKeyWith("scl",c,1)}this.update(0)}this.isPaused=!1;THREE.AnimationHandler.addToUpdate(this)};
 THREE.Animation.prototype.pause=function(){!0===this.isPaused?THREE.AnimationHandler.addToUpdate(this):THREE.AnimationHandler.removeFromUpdate(this);this.isPaused=!this.isPaused};THREE.Animation.prototype.stop=function(){this.isPaused=this.isPlaying=!1;THREE.AnimationHandler.removeFromUpdate(this)};
 THREE.Animation.prototype.pause=function(){!0===this.isPaused?THREE.AnimationHandler.addToUpdate(this):THREE.AnimationHandler.removeFromUpdate(this);this.isPaused=!this.isPaused};THREE.Animation.prototype.stop=function(){this.isPaused=this.isPlaying=!1;THREE.AnimationHandler.removeFromUpdate(this)};
-THREE.Animation.prototype.update=function(a){if(!1!==this.isPlaying){var b=["pos","rot","scl"],c,d,e,f,g,h,i,k,l;l=this.currentTime+=a*this.timeScale;k=this.currentTime%=this.data.length;parseInt(Math.min(k*this.data.fps,this.data.length*this.data.fps),10);for(var n=0,m=this.hierarchy.length;n<m;n++){a=this.hierarchy[n];i=a.animationCache;for(var t=0;3>t;t++){c=b[t];g=i.prevKey[c];h=i.nextKey[c];if(h.time<=l){if(k<l)if(this.loop){g=this.data.hierarchy[n].keys[0];for(h=this.getNextKeyWith(c,n,1);h.time<
-k;)g=h,h=this.getNextKeyWith(c,n,h.index+1)}else{this.stop();return}else{do g=h,h=this.getNextKeyWith(c,n,h.index+1);while(h.time<k)}i.prevKey[c]=g;i.nextKey[c]=h}a.matrixAutoUpdate=!0;a.matrixWorldNeedsUpdate=!0;d=(k-g.time)/(h.time-g.time);e=g[c];f=h[c];if(0>d||1<d)console.log("THREE.Animation.update: Warning! Scale out of bounds:"+d+" on bone "+n),d=0>d?0:1;if("pos"===c)if(c=a.position,this.interpolationType===THREE.AnimationHandler.LINEAR)c.x=e[0]+(f[0]-e[0])*d,c.y=e[1]+(f[1]-e[1])*d,c.z=e[2]+
+THREE.Animation.prototype.update=function(a){if(!1!==this.isPlaying){var b=["pos","rot","scl"],c,d,e,f,g,h,i,j,l;l=this.currentTime+=a*this.timeScale;j=this.currentTime%=this.data.length;parseInt(Math.min(j*this.data.fps,this.data.length*this.data.fps),10);for(var n=0,m=this.hierarchy.length;n<m;n++){a=this.hierarchy[n];i=a.animationCache;for(var r=0;3>r;r++){c=b[r];g=i.prevKey[c];h=i.nextKey[c];if(h.time<=l){if(j<l)if(this.loop){g=this.data.hierarchy[n].keys[0];for(h=this.getNextKeyWith(c,n,1);h.time<
+j;)g=h,h=this.getNextKeyWith(c,n,h.index+1)}else{this.stop();return}else{do g=h,h=this.getNextKeyWith(c,n,h.index+1);while(h.time<j)}i.prevKey[c]=g;i.nextKey[c]=h}a.matrixAutoUpdate=!0;a.matrixWorldNeedsUpdate=!0;d=(j-g.time)/(h.time-g.time);e=g[c];f=h[c];if(0>d||1<d)console.log("THREE.Animation.update: Warning! Scale out of bounds:"+d+" on bone "+n),d=0>d?0:1;if("pos"===c)if(c=a.position,this.interpolationType===THREE.AnimationHandler.LINEAR)c.x=e[0]+(f[0]-e[0])*d,c.y=e[1]+(f[1]-e[1])*d,c.z=e[2]+
 (f[2]-e[2])*d;else{if(this.interpolationType===THREE.AnimationHandler.CATMULLROM||this.interpolationType===THREE.AnimationHandler.CATMULLROM_FORWARD)this.points[0]=this.getPrevKeyWith("pos",n,g.index-1).pos,this.points[1]=e,this.points[2]=f,this.points[3]=this.getNextKeyWith("pos",n,h.index+1).pos,d=0.33*d+0.33,e=this.interpolateCatmullRom(this.points,d),c.x=e[0],c.y=e[1],c.z=e[2],this.interpolationType===THREE.AnimationHandler.CATMULLROM_FORWARD&&(d=this.interpolateCatmullRom(this.points,1.01*d),
 (f[2]-e[2])*d;else{if(this.interpolationType===THREE.AnimationHandler.CATMULLROM||this.interpolationType===THREE.AnimationHandler.CATMULLROM_FORWARD)this.points[0]=this.getPrevKeyWith("pos",n,g.index-1).pos,this.points[1]=e,this.points[2]=f,this.points[3]=this.getNextKeyWith("pos",n,h.index+1).pos,d=0.33*d+0.33,e=this.interpolateCatmullRom(this.points,d),c.x=e[0],c.y=e[1],c.z=e[2],this.interpolationType===THREE.AnimationHandler.CATMULLROM_FORWARD&&(d=this.interpolateCatmullRom(this.points,1.01*d),
 this.target.set(d[0],d[1],d[2]),this.target.sub(c),this.target.y=0,this.target.normalize(),d=Math.atan2(this.target.x,this.target.z),a.rotation.set(0,d,0))}else"rot"===c?THREE.Quaternion.slerp(e,f,a.quaternion,d):"scl"===c&&(c=a.scale,c.x=e[0]+(f[0]-e[0])*d,c.y=e[1]+(f[1]-e[1])*d,c.z=e[2]+(f[2]-e[2])*d)}}}};
 this.target.set(d[0],d[1],d[2]),this.target.sub(c),this.target.y=0,this.target.normalize(),d=Math.atan2(this.target.x,this.target.z),a.rotation.set(0,d,0))}else"rot"===c?THREE.Quaternion.slerp(e,f,a.quaternion,d):"scl"===c&&(c=a.scale,c.x=e[0]+(f[0]-e[0])*d,c.y=e[1]+(f[1]-e[1])*d,c.z=e[2]+(f[2]-e[2])*d)}}}};
-THREE.Animation.prototype.interpolateCatmullRom=function(a,b){var c=[],d=[],e,f,g,h,i,k;e=(a.length-1)*b;f=Math.floor(e);e-=f;c[0]=0===f?f:f-1;c[1]=f;c[2]=f>a.length-2?f:f+1;c[3]=f>a.length-3?f:f+2;f=a[c[0]];h=a[c[1]];i=a[c[2]];k=a[c[3]];c=e*e;g=e*c;d[0]=this.interpolate(f[0],h[0],i[0],k[0],e,c,g);d[1]=this.interpolate(f[1],h[1],i[1],k[1],e,c,g);d[2]=this.interpolate(f[2],h[2],i[2],k[2],e,c,g);return d};
+THREE.Animation.prototype.interpolateCatmullRom=function(a,b){var c=[],d=[],e,f,g,h,i,j;e=(a.length-1)*b;f=Math.floor(e);e-=f;c[0]=0===f?f:f-1;c[1]=f;c[2]=f>a.length-2?f:f+1;c[3]=f>a.length-3?f:f+2;f=a[c[0]];h=a[c[1]];i=a[c[2]];j=a[c[3]];c=e*e;g=e*c;d[0]=this.interpolate(f[0],h[0],i[0],j[0],e,c,g);d[1]=this.interpolate(f[1],h[1],i[1],j[1],e,c,g);d[2]=this.interpolate(f[2],h[2],i[2],j[2],e,c,g);return d};
 THREE.Animation.prototype.interpolate=function(a,b,c,d,e,f,g){a=0.5*(c-a);d=0.5*(d-b);return(2*(b-c)+a+d)*g+(-3*(b-c)-2*a-d)*f+a*e+b};THREE.Animation.prototype.getNextKeyWith=function(a,b,c){for(var d=this.data.hierarchy[b].keys,c=this.interpolationType===THREE.AnimationHandler.CATMULLROM||this.interpolationType===THREE.AnimationHandler.CATMULLROM_FORWARD?c<d.length-1?c:d.length-1:c%d.length;c<d.length;c++)if(void 0!==d[c][a])return d[c];return this.data.hierarchy[b].keys[0]};
 THREE.Animation.prototype.interpolate=function(a,b,c,d,e,f,g){a=0.5*(c-a);d=0.5*(d-b);return(2*(b-c)+a+d)*g+(-3*(b-c)-2*a-d)*f+a*e+b};THREE.Animation.prototype.getNextKeyWith=function(a,b,c){for(var d=this.data.hierarchy[b].keys,c=this.interpolationType===THREE.AnimationHandler.CATMULLROM||this.interpolationType===THREE.AnimationHandler.CATMULLROM_FORWARD?c<d.length-1?c:d.length-1:c%d.length;c<d.length;c++)if(void 0!==d[c][a])return d[c];return this.data.hierarchy[b].keys[0]};
 THREE.Animation.prototype.getPrevKeyWith=function(a,b,c){for(var d=this.data.hierarchy[b].keys,c=this.interpolationType===THREE.AnimationHandler.CATMULLROM||this.interpolationType===THREE.AnimationHandler.CATMULLROM_FORWARD?0<c?c:0:0<=c?c:c+d.length;0<=c;c--)if(void 0!==d[c][a])return d[c];return this.data.hierarchy[b].keys[d.length-1]};THREE.KeyFrameAnimation=function(a,b,c){this.root=a;this.data=THREE.AnimationHandler.get(b);this.hierarchy=THREE.AnimationHandler.parse(a);this.currentTime=0;this.timeScale=0.001;this.isPlaying=!1;this.loop=this.isPaused=!0;this.JITCompile=void 0!==c?c:!0;a=0;for(b=this.hierarchy.length;a<b;a++){var c=this.data.hierarchy[a].sids,d=this.hierarchy[a];if(this.data.hierarchy[a].keys.length&&c){for(var e=0;e<c.length;e++){var f=c[e],g=this.getNextKeyWith(f,a,0);g&&g.apply(f)}d.matrixAutoUpdate=!1;this.data.hierarchy[a].node.updateMatrix();
 THREE.Animation.prototype.getPrevKeyWith=function(a,b,c){for(var d=this.data.hierarchy[b].keys,c=this.interpolationType===THREE.AnimationHandler.CATMULLROM||this.interpolationType===THREE.AnimationHandler.CATMULLROM_FORWARD?0<c?c:0:0<=c?c:c+d.length;0<=c;c--)if(void 0!==d[c][a])return d[c];return this.data.hierarchy[b].keys[d.length-1]};THREE.KeyFrameAnimation=function(a,b,c){this.root=a;this.data=THREE.AnimationHandler.get(b);this.hierarchy=THREE.AnimationHandler.parse(a);this.currentTime=0;this.timeScale=0.001;this.isPlaying=!1;this.loop=this.isPaused=!0;this.JITCompile=void 0!==c?c:!0;a=0;for(b=this.hierarchy.length;a<b;a++){var c=this.data.hierarchy[a].sids,d=this.hierarchy[a];if(this.data.hierarchy[a].keys.length&&c){for(var e=0;e<c.length;e++){var f=c[e],g=this.getNextKeyWith(f,a,0);g&&g.apply(f)}d.matrixAutoUpdate=!1;this.data.hierarchy[a].node.updateMatrix();
 d.matrixWorldNeedsUpdate=!0}}};
 d.matrixWorldNeedsUpdate=!0}}};
 THREE.KeyFrameAnimation.prototype.play=function(a,b){if(!this.isPlaying){this.isPlaying=!0;this.loop=void 0!==a?a:!0;this.currentTime=void 0!==b?b:0;this.startTimeMs=b;this.startTime=1E7;this.endTime=-this.startTime;var c,d=this.hierarchy.length,e,f;for(c=0;c<d;c++)e=this.hierarchy[c],f=this.data.hierarchy[c],e.useQuaternion=!0,void 0===f.animationCache&&(f.animationCache={},f.animationCache.prevKey=null,f.animationCache.nextKey=null,f.animationCache.originalMatrix=e instanceof THREE.Bone?e.skinMatrix:
 THREE.KeyFrameAnimation.prototype.play=function(a,b){if(!this.isPlaying){this.isPlaying=!0;this.loop=void 0!==a?a:!0;this.currentTime=void 0!==b?b:0;this.startTimeMs=b;this.startTime=1E7;this.endTime=-this.startTime;var c,d=this.hierarchy.length,e,f;for(c=0;c<d;c++)e=this.hierarchy[c],f=this.data.hierarchy[c],e.useQuaternion=!0,void 0===f.animationCache&&(f.animationCache={},f.animationCache.prevKey=null,f.animationCache.nextKey=null,f.animationCache.originalMatrix=e instanceof THREE.Bone?e.skinMatrix:
 e.matrix),e=this.data.hierarchy[c].keys,e.length&&(f.animationCache.prevKey=e[0],f.animationCache.nextKey=e[1],this.startTime=Math.min(e[0].time,this.startTime),this.endTime=Math.max(e[e.length-1].time,this.endTime));this.update(0)}this.isPaused=!1;THREE.AnimationHandler.addToUpdate(this)};THREE.KeyFrameAnimation.prototype.pause=function(){this.isPaused?THREE.AnimationHandler.addToUpdate(this):THREE.AnimationHandler.removeFromUpdate(this);this.isPaused=!this.isPaused};
 e.matrix),e=this.data.hierarchy[c].keys,e.length&&(f.animationCache.prevKey=e[0],f.animationCache.nextKey=e[1],this.startTime=Math.min(e[0].time,this.startTime),this.endTime=Math.max(e[e.length-1].time,this.endTime));this.update(0)}this.isPaused=!1;THREE.AnimationHandler.addToUpdate(this)};THREE.KeyFrameAnimation.prototype.pause=function(){this.isPaused?THREE.AnimationHandler.addToUpdate(this):THREE.AnimationHandler.removeFromUpdate(this);this.isPaused=!this.isPaused};
 THREE.KeyFrameAnimation.prototype.stop=function(){this.isPaused=this.isPlaying=!1;THREE.AnimationHandler.removeFromUpdate(this);for(var a=0;a<this.data.hierarchy.length;a++){var b=this.hierarchy[a],c=this.data.hierarchy[a];if(void 0!==c.animationCache){var d=c.animationCache.originalMatrix;b instanceof THREE.Bone?(d.copy(b.skinMatrix),b.skinMatrix=d):(d.copy(b.matrix),b.matrix=d);delete c.animationCache}}};
 THREE.KeyFrameAnimation.prototype.stop=function(){this.isPaused=this.isPlaying=!1;THREE.AnimationHandler.removeFromUpdate(this);for(var a=0;a<this.data.hierarchy.length;a++){var b=this.hierarchy[a],c=this.data.hierarchy[a];if(void 0!==c.animationCache){var d=c.animationCache.originalMatrix;b instanceof THREE.Bone?(d.copy(b.skinMatrix),b.skinMatrix=d):(d.copy(b.matrix),b.matrix=d);delete c.animationCache}}};
-THREE.KeyFrameAnimation.prototype.update=function(a){if(this.isPlaying){var b,c,d,e,f=this.data.JIT.hierarchy,g,h,i;h=this.currentTime+=a*this.timeScale;g=this.currentTime%=this.data.length;g<this.startTimeMs&&(g=this.currentTime=this.startTimeMs+g);e=parseInt(Math.min(g*this.data.fps,this.data.length*this.data.fps),10);if((i=g<h)&&!this.loop){for(var a=0,k=this.hierarchy.length;a<k;a++){var l=this.data.hierarchy[a].keys,f=this.data.hierarchy[a].sids;d=l.length-1;e=this.hierarchy[a];if(l.length){for(l=
-0;l<f.length;l++)g=f[l],(h=this.getPrevKeyWith(g,a,d))&&h.apply(g);this.data.hierarchy[a].node.updateMatrix();e.matrixWorldNeedsUpdate=!0}}this.stop()}else if(!(g<this.startTime)){a=0;for(k=this.hierarchy.length;a<k;a++){d=this.hierarchy[a];b=this.data.hierarchy[a];var l=b.keys,n=b.animationCache;if(this.JITCompile&&void 0!==f[a][e])d instanceof THREE.Bone?(d.skinMatrix=f[a][e],d.matrixWorldNeedsUpdate=!1):(d.matrix=f[a][e],d.matrixWorldNeedsUpdate=!0);else if(l.length){this.JITCompile&&n&&(d instanceof
+THREE.KeyFrameAnimation.prototype.update=function(a){if(this.isPlaying){var b,c,d,e,f=this.data.JIT.hierarchy,g,h,i;h=this.currentTime+=a*this.timeScale;g=this.currentTime%=this.data.length;g<this.startTimeMs&&(g=this.currentTime=this.startTimeMs+g);e=parseInt(Math.min(g*this.data.fps,this.data.length*this.data.fps),10);if((i=g<h)&&!this.loop){for(var a=0,j=this.hierarchy.length;a<j;a++){var l=this.data.hierarchy[a].keys,f=this.data.hierarchy[a].sids;d=l.length-1;e=this.hierarchy[a];if(l.length){for(l=
+0;l<f.length;l++)g=f[l],(h=this.getPrevKeyWith(g,a,d))&&h.apply(g);this.data.hierarchy[a].node.updateMatrix();e.matrixWorldNeedsUpdate=!0}}this.stop()}else if(!(g<this.startTime)){a=0;for(j=this.hierarchy.length;a<j;a++){d=this.hierarchy[a];b=this.data.hierarchy[a];var l=b.keys,n=b.animationCache;if(this.JITCompile&&void 0!==f[a][e])d instanceof THREE.Bone?(d.skinMatrix=f[a][e],d.matrixWorldNeedsUpdate=!1):(d.matrix=f[a][e],d.matrixWorldNeedsUpdate=!0);else if(l.length){this.JITCompile&&n&&(d instanceof
 THREE.Bone?d.skinMatrix=n.originalMatrix:d.matrix=n.originalMatrix);b=n.prevKey;c=n.nextKey;if(b&&c){if(c.time<=h){if(i&&this.loop){b=l[0];for(c=l[1];c.time<g;)b=c,c=l[b.index+1]}else if(!i)for(var m=l.length-1;c.time<g&&c.index!==m;)b=c,c=l[b.index+1];n.prevKey=b;n.nextKey=c}c.time>=g?b.interpolate(c,g):b.interpolate(c,c.time)}this.data.hierarchy[a].node.updateMatrix();d.matrixWorldNeedsUpdate=!0}}if(this.JITCompile&&void 0===f[0][e]){this.hierarchy[0].updateMatrixWorld(!0);for(a=0;a<this.hierarchy.length;a++)f[a][e]=
 THREE.Bone?d.skinMatrix=n.originalMatrix:d.matrix=n.originalMatrix);b=n.prevKey;c=n.nextKey;if(b&&c){if(c.time<=h){if(i&&this.loop){b=l[0];for(c=l[1];c.time<g;)b=c,c=l[b.index+1]}else if(!i)for(var m=l.length-1;c.time<g&&c.index!==m;)b=c,c=l[b.index+1];n.prevKey=b;n.nextKey=c}c.time>=g?b.interpolate(c,g):b.interpolate(c,c.time)}this.data.hierarchy[a].node.updateMatrix();d.matrixWorldNeedsUpdate=!0}}if(this.JITCompile&&void 0===f[0][e]){this.hierarchy[0].updateMatrixWorld(!0);for(a=0;a<this.hierarchy.length;a++)f[a][e]=
 this.hierarchy[a]instanceof THREE.Bone?this.hierarchy[a].skinMatrix.clone():this.hierarchy[a].matrix.clone()}}}};THREE.KeyFrameAnimation.prototype.getNextKeyWith=function(a,b,c){b=this.data.hierarchy[b].keys;for(c%=b.length;c<b.length;c++)if(b[c].hasTarget(a))return b[c];return b[0]};THREE.KeyFrameAnimation.prototype.getPrevKeyWith=function(a,b,c){b=this.data.hierarchy[b].keys;for(c=0<=c?c:c+b.length;0<=c;c--)if(b[c].hasTarget(a))return b[c];return b[b.length-1]};THREE.CubeCamera=function(a,b,c){THREE.Object3D.call(this);var d=new THREE.PerspectiveCamera(90,1,a,b);d.up.set(0,-1,0);d.lookAt(new THREE.Vector3(1,0,0));this.add(d);var e=new THREE.PerspectiveCamera(90,1,a,b);e.up.set(0,-1,0);e.lookAt(new THREE.Vector3(-1,0,0));this.add(e);var f=new THREE.PerspectiveCamera(90,1,a,b);f.up.set(0,0,1);f.lookAt(new THREE.Vector3(0,1,0));this.add(f);var g=new THREE.PerspectiveCamera(90,1,a,b);g.up.set(0,0,-1);g.lookAt(new THREE.Vector3(0,-1,0));this.add(g);var h=new THREE.PerspectiveCamera(90,
 this.hierarchy[a]instanceof THREE.Bone?this.hierarchy[a].skinMatrix.clone():this.hierarchy[a].matrix.clone()}}}};THREE.KeyFrameAnimation.prototype.getNextKeyWith=function(a,b,c){b=this.data.hierarchy[b].keys;for(c%=b.length;c<b.length;c++)if(b[c].hasTarget(a))return b[c];return b[0]};THREE.KeyFrameAnimation.prototype.getPrevKeyWith=function(a,b,c){b=this.data.hierarchy[b].keys;for(c=0<=c?c:c+b.length;0<=c;c--)if(b[c].hasTarget(a))return b[c];return b[b.length-1]};THREE.CubeCamera=function(a,b,c){THREE.Object3D.call(this);var d=new THREE.PerspectiveCamera(90,1,a,b);d.up.set(0,-1,0);d.lookAt(new THREE.Vector3(1,0,0));this.add(d);var e=new THREE.PerspectiveCamera(90,1,a,b);e.up.set(0,-1,0);e.lookAt(new THREE.Vector3(-1,0,0));this.add(e);var f=new THREE.PerspectiveCamera(90,1,a,b);f.up.set(0,0,1);f.lookAt(new THREE.Vector3(0,1,0));this.add(f);var g=new THREE.PerspectiveCamera(90,1,a,b);g.up.set(0,0,-1);g.lookAt(new THREE.Vector3(0,-1,0));this.add(g);var h=new THREE.PerspectiveCamera(90,
 1,a,b);h.up.set(0,-1,0);h.lookAt(new THREE.Vector3(0,0,1));this.add(h);var i=new THREE.PerspectiveCamera(90,1,a,b);i.up.set(0,-1,0);i.lookAt(new THREE.Vector3(0,0,-1));this.add(i);this.renderTarget=new THREE.WebGLRenderTargetCube(c,c,{format:THREE.RGBFormat,magFilter:THREE.LinearFilter,minFilter:THREE.LinearFilter});this.updateCubeMap=function(a,b){var c=this.renderTarget,m=c.generateMipmaps;c.generateMipmaps=!1;c.activeCubeFace=0;a.render(b,d,c);c.activeCubeFace=1;a.render(b,e,c);c.activeCubeFace=
 1,a,b);h.up.set(0,-1,0);h.lookAt(new THREE.Vector3(0,0,1));this.add(h);var i=new THREE.PerspectiveCamera(90,1,a,b);i.up.set(0,-1,0);i.lookAt(new THREE.Vector3(0,0,-1));this.add(i);this.renderTarget=new THREE.WebGLRenderTargetCube(c,c,{format:THREE.RGBFormat,magFilter:THREE.LinearFilter,minFilter:THREE.LinearFilter});this.updateCubeMap=function(a,b){var c=this.renderTarget,m=c.generateMipmaps;c.generateMipmaps=!1;c.activeCubeFace=0;a.render(b,d,c);c.activeCubeFace=1;a.render(b,e,c);c.activeCubeFace=
@@ -595,44 +595,44 @@ THREE.CombinedCamera.prototype.setLens=function(a,b){void 0===b&&(b=24);var c=2*
 THREE.CombinedCamera.prototype.toBackView=function(){this.rotation.x=0;this.rotation.y=Math.PI;this.rotation.z=0;this.rotationAutoUpdate=!1};THREE.CombinedCamera.prototype.toLeftView=function(){this.rotation.x=0;this.rotation.y=-Math.PI/2;this.rotation.z=0;this.rotationAutoUpdate=!1};THREE.CombinedCamera.prototype.toRightView=function(){this.rotation.x=0;this.rotation.y=Math.PI/2;this.rotation.z=0;this.rotationAutoUpdate=!1};
 THREE.CombinedCamera.prototype.toBackView=function(){this.rotation.x=0;this.rotation.y=Math.PI;this.rotation.z=0;this.rotationAutoUpdate=!1};THREE.CombinedCamera.prototype.toLeftView=function(){this.rotation.x=0;this.rotation.y=-Math.PI/2;this.rotation.z=0;this.rotationAutoUpdate=!1};THREE.CombinedCamera.prototype.toRightView=function(){this.rotation.x=0;this.rotation.y=Math.PI/2;this.rotation.z=0;this.rotationAutoUpdate=!1};
 THREE.CombinedCamera.prototype.toTopView=function(){this.rotation.x=-Math.PI/2;this.rotation.y=0;this.rotation.z=0;this.rotationAutoUpdate=!1};THREE.CombinedCamera.prototype.toBottomView=function(){this.rotation.x=Math.PI/2;this.rotation.y=0;this.rotation.z=0;this.rotationAutoUpdate=!1};THREE.AsteriskGeometry=function(a,b){THREE.Geometry.call(this);for(var c=0.707*a,d=0.707*b,c=[[a,0,0],[b,0,0],[-a,0,0],[-b,0,0],[0,a,0],[0,b,0],[0,-a,0],[0,-b,0],[0,0,a],[0,0,b],[0,0,-a],[0,0,-b],[c,c,0],[d,d,0],[-c,-c,0],[-d,-d,0],[c,-c,0],[d,-d,0],[-c,c,0],[-d,d,0],[c,0,c],[d,0,d],[-c,0,-c],[-d,0,-d],[c,0,-c],[d,0,-d],[-c,0,c],[-d,0,d],[0,c,c],[0,d,d],[0,-c,-c],[0,-d,-d],[0,c,-c],[0,d,-d],[0,-c,c],[0,-d,d]],d=0,e=c.length;d<e;d++)this.vertices.push(new THREE.Vector3(c[d][0],c[d][1],c[d][2]))};
 THREE.CombinedCamera.prototype.toTopView=function(){this.rotation.x=-Math.PI/2;this.rotation.y=0;this.rotation.z=0;this.rotationAutoUpdate=!1};THREE.CombinedCamera.prototype.toBottomView=function(){this.rotation.x=Math.PI/2;this.rotation.y=0;this.rotation.z=0;this.rotationAutoUpdate=!1};THREE.AsteriskGeometry=function(a,b){THREE.Geometry.call(this);for(var c=0.707*a,d=0.707*b,c=[[a,0,0],[b,0,0],[-a,0,0],[-b,0,0],[0,a,0],[0,b,0],[0,-a,0],[0,-b,0],[0,0,a],[0,0,b],[0,0,-a],[0,0,-b],[c,c,0],[d,d,0],[-c,-c,0],[-d,-d,0],[c,-c,0],[d,-d,0],[-c,c,0],[-d,d,0],[c,0,c],[d,0,d],[-c,0,-c],[-d,0,-d],[c,0,-c],[d,0,-d],[-c,0,c],[-d,0,d],[0,c,c],[0,d,d],[0,-c,-c],[0,-d,-d],[0,c,-c],[0,d,-d],[0,-c,c],[0,-d,d]],d=0,e=c.length;d<e;d++)this.vertices.push(new THREE.Vector3(c[d][0],c[d][1],c[d][2]))};
 THREE.AsteriskGeometry.prototype=Object.create(THREE.Geometry.prototype);THREE.CircleGeometry=function(a,b,c,d){THREE.Geometry.call(this);var a=a||50,c=void 0!==c?c:0,d=void 0!==d?d:2*Math.PI,b=void 0!==b?Math.max(3,b):8,e,f=[];e=new THREE.Vector3;var g=new THREE.Vector2(0.5,0.5);this.vertices.push(e);f.push(g);for(e=0;e<=b;e++){var h=new THREE.Vector3;h.x=a*Math.cos(c+e/b*d);h.y=a*Math.sin(c+e/b*d);this.vertices.push(h);f.push(new THREE.Vector2((h.x/a+1)/2,-(h.y/a+1)/2+1))}c=new THREE.Vector3(0,0,-1);for(e=1;e<=b;e++)this.faces.push(new THREE.Face3(e,e+1,0,[c,c,c])),
 THREE.AsteriskGeometry.prototype=Object.create(THREE.Geometry.prototype);THREE.CircleGeometry=function(a,b,c,d){THREE.Geometry.call(this);var a=a||50,c=void 0!==c?c:0,d=void 0!==d?d:2*Math.PI,b=void 0!==b?Math.max(3,b):8,e,f=[];e=new THREE.Vector3;var g=new THREE.Vector2(0.5,0.5);this.vertices.push(e);f.push(g);for(e=0;e<=b;e++){var h=new THREE.Vector3;h.x=a*Math.cos(c+e/b*d);h.y=a*Math.sin(c+e/b*d);this.vertices.push(h);f.push(new THREE.Vector2((h.x/a+1)/2,-(h.y/a+1)/2+1))}c=new THREE.Vector3(0,0,-1);for(e=1;e<=b;e++)this.faces.push(new THREE.Face3(e,e+1,0,[c,c,c])),
-this.faceVertexUvs[0].push([f[e],f[e+1],g]);this.computeCentroids();this.computeFaceNormals();this.boundingSphere=new THREE.Sphere(new THREE.Vector3,a)};THREE.CircleGeometry.prototype=Object.create(THREE.Geometry.prototype);THREE.CubeGeometry=function(a,b,c,d,e,f){function g(a,b,c,d,e,f,g,p){var q,y=h.widthSegments,v=h.heightSegments,z=e/2,s=f/2,C=h.vertices.length;if("x"===a&&"y"===b||"y"===a&&"x"===b)q="z";else if("x"===a&&"z"===b||"z"===a&&"x"===b)q="y",v=h.depthSegments;else if("z"===a&&"y"===b||"y"===a&&"z"===b)q="x",y=h.depthSegments;var H=y+1,B=v+1,w=e/y,I=f/v,J=new THREE.Vector3;J[q]=0<g?1:-1;for(e=0;e<B;e++)for(f=0;f<H;f++){var E=new THREE.Vector3;E[a]=(f*w-z)*c;E[b]=(e*I-s)*d;E[q]=g;h.vertices.push(E)}for(e=
-0;e<v;e++)for(f=0;f<y;f++)a=new THREE.Face4(f+H*e+C,f+H*(e+1)+C,f+1+H*(e+1)+C,f+1+H*e+C),a.normal.copy(J),a.vertexNormals.push(J.clone(),J.clone(),J.clone(),J.clone()),a.materialIndex=p,h.faces.push(a),h.faceVertexUvs[0].push([new THREE.Vector2(f/y,1-e/v),new THREE.Vector2(f/y,1-(e+1)/v),new THREE.Vector2((f+1)/y,1-(e+1)/v),new THREE.Vector2((f+1)/y,1-e/v)])}THREE.Geometry.call(this);var h=this;this.width=a;this.height=b;this.depth=c;this.widthSegments=d||1;this.heightSegments=e||1;this.depthSegments=
-f||1;a=this.width/2;b=this.height/2;c=this.depth/2;g("z","y",-1,-1,this.depth,this.height,a,0);g("z","y",1,-1,this.depth,this.height,-a,1);g("x","z",1,1,this.width,this.depth,b,2);g("x","z",1,-1,this.width,this.depth,-b,3);g("x","y",1,-1,this.width,this.height,c,4);g("x","y",-1,-1,this.width,this.height,-c,5);this.computeCentroids();this.mergeVertices()};THREE.CubeGeometry.prototype=Object.create(THREE.Geometry.prototype);THREE.CylinderGeometry=function(a,b,c,d,e,f){THREE.Geometry.call(this);var a=void 0!==a?a:20,b=void 0!==b?b:20,c=void 0!==c?c:100,g=c/2,d=d||8,e=e||1,h,i,k=[],l=[];for(i=0;i<=e;i++){var n=[],m=[],t=i/e,r=t*(b-a)+a;for(h=0;h<=d;h++){var p=h/d,q=new THREE.Vector3;q.x=r*Math.sin(2*p*Math.PI);q.y=-t*c+g;q.z=r*Math.cos(2*p*Math.PI);this.vertices.push(q);n.push(this.vertices.length-1);m.push(new THREE.Vector2(p,1-t))}k.push(n);l.push(m)}c=(b-a)/c;for(h=0;h<d;h++){0!==a?(n=this.vertices[k[0][h]].clone(),
-m=this.vertices[k[0][h+1]].clone()):(n=this.vertices[k[1][h]].clone(),m=this.vertices[k[1][h+1]].clone());n.setY(Math.sqrt(n.x*n.x+n.z*n.z)*c).normalize();m.setY(Math.sqrt(m.x*m.x+m.z*m.z)*c).normalize();for(i=0;i<e;i++){var t=k[i][h],r=k[i+1][h],p=k[i+1][h+1],q=k[i][h+1],y=n.clone(),v=n.clone(),z=m.clone(),s=m.clone(),C=l[i][h].clone(),H=l[i+1][h].clone(),B=l[i+1][h+1].clone(),w=l[i][h+1].clone();this.faces.push(new THREE.Face4(t,r,p,q,[y,v,z,s]));this.faceVertexUvs[0].push([C,H,B,w])}}if(!f&&0<
-a){this.vertices.push(new THREE.Vector3(0,g,0));for(h=0;h<d;h++)t=k[0][h],r=k[0][h+1],p=this.vertices.length-1,y=new THREE.Vector3(0,1,0),v=new THREE.Vector3(0,1,0),z=new THREE.Vector3(0,1,0),C=l[0][h].clone(),H=l[0][h+1].clone(),B=new THREE.Vector2(H.u,0),this.faces.push(new THREE.Face3(t,r,p,[y,v,z])),this.faceVertexUvs[0].push([C,H,B])}if(!f&&0<b){this.vertices.push(new THREE.Vector3(0,-g,0));for(h=0;h<d;h++)t=k[i][h+1],r=k[i][h],p=this.vertices.length-1,y=new THREE.Vector3(0,-1,0),v=new THREE.Vector3(0,
--1,0),z=new THREE.Vector3(0,-1,0),C=l[i][h+1].clone(),H=l[i][h].clone(),B=new THREE.Vector2(H.u,1),this.faces.push(new THREE.Face3(t,r,p,[y,v,z])),this.faceVertexUvs[0].push([C,H,B])}this.computeCentroids();this.computeFaceNormals()};THREE.CylinderGeometry.prototype=Object.create(THREE.Geometry.prototype);THREE.ExtrudeGeometry=function(a,b){"undefined"!==typeof a&&(THREE.Geometry.call(this),a=a instanceof Array?a:[a],this.shapebb=a[a.length-1].getBoundingBox(),this.addShapeList(a,b),this.computeCentroids(),this.computeFaceNormals())};THREE.ExtrudeGeometry.prototype=Object.create(THREE.Geometry.prototype);THREE.ExtrudeGeometry.prototype.addShapeList=function(a,b){for(var c=a.length,d=0;d<c;d++)this.addShape(a[d],b)};
-THREE.ExtrudeGeometry.prototype.addShape=function(a,b){function c(a,b,c){b||console.log("die");return b.clone().multiplyScalar(c).add(a)}function d(a,b,c){var d=THREE.ExtrudeGeometry.__v1,e=THREE.ExtrudeGeometry.__v2,f=THREE.ExtrudeGeometry.__v3,g=THREE.ExtrudeGeometry.__v4,i=THREE.ExtrudeGeometry.__v5,h=THREE.ExtrudeGeometry.__v6;d.set(a.x-b.x,a.y-b.y);e.set(a.x-c.x,a.y-c.y);d=d.normalize();e=e.normalize();f.set(-d.y,d.x);g.set(e.y,-e.x);i.copy(a).add(f);h.copy(a).add(g);if(i.equals(h))return g.clone();
-i.copy(b).add(f);h.copy(c).add(g);f=d.dot(g);g=h.sub(i).dot(g);0===f&&(console.log("Either infinite or no solutions!"),0===g?console.log("Its finite solutions."):console.log("Too bad, no solutions."));g/=f;return 0>g?(b=Math.atan2(b.y-a.y,b.x-a.x),a=Math.atan2(c.y-a.y,c.x-a.x),b>a&&(a+=2*Math.PI),c=(b+a)/2,a=-Math.cos(c),c=-Math.sin(c),new THREE.Vector2(a,c)):d.multiplyScalar(g).add(i).sub(a).clone()}function e(c,d){var e,f;for(M=c.length;0<=--M;){e=M;f=M-1;0>f&&(f=c.length-1);for(var g=0,i=t+2*l,
-g=0;g<i;g++){var h=fa*g,k=fa*(g+1),m=d+e+h,h=d+f+h,n=d+f+k,k=d+e+k,p=c,q=g,r=i,s=e,w=f,m=m+Z,h=h+Z,n=n+Z,k=k+Z;E.faces.push(new THREE.Face4(m,h,n,k,null,null,v));m=z.generateSideWallUV(E,a,p,b,m,h,n,k,q,r,s,w);E.faceVertexUvs[0].push(m)}}}function f(a,b,c){E.vertices.push(new THREE.Vector3(a,b,c))}function g(c,d,e,f){c+=Z;d+=Z;e+=Z;E.faces.push(new THREE.Face3(c,d,e,null,null,y));c=f?z.generateBottomUV(E,a,b,c,d,e):z.generateTopUV(E,a,b,c,d,e);E.faceVertexUvs[0].push(c)}var h=void 0!==b.amount?b.amount:
-100,i=void 0!==b.bevelThickness?b.bevelThickness:6,k=void 0!==b.bevelSize?b.bevelSize:i-2,l=void 0!==b.bevelSegments?b.bevelSegments:3,n=void 0!==b.bevelEnabled?b.bevelEnabled:!0,m=void 0!==b.curveSegments?b.curveSegments:12,t=void 0!==b.steps?b.steps:1,r=b.extrudePath,p,q=!1,y=b.material,v=b.extrudeMaterial,z=void 0!==b.UVGenerator?b.UVGenerator:THREE.ExtrudeGeometry.WorldUVGenerator,s,C,H,B;r&&(p=r.getSpacedPoints(t),q=!0,n=!1,s=void 0!==b.frames?b.frames:new THREE.TubeGeometry.FrenetFrames(r,t,
-!1),C=new THREE.Vector3,H=new THREE.Vector3,B=new THREE.Vector3);n||(k=i=l=0);var w,I,J,E=this,Z=this.vertices.length,m=a.extractPoints(m),A=m.shape,m=m.holes;if(r=!THREE.Shape.Utils.isClockWise(A)){A=A.reverse();I=0;for(J=m.length;I<J;I++)w=m[I],THREE.Shape.Utils.isClockWise(w)&&(m[I]=w.reverse());r=!1}var U=THREE.Shape.Utils.triangulateShape(A,m),r=A;I=0;for(J=m.length;I<J;I++)w=m[I],A=A.concat(w);var F,G,K,N,fa=A.length,ma=U.length,eb=[],M=0,T=r.length;F=T-1;for(G=M+1;M<T;M++,F++,G++)F===T&&(F=
-0),G===T&&(G=0),eb[M]=d(r[M],r[F],r[G]);var ja=[],L,ca=eb.concat();I=0;for(J=m.length;I<J;I++){w=m[I];L=[];M=0;T=w.length;F=T-1;for(G=M+1;M<T;M++,F++,G++)F===T&&(F=0),G===T&&(G=0),L[M]=d(w[M],w[F],w[G]);ja.push(L);ca=ca.concat(L)}for(F=0;F<l;F++){w=F/l;K=i*(1-w);G=k*Math.sin(w*Math.PI/2);M=0;for(T=r.length;M<T;M++)N=c(r[M],eb[M],G),f(N.x,N.y,-K);I=0;for(J=m.length;I<J;I++){w=m[I];L=ja[I];M=0;for(T=w.length;M<T;M++)N=c(w[M],L[M],G),f(N.x,N.y,-K)}}G=k;for(M=0;M<fa;M++)N=n?c(A[M],ca[M],G):A[M],q?(H.copy(s.normals[0]).multiplyScalar(N.x),
-C.copy(s.binormals[0]).multiplyScalar(N.y),B.copy(p[0]).add(H).add(C),f(B.x,B.y,B.z)):f(N.x,N.y,0);for(w=1;w<=t;w++)for(M=0;M<fa;M++)N=n?c(A[M],ca[M],G):A[M],q?(H.copy(s.normals[w]).multiplyScalar(N.x),C.copy(s.binormals[w]).multiplyScalar(N.y),B.copy(p[w]).add(H).add(C),f(B.x,B.y,B.z)):f(N.x,N.y,h/t*w);for(F=l-1;0<=F;F--){w=F/l;K=i*(1-w);G=k*Math.sin(w*Math.PI/2);M=0;for(T=r.length;M<T;M++)N=c(r[M],eb[M],G),f(N.x,N.y,h+K);I=0;for(J=m.length;I<J;I++){w=m[I];L=ja[I];M=0;for(T=w.length;M<T;M++)N=c(w[M],
-L[M],G),q?f(N.x,N.y+p[t-1].y,p[t-1].x+K):f(N.x,N.y,h+K)}}if(n){i=0*fa;for(M=0;M<ma;M++)h=U[M],g(h[2]+i,h[1]+i,h[0]+i,!0);i=fa*(t+2*l);for(M=0;M<ma;M++)h=U[M],g(h[0]+i,h[1]+i,h[2]+i,!1)}else{for(M=0;M<ma;M++)h=U[M],g(h[2],h[1],h[0],!0);for(M=0;M<ma;M++)h=U[M],g(h[0]+fa*t,h[1]+fa*t,h[2]+fa*t,!1)}h=0;e(r,h);h+=r.length;I=0;for(J=m.length;I<J;I++)w=m[I],e(w,h),h+=w.length};
-THREE.ExtrudeGeometry.WorldUVGenerator={generateTopUV:function(a,b,c,d,e,f){b=a.vertices[e].x;e=a.vertices[e].y;c=a.vertices[f].x;f=a.vertices[f].y;return[new THREE.Vector2(a.vertices[d].x,a.vertices[d].y),new THREE.Vector2(b,e),new THREE.Vector2(c,f)]},generateBottomUV:function(a,b,c,d,e,f){return this.generateTopUV(a,b,c,d,e,f)},generateSideWallUV:function(a,b,c,d,e,f,g,h){var b=a.vertices[e].x,c=a.vertices[e].y,e=a.vertices[e].z,d=a.vertices[f].x,i=a.vertices[f].y,f=a.vertices[f].z,k=a.vertices[g].x,
-l=a.vertices[g].y,g=a.vertices[g].z,n=a.vertices[h].x,m=a.vertices[h].y,a=a.vertices[h].z;return 0.01>Math.abs(c-i)?[new THREE.Vector2(b,1-e),new THREE.Vector2(d,1-f),new THREE.Vector2(k,1-g),new THREE.Vector2(n,1-a)]:[new THREE.Vector2(c,1-e),new THREE.Vector2(i,1-f),new THREE.Vector2(l,1-g),new THREE.Vector2(m,1-a)]}};THREE.ExtrudeGeometry.__v1=new THREE.Vector2;THREE.ExtrudeGeometry.__v2=new THREE.Vector2;THREE.ExtrudeGeometry.__v3=new THREE.Vector2;THREE.ExtrudeGeometry.__v4=new THREE.Vector2;
+this.faceVertexUvs[0].push([f[e],f[e+1],g]);this.computeCentroids();this.computeFaceNormals();this.boundingSphere=new THREE.Sphere(new THREE.Vector3,a)};THREE.CircleGeometry.prototype=Object.create(THREE.Geometry.prototype);THREE.CubeGeometry=function(a,b,c,d,e,f){function g(a,b,c,d,e,f,g,p){var q,w=h.widthSegments,v=h.heightSegments,z=e/2,y=f/2,t=h.vertices.length;if("x"===a&&"y"===b||"y"===a&&"x"===b)q="z";else if("x"===a&&"z"===b||"z"===a&&"x"===b)q="y",v=h.depthSegments;else if("z"===a&&"y"===b||"y"===a&&"z"===b)q="x",w=h.depthSegments;var D=w+1,C=v+1,k=e/w,I=f/v,J=new THREE.Vector3;J[q]=0<g?1:-1;for(e=0;e<C;e++)for(f=0;f<D;f++){var B=new THREE.Vector3;B[a]=(f*k-z)*c;B[b]=(e*I-y)*d;B[q]=g;h.vertices.push(B)}for(e=
+0;e<v;e++)for(f=0;f<w;f++)a=new THREE.Face4(f+D*e+t,f+D*(e+1)+t,f+1+D*(e+1)+t,f+1+D*e+t),a.normal.copy(J),a.vertexNormals.push(J.clone(),J.clone(),J.clone(),J.clone()),a.materialIndex=p,h.faces.push(a),h.faceVertexUvs[0].push([new THREE.Vector2(f/w,1-e/v),new THREE.Vector2(f/w,1-(e+1)/v),new THREE.Vector2((f+1)/w,1-(e+1)/v),new THREE.Vector2((f+1)/w,1-e/v)])}THREE.Geometry.call(this);var h=this;this.width=a;this.height=b;this.depth=c;this.widthSegments=d||1;this.heightSegments=e||1;this.depthSegments=
+f||1;a=this.width/2;b=this.height/2;c=this.depth/2;g("z","y",-1,-1,this.depth,this.height,a,0);g("z","y",1,-1,this.depth,this.height,-a,1);g("x","z",1,1,this.width,this.depth,b,2);g("x","z",1,-1,this.width,this.depth,-b,3);g("x","y",1,-1,this.width,this.height,c,4);g("x","y",-1,-1,this.width,this.height,-c,5);this.computeCentroids();this.mergeVertices()};THREE.CubeGeometry.prototype=Object.create(THREE.Geometry.prototype);THREE.CylinderGeometry=function(a,b,c,d,e,f){THREE.Geometry.call(this);var a=void 0!==a?a:20,b=void 0!==b?b:20,c=void 0!==c?c:100,g=c/2,d=d||8,e=e||1,h,i,j=[],l=[];for(i=0;i<=e;i++){var n=[],m=[],r=i/e,u=r*(b-a)+a;for(h=0;h<=d;h++){var p=h/d,q=new THREE.Vector3;q.x=u*Math.sin(2*p*Math.PI);q.y=-r*c+g;q.z=u*Math.cos(2*p*Math.PI);this.vertices.push(q);n.push(this.vertices.length-1);m.push(new THREE.Vector2(p,1-r))}j.push(n);l.push(m)}c=(b-a)/c;for(h=0;h<d;h++){0!==a?(n=this.vertices[j[0][h]].clone(),
+m=this.vertices[j[0][h+1]].clone()):(n=this.vertices[j[1][h]].clone(),m=this.vertices[j[1][h+1]].clone());n.setY(Math.sqrt(n.x*n.x+n.z*n.z)*c).normalize();m.setY(Math.sqrt(m.x*m.x+m.z*m.z)*c).normalize();for(i=0;i<e;i++){var r=j[i][h],u=j[i+1][h],p=j[i+1][h+1],q=j[i][h+1],w=n.clone(),v=n.clone(),z=m.clone(),y=m.clone(),t=l[i][h].clone(),D=l[i+1][h].clone(),C=l[i+1][h+1].clone(),k=l[i][h+1].clone();this.faces.push(new THREE.Face4(r,u,p,q,[w,v,z,y]));this.faceVertexUvs[0].push([t,D,C,k])}}if(!f&&0<
+a){this.vertices.push(new THREE.Vector3(0,g,0));for(h=0;h<d;h++)r=j[0][h],u=j[0][h+1],p=this.vertices.length-1,w=new THREE.Vector3(0,1,0),v=new THREE.Vector3(0,1,0),z=new THREE.Vector3(0,1,0),t=l[0][h].clone(),D=l[0][h+1].clone(),C=new THREE.Vector2(D.u,0),this.faces.push(new THREE.Face3(r,u,p,[w,v,z])),this.faceVertexUvs[0].push([t,D,C])}if(!f&&0<b){this.vertices.push(new THREE.Vector3(0,-g,0));for(h=0;h<d;h++)r=j[i][h+1],u=j[i][h],p=this.vertices.length-1,w=new THREE.Vector3(0,-1,0),v=new THREE.Vector3(0,
+-1,0),z=new THREE.Vector3(0,-1,0),t=l[i][h+1].clone(),D=l[i][h].clone(),C=new THREE.Vector2(D.u,1),this.faces.push(new THREE.Face3(r,u,p,[w,v,z])),this.faceVertexUvs[0].push([t,D,C])}this.computeCentroids();this.computeFaceNormals()};THREE.CylinderGeometry.prototype=Object.create(THREE.Geometry.prototype);THREE.ExtrudeGeometry=function(a,b){"undefined"!==typeof a&&(THREE.Geometry.call(this),a=a instanceof Array?a:[a],this.shapebb=a[a.length-1].getBoundingBox(),this.addShapeList(a,b),this.computeCentroids(),this.computeFaceNormals())};THREE.ExtrudeGeometry.prototype=Object.create(THREE.Geometry.prototype);THREE.ExtrudeGeometry.prototype.addShapeList=function(a,b){for(var c=a.length,d=0;d<c;d++)this.addShape(a[d],b)};
+THREE.ExtrudeGeometry.prototype.addShape=function(a,b){function c(a,b,c){b||console.log("die");return b.clone().multiplyScalar(c).add(a)}function d(a,b,c){var d=THREE.ExtrudeGeometry.__v1,e=THREE.ExtrudeGeometry.__v2,f=THREE.ExtrudeGeometry.__v3,g=THREE.ExtrudeGeometry.__v4,h=THREE.ExtrudeGeometry.__v5,i=THREE.ExtrudeGeometry.__v6;d.set(a.x-b.x,a.y-b.y);e.set(a.x-c.x,a.y-c.y);d=d.normalize();e=e.normalize();f.set(-d.y,d.x);g.set(e.y,-e.x);h.copy(a).add(f);i.copy(a).add(g);if(h.equals(i))return g.clone();
+h.copy(b).add(f);i.copy(c).add(g);f=d.dot(g);g=i.sub(h).dot(g);0===f&&(console.log("Either infinite or no solutions!"),0===g?console.log("Its finite solutions."):console.log("Too bad, no solutions."));g/=f;return 0>g?(b=Math.atan2(b.y-a.y,b.x-a.x),a=Math.atan2(c.y-a.y,c.x-a.x),b>a&&(a+=2*Math.PI),c=(b+a)/2,a=-Math.cos(c),c=-Math.sin(c),new THREE.Vector2(a,c)):d.multiplyScalar(g).add(h).sub(a).clone()}function e(c,d){var e,f;for(N=c.length;0<=--N;){e=N;f=N-1;0>f&&(f=c.length-1);for(var g=0,h=r+2*l,
+g=0;g<h;g++){var i=O*g,j=O*(g+1),k=d+e+i,i=d+f+i,m=d+f+j,j=d+e+j,n=c,p=g,q=h,s=e,t=f,k=k+P,i=i+P,m=m+P,j=j+P;B.faces.push(new THREE.Face4(k,i,m,j,null,null,v));k=z.generateSideWallUV(B,a,n,b,k,i,m,j,p,q,s,t);B.faceVertexUvs[0].push(k)}}}function f(a,b,c){B.vertices.push(new THREE.Vector3(a,b,c))}function g(c,d,e,f){c+=P;d+=P;e+=P;B.faces.push(new THREE.Face3(c,d,e,null,null,w));c=f?z.generateBottomUV(B,a,b,c,d,e):z.generateTopUV(B,a,b,c,d,e);B.faceVertexUvs[0].push(c)}var h=void 0!==b.amount?b.amount:
+100,i=void 0!==b.bevelThickness?b.bevelThickness:6,j=void 0!==b.bevelSize?b.bevelSize:i-2,l=void 0!==b.bevelSegments?b.bevelSegments:3,n=void 0!==b.bevelEnabled?b.bevelEnabled:!0,m=void 0!==b.curveSegments?b.curveSegments:12,r=void 0!==b.steps?b.steps:1,u=b.extrudePath,p,q=!1,w=b.material,v=b.extrudeMaterial,z=void 0!==b.UVGenerator?b.UVGenerator:THREE.ExtrudeGeometry.WorldUVGenerator,y,t,D,C;u&&(p=u.getSpacedPoints(r),q=!0,n=!1,y=void 0!==b.frames?b.frames:new THREE.TubeGeometry.FrenetFrames(u,r,
+!1),t=new THREE.Vector3,D=new THREE.Vector3,C=new THREE.Vector3);n||(j=i=l=0);var k,I,J,B=this,P=this.vertices.length,m=a.extractPoints(m),A=m.shape,m=m.holes;if(u=!THREE.Shape.Utils.isClockWise(A)){A=A.reverse();I=0;for(J=m.length;I<J;I++)k=m[I],THREE.Shape.Utils.isClockWise(k)&&(m[I]=k.reverse());u=!1}var G=THREE.Shape.Utils.triangulateShape(A,m),u=A;I=0;for(J=m.length;I<J;I++)k=m[I],A=A.concat(k);var E,F,s,H,O=A.length,K=G.length,x=[],N=0,R=u.length;E=R-1;for(F=N+1;N<R;N++,E++,F++)E===R&&(E=0),
+F===R&&(F=0),x[N]=d(u[N],u[E],u[F]);var $=[],Y,W=x.concat();I=0;for(J=m.length;I<J;I++){k=m[I];Y=[];N=0;R=k.length;E=R-1;for(F=N+1;N<R;N++,E++,F++)E===R&&(E=0),F===R&&(F=0),Y[N]=d(k[N],k[E],k[F]);$.push(Y);W=W.concat(Y)}for(E=0;E<l;E++){k=E/l;s=i*(1-k);F=j*Math.sin(k*Math.PI/2);N=0;for(R=u.length;N<R;N++)H=c(u[N],x[N],F),f(H.x,H.y,-s);I=0;for(J=m.length;I<J;I++){k=m[I];Y=$[I];N=0;for(R=k.length;N<R;N++)H=c(k[N],Y[N],F),f(H.x,H.y,-s)}}F=j;for(N=0;N<O;N++)H=n?c(A[N],W[N],F):A[N],q?(D.copy(y.normals[0]).multiplyScalar(H.x),
+t.copy(y.binormals[0]).multiplyScalar(H.y),C.copy(p[0]).add(D).add(t),f(C.x,C.y,C.z)):f(H.x,H.y,0);for(k=1;k<=r;k++)for(N=0;N<O;N++)H=n?c(A[N],W[N],F):A[N],q?(D.copy(y.normals[k]).multiplyScalar(H.x),t.copy(y.binormals[k]).multiplyScalar(H.y),C.copy(p[k]).add(D).add(t),f(C.x,C.y,C.z)):f(H.x,H.y,h/r*k);for(E=l-1;0<=E;E--){k=E/l;s=i*(1-k);F=j*Math.sin(k*Math.PI/2);N=0;for(R=u.length;N<R;N++)H=c(u[N],x[N],F),f(H.x,H.y,h+s);I=0;for(J=m.length;I<J;I++){k=m[I];Y=$[I];N=0;for(R=k.length;N<R;N++)H=c(k[N],
+Y[N],F),q?f(H.x,H.y+p[r-1].y,p[r-1].x+s):f(H.x,H.y,h+s)}}if(n){i=0*O;for(N=0;N<K;N++)h=G[N],g(h[2]+i,h[1]+i,h[0]+i,!0);i=O*(r+2*l);for(N=0;N<K;N++)h=G[N],g(h[0]+i,h[1]+i,h[2]+i,!1)}else{for(N=0;N<K;N++)h=G[N],g(h[2],h[1],h[0],!0);for(N=0;N<K;N++)h=G[N],g(h[0]+O*r,h[1]+O*r,h[2]+O*r,!1)}h=0;e(u,h);h+=u.length;I=0;for(J=m.length;I<J;I++)k=m[I],e(k,h),h+=k.length};
+THREE.ExtrudeGeometry.WorldUVGenerator={generateTopUV:function(a,b,c,d,e,f){b=a.vertices[e].x;e=a.vertices[e].y;c=a.vertices[f].x;f=a.vertices[f].y;return[new THREE.Vector2(a.vertices[d].x,a.vertices[d].y),new THREE.Vector2(b,e),new THREE.Vector2(c,f)]},generateBottomUV:function(a,b,c,d,e,f){return this.generateTopUV(a,b,c,d,e,f)},generateSideWallUV:function(a,b,c,d,e,f,g,h){var b=a.vertices[e].x,c=a.vertices[e].y,e=a.vertices[e].z,d=a.vertices[f].x,i=a.vertices[f].y,f=a.vertices[f].z,j=a.vertices[g].x,
+l=a.vertices[g].y,g=a.vertices[g].z,n=a.vertices[h].x,m=a.vertices[h].y,a=a.vertices[h].z;return 0.01>Math.abs(c-i)?[new THREE.Vector2(b,1-e),new THREE.Vector2(d,1-f),new THREE.Vector2(j,1-g),new THREE.Vector2(n,1-a)]:[new THREE.Vector2(c,1-e),new THREE.Vector2(i,1-f),new THREE.Vector2(l,1-g),new THREE.Vector2(m,1-a)]}};THREE.ExtrudeGeometry.__v1=new THREE.Vector2;THREE.ExtrudeGeometry.__v2=new THREE.Vector2;THREE.ExtrudeGeometry.__v3=new THREE.Vector2;THREE.ExtrudeGeometry.__v4=new THREE.Vector2;
 THREE.ExtrudeGeometry.__v5=new THREE.Vector2;THREE.ExtrudeGeometry.__v6=new THREE.Vector2;THREE.ShapeGeometry=function(a,b){THREE.Geometry.call(this);!1===a instanceof Array&&(a=[a]);this.shapebb=a[a.length-1].getBoundingBox();this.addShapeList(a,b);this.computeCentroids();this.computeFaceNormals()};THREE.ShapeGeometry.prototype=Object.create(THREE.Geometry.prototype);THREE.ShapeGeometry.prototype.addShapeList=function(a,b){for(var c=0,d=a.length;c<d;c++)this.addShape(a[c],b);return this};
 THREE.ExtrudeGeometry.__v5=new THREE.Vector2;THREE.ExtrudeGeometry.__v6=new THREE.Vector2;THREE.ShapeGeometry=function(a,b){THREE.Geometry.call(this);!1===a instanceof Array&&(a=[a]);this.shapebb=a[a.length-1].getBoundingBox();this.addShapeList(a,b);this.computeCentroids();this.computeFaceNormals()};THREE.ShapeGeometry.prototype=Object.create(THREE.Geometry.prototype);THREE.ShapeGeometry.prototype.addShapeList=function(a,b){for(var c=0,d=a.length;c<d;c++)this.addShape(a[c],b);return this};
-THREE.ShapeGeometry.prototype.addShape=function(a,b){void 0===b&&(b={});var c=b.material,d=void 0===b.UVGenerator?THREE.ExtrudeGeometry.WorldUVGenerator:b.UVGenerator,e,f,g,h=this.vertices.length;e=a.extractPoints(void 0!==b.curveSegments?b.curveSegments:12);var i=e.shape,k=e.holes;if(!THREE.Shape.Utils.isClockWise(i)){i=i.reverse();e=0;for(f=k.length;e<f;e++)g=k[e],THREE.Shape.Utils.isClockWise(g)&&(k[e]=g.reverse())}var l=THREE.Shape.Utils.triangulateShape(i,k);e=0;for(f=k.length;e<f;e++)g=k[e],
-i=i.concat(g);k=i.length;f=l.length;for(e=0;e<k;e++)g=i[e],this.vertices.push(new THREE.Vector3(g.x,g.y,0));for(e=0;e<f;e++)k=l[e],i=k[0]+h,g=k[1]+h,k=k[2]+h,this.faces.push(new THREE.Face3(i,g,k,null,null,c)),this.faceVertexUvs[0].push(d.generateBottomUV(this,a,b,i,g,k))};THREE.LatheGeometry=function(a,b,c,d){THREE.Geometry.call(this);for(var b=b||12,c=c||0,d=d||2*Math.PI,e=1/(a.length-1),f=1/b,g=0,h=b;g<=h;g++)for(var i=c+g*f*d,k=Math.cos(i),l=Math.sin(i),i=0,n=a.length;i<n;i++){var m=a[i],t=new THREE.Vector3;t.x=k*m.x-l*m.y;t.y=l*m.x+k*m.y;t.z=m.z;this.vertices.push(t)}c=a.length;g=0;for(h=b;g<h;g++){i=0;for(n=a.length-1;i<n;i++)d=b=i+c*g,l=b+c,k=b+1+c,this.faces.push(new THREE.Face4(d,l,k,b+1)),k=g*f,b=i*e,d=k+f,l=b+e,this.faceVertexUvs[0].push([new THREE.Vector2(k,
-b),new THREE.Vector2(d,b),new THREE.Vector2(d,l),new THREE.Vector2(k,l)])}this.mergeVertices();this.computeCentroids();this.computeFaceNormals();this.computeVertexNormals()};THREE.LatheGeometry.prototype=Object.create(THREE.Geometry.prototype);THREE.PlaneGeometry=function(a,b,c,d){THREE.Geometry.call(this);this.width=a;this.height=b;this.widthSegments=c||1;this.heightSegments=d||1;for(var c=a/2,e=b/2,d=this.widthSegments,f=this.heightSegments,g=d+1,h=f+1,i=this.width/d,k=this.height/f,l=new THREE.Vector3(0,0,1),a=0;a<h;a++)for(b=0;b<g;b++)this.vertices.push(new THREE.Vector3(b*i-c,-(a*k-e),0));for(a=0;a<f;a++)for(b=0;b<d;b++)c=new THREE.Face4(b+g*a,b+g*(a+1),b+1+g*(a+1),b+1+g*a),c.normal.copy(l),c.vertexNormals.push(l.clone(),l.clone(),
-l.clone(),l.clone()),this.faces.push(c),this.faceVertexUvs[0].push([new THREE.Vector2(b/d,1-a/f),new THREE.Vector2(b/d,1-(a+1)/f),new THREE.Vector2((b+1)/d,1-(a+1)/f),new THREE.Vector2((b+1)/d,1-a/f)]);this.computeCentroids()};THREE.PlaneGeometry.prototype=Object.create(THREE.Geometry.prototype);THREE.SphereGeometry=function(a,b,c,d,e,f,g){THREE.Geometry.call(this);this.radius=a||50;this.widthSegments=Math.max(3,Math.floor(b)||8);this.heightSegments=Math.max(2,Math.floor(c)||6);for(var d=void 0!==d?d:0,e=void 0!==e?e:2*Math.PI,f=void 0!==f?f:0,g=void 0!==g?g:Math.PI,h=[],i=[],c=0;c<=this.heightSegments;c++){for(var k=[],l=[],b=0;b<=this.widthSegments;b++){var n=b/this.widthSegments,m=c/this.heightSegments,t=new THREE.Vector3;t.x=-this.radius*Math.cos(d+n*e)*Math.sin(f+m*g);t.y=this.radius*
-Math.cos(f+m*g);t.z=this.radius*Math.sin(d+n*e)*Math.sin(f+m*g);this.vertices.push(t);k.push(this.vertices.length-1);l.push(new THREE.Vector2(n,1-m))}h.push(k);i.push(l)}for(c=0;c<this.heightSegments;c++)for(b=0;b<this.widthSegments;b++){var d=h[c][b+1],e=h[c][b],f=h[c+1][b],g=h[c+1][b+1],k=this.vertices[d].clone().normalize(),l=this.vertices[e].clone().normalize(),n=this.vertices[f].clone().normalize(),m=this.vertices[g].clone().normalize(),t=i[c][b+1].clone(),r=i[c][b].clone(),p=i[c+1][b].clone(),
-q=i[c+1][b+1].clone();Math.abs(this.vertices[d].y)===this.radius?(this.faces.push(new THREE.Face3(d,f,g,[k,n,m])),this.faceVertexUvs[0].push([t,p,q])):Math.abs(this.vertices[f].y)===this.radius?(this.faces.push(new THREE.Face3(d,e,f,[k,l,n])),this.faceVertexUvs[0].push([t,r,p])):(this.faces.push(new THREE.Face4(d,e,f,g,[k,l,n,m])),this.faceVertexUvs[0].push([t,r,p,q]))}this.computeCentroids();this.computeFaceNormals();this.boundingSphere=new THREE.Sphere(new THREE.Vector3,a)};
+THREE.ShapeGeometry.prototype.addShape=function(a,b){void 0===b&&(b={});var c=b.material,d=void 0===b.UVGenerator?THREE.ExtrudeGeometry.WorldUVGenerator:b.UVGenerator,e,f,g,h=this.vertices.length;e=a.extractPoints(void 0!==b.curveSegments?b.curveSegments:12);var i=e.shape,j=e.holes;if(!THREE.Shape.Utils.isClockWise(i)){i=i.reverse();e=0;for(f=j.length;e<f;e++)g=j[e],THREE.Shape.Utils.isClockWise(g)&&(j[e]=g.reverse())}var l=THREE.Shape.Utils.triangulateShape(i,j);e=0;for(f=j.length;e<f;e++)g=j[e],
+i=i.concat(g);j=i.length;f=l.length;for(e=0;e<j;e++)g=i[e],this.vertices.push(new THREE.Vector3(g.x,g.y,0));for(e=0;e<f;e++)j=l[e],i=j[0]+h,g=j[1]+h,j=j[2]+h,this.faces.push(new THREE.Face3(i,g,j,null,null,c)),this.faceVertexUvs[0].push(d.generateBottomUV(this,a,b,i,g,j))};THREE.LatheGeometry=function(a,b,c,d){THREE.Geometry.call(this);for(var b=b||12,c=c||0,d=d||2*Math.PI,e=1/(a.length-1),f=1/b,g=0,h=b;g<=h;g++)for(var i=c+g*f*d,j=Math.cos(i),l=Math.sin(i),i=0,n=a.length;i<n;i++){var m=a[i],r=new THREE.Vector3;r.x=j*m.x-l*m.y;r.y=l*m.x+j*m.y;r.z=m.z;this.vertices.push(r)}c=a.length;g=0;for(h=b;g<h;g++){i=0;for(n=a.length-1;i<n;i++)d=b=i+c*g,l=b+c,j=b+1+c,this.faces.push(new THREE.Face4(d,l,j,b+1)),j=g*f,b=i*e,d=j+f,l=b+e,this.faceVertexUvs[0].push([new THREE.Vector2(j,
+b),new THREE.Vector2(d,b),new THREE.Vector2(d,l),new THREE.Vector2(j,l)])}this.mergeVertices();this.computeCentroids();this.computeFaceNormals();this.computeVertexNormals()};THREE.LatheGeometry.prototype=Object.create(THREE.Geometry.prototype);THREE.PlaneGeometry=function(a,b,c,d){THREE.Geometry.call(this);this.width=a;this.height=b;this.widthSegments=c||1;this.heightSegments=d||1;for(var c=a/2,e=b/2,d=this.widthSegments,f=this.heightSegments,g=d+1,h=f+1,i=this.width/d,j=this.height/f,l=new THREE.Vector3(0,0,1),a=0;a<h;a++)for(b=0;b<g;b++)this.vertices.push(new THREE.Vector3(b*i-c,-(a*j-e),0));for(a=0;a<f;a++)for(b=0;b<d;b++)c=new THREE.Face4(b+g*a,b+g*(a+1),b+1+g*(a+1),b+1+g*a),c.normal.copy(l),c.vertexNormals.push(l.clone(),l.clone(),
+l.clone(),l.clone()),this.faces.push(c),this.faceVertexUvs[0].push([new THREE.Vector2(b/d,1-a/f),new THREE.Vector2(b/d,1-(a+1)/f),new THREE.Vector2((b+1)/d,1-(a+1)/f),new THREE.Vector2((b+1)/d,1-a/f)]);this.computeCentroids()};THREE.PlaneGeometry.prototype=Object.create(THREE.Geometry.prototype);THREE.SphereGeometry=function(a,b,c,d,e,f,g){THREE.Geometry.call(this);this.radius=a||50;this.widthSegments=Math.max(3,Math.floor(b)||8);this.heightSegments=Math.max(2,Math.floor(c)||6);for(var d=void 0!==d?d:0,e=void 0!==e?e:2*Math.PI,f=void 0!==f?f:0,g=void 0!==g?g:Math.PI,h=[],i=[],c=0;c<=this.heightSegments;c++){for(var j=[],l=[],b=0;b<=this.widthSegments;b++){var n=b/this.widthSegments,m=c/this.heightSegments,r=new THREE.Vector3;r.x=-this.radius*Math.cos(d+n*e)*Math.sin(f+m*g);r.y=this.radius*
+Math.cos(f+m*g);r.z=this.radius*Math.sin(d+n*e)*Math.sin(f+m*g);this.vertices.push(r);j.push(this.vertices.length-1);l.push(new THREE.Vector2(n,1-m))}h.push(j);i.push(l)}for(c=0;c<this.heightSegments;c++)for(b=0;b<this.widthSegments;b++){var d=h[c][b+1],e=h[c][b],f=h[c+1][b],g=h[c+1][b+1],j=this.vertices[d].clone().normalize(),l=this.vertices[e].clone().normalize(),n=this.vertices[f].clone().normalize(),m=this.vertices[g].clone().normalize(),r=i[c][b+1].clone(),u=i[c][b].clone(),p=i[c+1][b].clone(),
+q=i[c+1][b+1].clone();Math.abs(this.vertices[d].y)===this.radius?(this.faces.push(new THREE.Face3(d,f,g,[j,n,m])),this.faceVertexUvs[0].push([r,p,q])):Math.abs(this.vertices[f].y)===this.radius?(this.faces.push(new THREE.Face3(d,e,f,[j,l,n])),this.faceVertexUvs[0].push([r,u,p])):(this.faces.push(new THREE.Face4(d,e,f,g,[j,l,n,m])),this.faceVertexUvs[0].push([r,u,p,q]))}this.computeCentroids();this.computeFaceNormals();this.boundingSphere=new THREE.Sphere(new THREE.Vector3,a)};
 THREE.SphereGeometry.prototype=Object.create(THREE.Geometry.prototype);THREE.TextGeometry=function(a,b){var c=THREE.FontUtils.generateShapes(a,b);b.amount=void 0!==b.height?b.height:50;void 0===b.bevelThickness&&(b.bevelThickness=10);void 0===b.bevelSize&&(b.bevelSize=8);void 0===b.bevelEnabled&&(b.bevelEnabled=!1);THREE.ExtrudeGeometry.call(this,c,b)};THREE.TextGeometry.prototype=Object.create(THREE.ExtrudeGeometry.prototype);THREE.TorusGeometry=function(a,b,c,d,e){THREE.Geometry.call(this);this.radius=a||100;this.tube=b||40;this.radialSegments=c||8;this.tubularSegments=d||6;this.arc=e||2*Math.PI;e=new THREE.Vector3;a=[];b=[];for(c=0;c<=this.radialSegments;c++)for(d=0;d<=this.tubularSegments;d++){var f=d/this.tubularSegments*this.arc,g=2*c/this.radialSegments*Math.PI;e.x=this.radius*Math.cos(f);e.y=this.radius*Math.sin(f);var h=new THREE.Vector3;h.x=(this.radius+this.tube*Math.cos(g))*Math.cos(f);h.y=(this.radius+this.tube*
 THREE.SphereGeometry.prototype=Object.create(THREE.Geometry.prototype);THREE.TextGeometry=function(a,b){var c=THREE.FontUtils.generateShapes(a,b);b.amount=void 0!==b.height?b.height:50;void 0===b.bevelThickness&&(b.bevelThickness=10);void 0===b.bevelSize&&(b.bevelSize=8);void 0===b.bevelEnabled&&(b.bevelEnabled=!1);THREE.ExtrudeGeometry.call(this,c,b)};THREE.TextGeometry.prototype=Object.create(THREE.ExtrudeGeometry.prototype);THREE.TorusGeometry=function(a,b,c,d,e){THREE.Geometry.call(this);this.radius=a||100;this.tube=b||40;this.radialSegments=c||8;this.tubularSegments=d||6;this.arc=e||2*Math.PI;e=new THREE.Vector3;a=[];b=[];for(c=0;c<=this.radialSegments;c++)for(d=0;d<=this.tubularSegments;d++){var f=d/this.tubularSegments*this.arc,g=2*c/this.radialSegments*Math.PI;e.x=this.radius*Math.cos(f);e.y=this.radius*Math.sin(f);var h=new THREE.Vector3;h.x=(this.radius+this.tube*Math.cos(g))*Math.cos(f);h.y=(this.radius+this.tube*
 Math.cos(g))*Math.sin(f);h.z=this.tube*Math.sin(g);this.vertices.push(h);a.push(new THREE.Vector2(d/this.tubularSegments,c/this.radialSegments));b.push(h.clone().sub(e).normalize())}for(c=1;c<=this.radialSegments;c++)for(d=1;d<=this.tubularSegments;d++){var e=(this.tubularSegments+1)*c+d-1,f=(this.tubularSegments+1)*(c-1)+d-1,g=(this.tubularSegments+1)*(c-1)+d,h=(this.tubularSegments+1)*c+d,i=new THREE.Face4(e,f,g,h,[b[e],b[f],b[g],b[h]]);i.normal.add(b[e]);i.normal.add(b[f]);i.normal.add(b[g]);i.normal.add(b[h]);
 Math.cos(g))*Math.sin(f);h.z=this.tube*Math.sin(g);this.vertices.push(h);a.push(new THREE.Vector2(d/this.tubularSegments,c/this.radialSegments));b.push(h.clone().sub(e).normalize())}for(c=1;c<=this.radialSegments;c++)for(d=1;d<=this.tubularSegments;d++){var e=(this.tubularSegments+1)*c+d-1,f=(this.tubularSegments+1)*(c-1)+d-1,g=(this.tubularSegments+1)*(c-1)+d,h=(this.tubularSegments+1)*c+d,i=new THREE.Face4(e,f,g,h,[b[e],b[f],b[g],b[h]]);i.normal.add(b[e]);i.normal.add(b[f]);i.normal.add(b[g]);i.normal.add(b[h]);
 i.normal.normalize();this.faces.push(i);this.faceVertexUvs[0].push([a[e].clone(),a[f].clone(),a[g].clone(),a[h].clone()])}this.computeCentroids()};THREE.TorusGeometry.prototype=Object.create(THREE.Geometry.prototype);THREE.TorusKnotGeometry=function(a,b,c,d,e,f,g){function h(a,b,c,d,e,f){var g=Math.cos(a);Math.cos(b);b=Math.sin(a);a*=c/d;c=Math.cos(a);g*=0.5*e*(2+c);b=0.5*e*(2+c)*b;e=0.5*f*e*Math.sin(a);return new THREE.Vector3(g,b,e)}THREE.Geometry.call(this);this.radius=a||100;this.tube=b||40;this.radialSegments=c||64;this.tubularSegments=d||8;this.p=e||2;this.q=f||3;this.heightScale=g||1;this.grid=Array(this.radialSegments);c=new THREE.Vector3;d=new THREE.Vector3;e=new THREE.Vector3;for(a=0;a<this.radialSegments;++a){this.grid[a]=
 i.normal.normalize();this.faces.push(i);this.faceVertexUvs[0].push([a[e].clone(),a[f].clone(),a[g].clone(),a[h].clone()])}this.computeCentroids()};THREE.TorusGeometry.prototype=Object.create(THREE.Geometry.prototype);THREE.TorusKnotGeometry=function(a,b,c,d,e,f,g){function h(a,b,c,d,e,f){var g=Math.cos(a);Math.cos(b);b=Math.sin(a);a*=c/d;c=Math.cos(a);g*=0.5*e*(2+c);b=0.5*e*(2+c)*b;e=0.5*f*e*Math.sin(a);return new THREE.Vector3(g,b,e)}THREE.Geometry.call(this);this.radius=a||100;this.tube=b||40;this.radialSegments=c||64;this.tubularSegments=d||8;this.p=e||2;this.q=f||3;this.heightScale=g||1;this.grid=Array(this.radialSegments);c=new THREE.Vector3;d=new THREE.Vector3;e=new THREE.Vector3;for(a=0;a<this.radialSegments;++a){this.grid[a]=
 Array(this.tubularSegments);for(b=0;b<this.tubularSegments;++b){var i=2*(a/this.radialSegments)*this.p*Math.PI,g=2*(b/this.tubularSegments)*Math.PI,f=h(i,g,this.q,this.p,this.radius,this.heightScale),i=h(i+0.01,g,this.q,this.p,this.radius,this.heightScale);c.subVectors(i,f);d.addVectors(i,f);e.crossVectors(c,d);d.crossVectors(e,c);e.normalize();d.normalize();i=-this.tube*Math.cos(g);g=this.tube*Math.sin(g);f.x+=i*d.x+g*e.x;f.y+=i*d.y+g*e.y;f.z+=i*d.z+g*e.z;this.grid[a][b]=this.vertices.push(new THREE.Vector3(f.x,
 Array(this.tubularSegments);for(b=0;b<this.tubularSegments;++b){var i=2*(a/this.radialSegments)*this.p*Math.PI,g=2*(b/this.tubularSegments)*Math.PI,f=h(i,g,this.q,this.p,this.radius,this.heightScale),i=h(i+0.01,g,this.q,this.p,this.radius,this.heightScale);c.subVectors(i,f);d.addVectors(i,f);e.crossVectors(c,d);d.crossVectors(e,c);e.normalize();d.normalize();i=-this.tube*Math.cos(g);g=this.tube*Math.sin(g);f.x+=i*d.x+g*e.x;f.y+=i*d.y+g*e.y;f.z+=i*d.z+g*e.z;this.grid[a][b]=this.vertices.push(new THREE.Vector3(f.x,
-f.y,f.z))-1}}for(a=0;a<this.radialSegments;++a)for(b=0;b<this.tubularSegments;++b){var e=(a+1)%this.radialSegments,f=(b+1)%this.tubularSegments,c=this.grid[a][b],d=this.grid[e][b],e=this.grid[e][f],f=this.grid[a][f],g=new THREE.Vector2(a/this.radialSegments,b/this.tubularSegments),i=new THREE.Vector2((a+1)/this.radialSegments,b/this.tubularSegments),k=new THREE.Vector2((a+1)/this.radialSegments,(b+1)/this.tubularSegments),l=new THREE.Vector2(a/this.radialSegments,(b+1)/this.tubularSegments);this.faces.push(new THREE.Face4(c,
-d,e,f));this.faceVertexUvs[0].push([g,i,k,l])}this.computeCentroids();this.computeFaceNormals();this.computeVertexNormals()};THREE.TorusKnotGeometry.prototype=Object.create(THREE.Geometry.prototype);THREE.TubeGeometry=function(a,b,c,d,e,f){THREE.Geometry.call(this);this.path=a;this.segments=b||64;this.radius=c||1;this.radiusSegments=d||8;this.closed=e||!1;f&&(this.debug=new THREE.Object3D);this.grid=[];var g,h,e=this.segments+1,i,k,l,f=new THREE.Vector3,n,m,t,b=new THREE.TubeGeometry.FrenetFrames(this.path,this.segments,this.closed);n=b.tangents;m=b.normals;t=b.binormals;this.tangents=n;this.normals=m;this.binormals=t;for(b=0;b<e;b++){this.grid[b]=[];d=b/(e-1);l=a.getPointAt(d);d=n[b];g=m[b];
-h=t[b];this.debug&&(this.debug.add(new THREE.ArrowHelper(d,l,c,255)),this.debug.add(new THREE.ArrowHelper(g,l,c,16711680)),this.debug.add(new THREE.ArrowHelper(h,l,c,65280)));for(d=0;d<this.radiusSegments;d++)i=2*(d/this.radiusSegments)*Math.PI,k=-this.radius*Math.cos(i),i=this.radius*Math.sin(i),f.copy(l),f.x+=k*g.x+i*h.x,f.y+=k*g.y+i*h.y,f.z+=k*g.z+i*h.z,this.grid[b][d]=this.vertices.push(new THREE.Vector3(f.x,f.y,f.z))-1}for(b=0;b<this.segments;b++)for(d=0;d<this.radiusSegments;d++)e=this.closed?
-(b+1)%this.segments:b+1,f=(d+1)%this.radiusSegments,a=this.grid[b][d],c=this.grid[e][d],e=this.grid[e][f],f=this.grid[b][f],n=new THREE.Vector2(b/this.segments,d/this.radiusSegments),m=new THREE.Vector2((b+1)/this.segments,d/this.radiusSegments),t=new THREE.Vector2((b+1)/this.segments,(d+1)/this.radiusSegments),g=new THREE.Vector2(b/this.segments,(d+1)/this.radiusSegments),this.faces.push(new THREE.Face4(a,c,e,f)),this.faceVertexUvs[0].push([n,m,t,g]);this.computeCentroids();this.computeFaceNormals();
+f.y,f.z))-1}}for(a=0;a<this.radialSegments;++a)for(b=0;b<this.tubularSegments;++b){var e=(a+1)%this.radialSegments,f=(b+1)%this.tubularSegments,c=this.grid[a][b],d=this.grid[e][b],e=this.grid[e][f],f=this.grid[a][f],g=new THREE.Vector2(a/this.radialSegments,b/this.tubularSegments),i=new THREE.Vector2((a+1)/this.radialSegments,b/this.tubularSegments),j=new THREE.Vector2((a+1)/this.radialSegments,(b+1)/this.tubularSegments),l=new THREE.Vector2(a/this.radialSegments,(b+1)/this.tubularSegments);this.faces.push(new THREE.Face4(c,
+d,e,f));this.faceVertexUvs[0].push([g,i,j,l])}this.computeCentroids();this.computeFaceNormals();this.computeVertexNormals()};THREE.TorusKnotGeometry.prototype=Object.create(THREE.Geometry.prototype);THREE.TubeGeometry=function(a,b,c,d,e,f){THREE.Geometry.call(this);this.path=a;this.segments=b||64;this.radius=c||1;this.radiusSegments=d||8;this.closed=e||!1;f&&(this.debug=new THREE.Object3D);this.grid=[];var g,h,e=this.segments+1,i,j,l,f=new THREE.Vector3,n,m,r,b=new THREE.TubeGeometry.FrenetFrames(this.path,this.segments,this.closed);n=b.tangents;m=b.normals;r=b.binormals;this.tangents=n;this.normals=m;this.binormals=r;for(b=0;b<e;b++){this.grid[b]=[];d=b/(e-1);l=a.getPointAt(d);d=n[b];g=m[b];
+h=r[b];this.debug&&(this.debug.add(new THREE.ArrowHelper(d,l,c,255)),this.debug.add(new THREE.ArrowHelper(g,l,c,16711680)),this.debug.add(new THREE.ArrowHelper(h,l,c,65280)));for(d=0;d<this.radiusSegments;d++)i=2*(d/this.radiusSegments)*Math.PI,j=-this.radius*Math.cos(i),i=this.radius*Math.sin(i),f.copy(l),f.x+=j*g.x+i*h.x,f.y+=j*g.y+i*h.y,f.z+=j*g.z+i*h.z,this.grid[b][d]=this.vertices.push(new THREE.Vector3(f.x,f.y,f.z))-1}for(b=0;b<this.segments;b++)for(d=0;d<this.radiusSegments;d++)e=this.closed?
+(b+1)%this.segments:b+1,f=(d+1)%this.radiusSegments,a=this.grid[b][d],c=this.grid[e][d],e=this.grid[e][f],f=this.grid[b][f],n=new THREE.Vector2(b/this.segments,d/this.radiusSegments),m=new THREE.Vector2((b+1)/this.segments,d/this.radiusSegments),r=new THREE.Vector2((b+1)/this.segments,(d+1)/this.radiusSegments),g=new THREE.Vector2(b/this.segments,(d+1)/this.radiusSegments),this.faces.push(new THREE.Face4(a,c,e,f)),this.faceVertexUvs[0].push([n,m,r,g]);this.computeCentroids();this.computeFaceNormals();
 this.computeVertexNormals()};THREE.TubeGeometry.prototype=Object.create(THREE.Geometry.prototype);
 this.computeVertexNormals()};THREE.TubeGeometry.prototype=Object.create(THREE.Geometry.prototype);
-THREE.TubeGeometry.FrenetFrames=function(a,b,c){new THREE.Vector3;var d=new THREE.Vector3;new THREE.Vector3;var e=[],f=[],g=[],h=new THREE.Vector3,i=new THREE.Matrix4,b=b+1,k,l,n;this.tangents=e;this.normals=f;this.binormals=g;for(k=0;k<b;k++)l=k/(b-1),e[k]=a.getTangentAt(l),e[k].normalize();f[0]=new THREE.Vector3;g[0]=new THREE.Vector3;a=Number.MAX_VALUE;k=Math.abs(e[0].x);l=Math.abs(e[0].y);n=Math.abs(e[0].z);k<=a&&(a=k,d.set(1,0,0));l<=a&&(a=l,d.set(0,1,0));n<=a&&d.set(0,0,1);h.crossVectors(e[0],
-d).normalize();f[0].crossVectors(e[0],h);g[0].crossVectors(e[0],f[0]);for(k=1;k<b;k++)f[k]=f[k-1].clone(),g[k]=g[k-1].clone(),h.crossVectors(e[k-1],e[k]),1E-4<h.length()&&(h.normalize(),d=Math.acos(e[k-1].dot(e[k])),f[k].applyMatrix4(i.makeRotationAxis(h,d))),g[k].crossVectors(e[k],f[k]);if(c){d=Math.acos(f[0].dot(f[b-1]));d/=b-1;0<e[0].dot(h.crossVectors(f[0],f[b-1]))&&(d=-d);for(k=1;k<b;k++)f[k].applyMatrix4(i.makeRotationAxis(e[k],d*k)),g[k].crossVectors(e[k],f[k])}};THREE.PolyhedronGeometry=function(a,b,c,d){function e(a){var b=a.normalize().clone();b.index=i.vertices.push(b)-1;var c=Math.atan2(a.z,-a.x)/2/Math.PI+0.5,a=Math.atan2(-a.y,Math.sqrt(a.x*a.x+a.z*a.z))/Math.PI+0.5;b.uv=new THREE.Vector2(c,1-a);return b}function f(a,b,c,d){1>d?(d=new THREE.Face3(a.index,b.index,c.index,[a.clone(),b.clone(),c.clone()]),d.centroid.add(a).add(b).add(c).divideScalar(3),d.normal=d.centroid.clone().normalize(),i.faces.push(d),d=Math.atan2(d.centroid.z,-d.centroid.x),i.faceVertexUvs[0].push([h(a.uv,
+THREE.TubeGeometry.FrenetFrames=function(a,b,c){new THREE.Vector3;var d=new THREE.Vector3;new THREE.Vector3;var e=[],f=[],g=[],h=new THREE.Vector3,i=new THREE.Matrix4,b=b+1,j,l,n;this.tangents=e;this.normals=f;this.binormals=g;for(j=0;j<b;j++)l=j/(b-1),e[j]=a.getTangentAt(l),e[j].normalize();f[0]=new THREE.Vector3;g[0]=new THREE.Vector3;a=Number.MAX_VALUE;j=Math.abs(e[0].x);l=Math.abs(e[0].y);n=Math.abs(e[0].z);j<=a&&(a=j,d.set(1,0,0));l<=a&&(a=l,d.set(0,1,0));n<=a&&d.set(0,0,1);h.crossVectors(e[0],
+d).normalize();f[0].crossVectors(e[0],h);g[0].crossVectors(e[0],f[0]);for(j=1;j<b;j++)f[j]=f[j-1].clone(),g[j]=g[j-1].clone(),h.crossVectors(e[j-1],e[j]),1E-4<h.length()&&(h.normalize(),d=Math.acos(e[j-1].dot(e[j])),f[j].applyMatrix4(i.makeRotationAxis(h,d))),g[j].crossVectors(e[j],f[j]);if(c){d=Math.acos(f[0].dot(f[b-1]));d/=b-1;0<e[0].dot(h.crossVectors(f[0],f[b-1]))&&(d=-d);for(j=1;j<b;j++)f[j].applyMatrix4(i.makeRotationAxis(e[j],d*j)),g[j].crossVectors(e[j],f[j])}};THREE.PolyhedronGeometry=function(a,b,c,d){function e(a){var b=a.normalize().clone();b.index=i.vertices.push(b)-1;var c=Math.atan2(a.z,-a.x)/2/Math.PI+0.5,a=Math.atan2(-a.y,Math.sqrt(a.x*a.x+a.z*a.z))/Math.PI+0.5;b.uv=new THREE.Vector2(c,1-a);return b}function f(a,b,c,d){1>d?(d=new THREE.Face3(a.index,b.index,c.index,[a.clone(),b.clone(),c.clone()]),d.centroid.add(a).add(b).add(c).divideScalar(3),d.normal=d.centroid.clone().normalize(),i.faces.push(d),d=Math.atan2(d.centroid.z,-d.centroid.x),i.faceVertexUvs[0].push([h(a.uv,
 a,d),h(b.uv,b,d),h(c.uv,c,d)])):(d-=1,f(a,g(a,b),g(a,c),d),f(g(a,b),b,g(b,c),d),f(g(a,c),g(b,c),c,d),f(g(a,b),g(b,c),g(a,c),d))}function g(a,b){n[a.index]||(n[a.index]=[]);n[b.index]||(n[b.index]=[]);var c=n[a.index][b.index];void 0===c&&(n[a.index][b.index]=n[b.index][a.index]=c=e((new THREE.Vector3).addVectors(a,b).divideScalar(2)));return c}function h(a,b,c){0>c&&1===a.x&&(a=new THREE.Vector2(a.x-1,a.y));0===b.x&&0===b.z&&(a=new THREE.Vector2(c/2/Math.PI+0.5,a.y));return a}THREE.Geometry.call(this);
 a,d),h(b.uv,b,d),h(c.uv,c,d)])):(d-=1,f(a,g(a,b),g(a,c),d),f(g(a,b),b,g(b,c),d),f(g(a,c),g(b,c),c,d),f(g(a,b),g(b,c),g(a,c),d))}function g(a,b){n[a.index]||(n[a.index]=[]);n[b.index]||(n[b.index]=[]);var c=n[a.index][b.index];void 0===c&&(n[a.index][b.index]=n[b.index][a.index]=c=e((new THREE.Vector3).addVectors(a,b).divideScalar(2)));return c}function h(a,b,c){0>c&&1===a.x&&(a=new THREE.Vector2(a.x-1,a.y));0===b.x&&0===b.z&&(a=new THREE.Vector2(c/2/Math.PI+0.5,a.y));return a}THREE.Geometry.call(this);
-for(var c=c||1,d=d||0,i=this,k=0,l=a.length;k<l;k++)e(new THREE.Vector3(a[k][0],a[k][1],a[k][2]));for(var n=[],a=this.vertices,k=0,l=b.length;k<l;k++)f(a[b[k][0]],a[b[k][1]],a[b[k][2]],d);this.mergeVertices();k=0;for(l=this.vertices.length;k<l;k++)this.vertices[k].multiplyScalar(c);this.computeCentroids();this.boundingSphere=new THREE.Sphere(new THREE.Vector3,c)};THREE.PolyhedronGeometry.prototype=Object.create(THREE.Geometry.prototype);THREE.IcosahedronGeometry=function(a,b){var c=(1+Math.sqrt(5))/2;THREE.PolyhedronGeometry.call(this,[[-1,c,0],[1,c,0],[-1,-c,0],[1,-c,0],[0,-1,c],[0,1,c],[0,-1,-c],[0,1,-c],[c,0,-1],[c,0,1],[-c,0,-1],[-c,0,1]],[[0,11,5],[0,5,1],[0,1,7],[0,7,10],[0,10,11],[1,5,9],[5,11,4],[11,10,2],[10,7,6],[7,1,8],[3,9,4],[3,4,2],[3,2,6],[3,6,8],[3,8,9],[4,9,5],[2,4,11],[6,2,10],[8,6,7],[9,8,1]],a,b)};THREE.IcosahedronGeometry.prototype=Object.create(THREE.Geometry.prototype);THREE.OctahedronGeometry=function(a,b){THREE.PolyhedronGeometry.call(this,[[1,0,0],[-1,0,0],[0,1,0],[0,-1,0],[0,0,1],[0,0,-1]],[[0,2,4],[0,4,3],[0,3,5],[0,5,2],[1,2,5],[1,5,3],[1,3,4],[1,4,2]],a,b)};THREE.OctahedronGeometry.prototype=Object.create(THREE.Geometry.prototype);THREE.TetrahedronGeometry=function(a,b){THREE.PolyhedronGeometry.call(this,[[1,1,1],[-1,-1,1],[-1,1,-1],[1,-1,-1]],[[2,1,0],[0,3,2],[1,3,0],[2,3,1]],a,b)};THREE.TetrahedronGeometry.prototype=Object.create(THREE.Geometry.prototype);THREE.ParametricGeometry=function(a,b,c,d){THREE.Geometry.call(this);var e=this.vertices,f=this.faces,g=this.faceVertexUvs[0],d=void 0===d?!1:d,h,i,k,l,n=b+1;for(h=0;h<=c;h++){l=h/c;for(i=0;i<=b;i++)k=i/b,k=a(k,l),e.push(k)}var m,t,r,p;for(h=0;h<c;h++)for(i=0;i<b;i++)a=h*n+i,e=h*n+i+1,l=(h+1)*n+i,k=(h+1)*n+i+1,m=new THREE.Vector2(i/b,h/c),t=new THREE.Vector2((i+1)/b,h/c),r=new THREE.Vector2(i/b,(h+1)/c),p=new THREE.Vector2((i+1)/b,(h+1)/c),d?(f.push(new THREE.Face3(a,e,l)),f.push(new THREE.Face3(e,
-k,l)),g.push([m,t,r]),g.push([t,p,r])):(f.push(new THREE.Face4(a,e,k,l)),g.push([m,t,p,r]));this.computeCentroids();this.computeFaceNormals();this.computeVertexNormals()};THREE.ParametricGeometry.prototype=Object.create(THREE.Geometry.prototype);THREE.ConvexGeometry=function(a){function b(a){var b=a.length();return new THREE.Vector2(a.x/b,a.y/b)}THREE.Geometry.call(this);for(var c=[[0,1,2],[0,2,1]],d=3;d<a.length;d++){var e=d,f=a[e].clone(),g=f.length();f.x+=g*2E-6*(Math.random()-0.5);f.y+=g*2E-6*(Math.random()-0.5);f.z+=g*2E-6*(Math.random()-0.5);for(var g=[],h=0;h<c.length;){var i=c[h],k=f,l=a[i[0]],n;n=l;var m=a[i[1]],t=a[i[2]],r=new THREE.Vector3,p=new THREE.Vector3;r.subVectors(t,m);p.subVectors(n,m);r.cross(p);r.normalize();n=r;l=n.dot(l);
-if(n.dot(k)>=l){for(k=0;3>k;k++){l=[i[k],i[(k+1)%3]];n=!0;for(m=0;m<g.length;m++)if(g[m][0]===l[1]&&g[m][1]===l[0]){g[m]=g[g.length-1];g.pop();n=!1;break}n&&g.push(l)}c[h]=c[c.length-1];c.pop()}else h++}for(m=0;m<g.length;m++)c.push([g[m][0],g[m][1],e])}e=0;f=Array(a.length);for(d=0;d<c.length;d++){g=c[d];for(h=0;3>h;h++)void 0===f[g[h]]&&(f[g[h]]=e++,this.vertices.push(a[g[h]])),g[h]=f[g[h]]}for(d=0;d<c.length;d++)this.faces.push(new THREE.Face3(c[d][0],c[d][1],c[d][2]));for(d=0;d<this.faces.length;d++)g=
+for(var c=c||1,d=d||0,i=this,j=0,l=a.length;j<l;j++)e(new THREE.Vector3(a[j][0],a[j][1],a[j][2]));for(var n=[],a=this.vertices,j=0,l=b.length;j<l;j++)f(a[b[j][0]],a[b[j][1]],a[b[j][2]],d);this.mergeVertices();j=0;for(l=this.vertices.length;j<l;j++)this.vertices[j].multiplyScalar(c);this.computeCentroids();this.boundingSphere=new THREE.Sphere(new THREE.Vector3,c)};THREE.PolyhedronGeometry.prototype=Object.create(THREE.Geometry.prototype);THREE.IcosahedronGeometry=function(a,b){var c=(1+Math.sqrt(5))/2;THREE.PolyhedronGeometry.call(this,[[-1,c,0],[1,c,0],[-1,-c,0],[1,-c,0],[0,-1,c],[0,1,c],[0,-1,-c],[0,1,-c],[c,0,-1],[c,0,1],[-c,0,-1],[-c,0,1]],[[0,11,5],[0,5,1],[0,1,7],[0,7,10],[0,10,11],[1,5,9],[5,11,4],[11,10,2],[10,7,6],[7,1,8],[3,9,4],[3,4,2],[3,2,6],[3,6,8],[3,8,9],[4,9,5],[2,4,11],[6,2,10],[8,6,7],[9,8,1]],a,b)};THREE.IcosahedronGeometry.prototype=Object.create(THREE.Geometry.prototype);THREE.OctahedronGeometry=function(a,b){THREE.PolyhedronGeometry.call(this,[[1,0,0],[-1,0,0],[0,1,0],[0,-1,0],[0,0,1],[0,0,-1]],[[0,2,4],[0,4,3],[0,3,5],[0,5,2],[1,2,5],[1,5,3],[1,3,4],[1,4,2]],a,b)};THREE.OctahedronGeometry.prototype=Object.create(THREE.Geometry.prototype);THREE.TetrahedronGeometry=function(a,b){THREE.PolyhedronGeometry.call(this,[[1,1,1],[-1,-1,1],[-1,1,-1],[1,-1,-1]],[[2,1,0],[0,3,2],[1,3,0],[2,3,1]],a,b)};THREE.TetrahedronGeometry.prototype=Object.create(THREE.Geometry.prototype);THREE.ParametricGeometry=function(a,b,c,d){THREE.Geometry.call(this);var e=this.vertices,f=this.faces,g=this.faceVertexUvs[0],d=void 0===d?!1:d,h,i,j,l,n=b+1;for(h=0;h<=c;h++){l=h/c;for(i=0;i<=b;i++)j=i/b,j=a(j,l),e.push(j)}var m,r,u,p;for(h=0;h<c;h++)for(i=0;i<b;i++)a=h*n+i,e=h*n+i+1,l=(h+1)*n+i,j=(h+1)*n+i+1,m=new THREE.Vector2(i/b,h/c),r=new THREE.Vector2((i+1)/b,h/c),u=new THREE.Vector2(i/b,(h+1)/c),p=new THREE.Vector2((i+1)/b,(h+1)/c),d?(f.push(new THREE.Face3(a,e,l)),f.push(new THREE.Face3(e,
+j,l)),g.push([m,r,u]),g.push([r,p,u])):(f.push(new THREE.Face4(a,e,j,l)),g.push([m,r,p,u]));this.computeCentroids();this.computeFaceNormals();this.computeVertexNormals()};THREE.ParametricGeometry.prototype=Object.create(THREE.Geometry.prototype);THREE.ConvexGeometry=function(a){function b(a){var b=a.length();return new THREE.Vector2(a.x/b,a.y/b)}THREE.Geometry.call(this);for(var c=[[0,1,2],[0,2,1]],d=3;d<a.length;d++){var e=d,f=a[e].clone(),g=f.length();f.x+=g*2E-6*(Math.random()-0.5);f.y+=g*2E-6*(Math.random()-0.5);f.z+=g*2E-6*(Math.random()-0.5);for(var g=[],h=0;h<c.length;){var i=c[h],j=f,l=a[i[0]],n;n=l;var m=a[i[1]],r=a[i[2]],u=new THREE.Vector3,p=new THREE.Vector3;u.subVectors(r,m);p.subVectors(n,m);u.cross(p);u.normalize();n=u;l=n.dot(l);
+if(n.dot(j)>=l){for(j=0;3>j;j++){l=[i[j],i[(j+1)%3]];n=!0;for(m=0;m<g.length;m++)if(g[m][0]===l[1]&&g[m][1]===l[0]){g[m]=g[g.length-1];g.pop();n=!1;break}n&&g.push(l)}c[h]=c[c.length-1];c.pop()}else h++}for(m=0;m<g.length;m++)c.push([g[m][0],g[m][1],e])}e=0;f=Array(a.length);for(d=0;d<c.length;d++){g=c[d];for(h=0;3>h;h++)void 0===f[g[h]]&&(f[g[h]]=e++,this.vertices.push(a[g[h]])),g[h]=f[g[h]]}for(d=0;d<c.length;d++)this.faces.push(new THREE.Face3(c[d][0],c[d][1],c[d][2]));for(d=0;d<this.faces.length;d++)g=
 this.faces[d],this.faceVertexUvs[0].push([b(this.vertices[g.a]),b(this.vertices[g.b]),b(this.vertices[g.c])]);this.computeCentroids();this.computeFaceNormals();this.computeVertexNormals()};THREE.ConvexGeometry.prototype=Object.create(THREE.Geometry.prototype);THREE.AxisHelper=function(a){var b=new THREE.Geometry;b.vertices.push(new THREE.Vector3,new THREE.Vector3(a||1,0,0),new THREE.Vector3,new THREE.Vector3(0,a||1,0),new THREE.Vector3,new THREE.Vector3(0,0,a||1));b.colors.push(new THREE.Color(16711680),new THREE.Color(16755200),new THREE.Color(65280),new THREE.Color(11206400),new THREE.Color(255),new THREE.Color(43775));a=new THREE.LineBasicMaterial({vertexColors:THREE.VertexColors});THREE.Line.call(this,b,a,THREE.LinePieces)};
 this.faces[d],this.faceVertexUvs[0].push([b(this.vertices[g.a]),b(this.vertices[g.b]),b(this.vertices[g.c])]);this.computeCentroids();this.computeFaceNormals();this.computeVertexNormals()};THREE.ConvexGeometry.prototype=Object.create(THREE.Geometry.prototype);THREE.AxisHelper=function(a){var b=new THREE.Geometry;b.vertices.push(new THREE.Vector3,new THREE.Vector3(a||1,0,0),new THREE.Vector3,new THREE.Vector3(0,a||1,0),new THREE.Vector3,new THREE.Vector3(0,0,a||1));b.colors.push(new THREE.Color(16711680),new THREE.Color(16755200),new THREE.Color(65280),new THREE.Color(11206400),new THREE.Color(255),new THREE.Color(43775));a=new THREE.LineBasicMaterial({vertexColors:THREE.VertexColors});THREE.Line.call(this,b,a,THREE.LinePieces)};
 THREE.AxisHelper.prototype=Object.create(THREE.Line.prototype);THREE.ArrowHelper=function(a,b,c,d){THREE.Object3D.call(this);void 0===c&&(c=20);void 0===d&&(d=16776960);var e=new THREE.Geometry;e.vertices.push(new THREE.Vector3(0,0,0));e.vertices.push(new THREE.Vector3(0,1,0));this.line=new THREE.Line(e,new THREE.LineBasicMaterial({color:d}));this.add(this.line);e=new THREE.CylinderGeometry(0,0.05,0.25,5,1);this.cone=new THREE.Mesh(e,new THREE.MeshBasicMaterial({color:d}));this.cone.position.set(0,1,0);this.add(this.cone);b instanceof THREE.Vector3&&(this.position=
 THREE.AxisHelper.prototype=Object.create(THREE.Line.prototype);THREE.ArrowHelper=function(a,b,c,d){THREE.Object3D.call(this);void 0===c&&(c=20);void 0===d&&(d=16776960);var e=new THREE.Geometry;e.vertices.push(new THREE.Vector3(0,0,0));e.vertices.push(new THREE.Vector3(0,1,0));this.line=new THREE.Line(e,new THREE.LineBasicMaterial({color:d}));this.add(this.line);e=new THREE.CylinderGeometry(0,0.05,0.25,5,1);this.cone=new THREE.Mesh(e,new THREE.MeshBasicMaterial({color:d}));this.cone.position.set(0,1,0);this.add(this.cone);b instanceof THREE.Vector3&&(this.position=
 b);this.setDirection(a);this.setLength(c)};THREE.ArrowHelper.prototype=Object.create(THREE.Object3D.prototype);THREE.ArrowHelper.prototype.setDirection=function(a){var b=THREE.ArrowHelper.__v1.copy(a).normalize();0.999<b.y?this.rotation.set(0,0,0):-0.999>b.y?this.rotation.set(Math.PI,0,0):(a=THREE.ArrowHelper.__v2.set(b.z,0,-b.x).normalize(),b=Math.acos(b.y),a=THREE.ArrowHelper.__q1.setFromAxisAngle(a,b),this.rotation.setEulerFromQuaternion(a,this.eulerOrder))};
 b);this.setDirection(a);this.setLength(c)};THREE.ArrowHelper.prototype=Object.create(THREE.Object3D.prototype);THREE.ArrowHelper.prototype.setDirection=function(a){var b=THREE.ArrowHelper.__v1.copy(a).normalize();0.999<b.y?this.rotation.set(0,0,0):-0.999>b.y?this.rotation.set(Math.PI,0,0):(a=THREE.ArrowHelper.__v2.set(b.z,0,-b.x).normalize(),b=Math.acos(b.y),a=THREE.ArrowHelper.__q1.setFromAxisAngle(a,b),this.rotation.setEulerFromQuaternion(a,this.eulerOrder))};
@@ -645,7 +645,7 @@ new THREE.Mesh(d,f);this.lightRays=new THREE.Line(e,g,THREE.LinePieces);this.add
 !0,this.targetSphere.properties.gizmoSubject=a.target,this.targetSphere.properties.gizmoRoot=this.targetSphere,c=new THREE.LineDashedMaterial({color:c,dashSize:4,gapSize:4,opacity:0.75,transparent:!0,fog:!1}),d=new THREE.Geometry,d.vertices.push(this.position.clone()),d.vertices.push(this.targetSphere.position.clone()),d.computeLineDistances(),this.targetLine=new THREE.Line(d,c),this.targetLine.properties.isGizmo=!0);this.properties.isGizmo=!0};THREE.DirectionalLightHelper.prototype=Object.create(THREE.Object3D.prototype);
 !0,this.targetSphere.properties.gizmoSubject=a.target,this.targetSphere.properties.gizmoRoot=this.targetSphere,c=new THREE.LineDashedMaterial({color:c,dashSize:4,gapSize:4,opacity:0.75,transparent:!0,fog:!1}),d=new THREE.Geometry,d.vertices.push(this.position.clone()),d.vertices.push(this.targetSphere.position.clone()),d.computeLineDistances(),this.targetLine=new THREE.Line(d,c),this.targetLine.properties.isGizmo=!0);this.properties.isGizmo=!0};THREE.DirectionalLightHelper.prototype=Object.create(THREE.Object3D.prototype);
 THREE.DirectionalLightHelper.prototype.update=function(){this.direction.subVectors(this.light.target.position,this.light.position);var a=THREE.Math.clamp(this.light.intensity,0,1);this.color.copy(this.light.color);this.color.multiplyScalar(a);this.lightSphere.material.color.copy(this.color);this.lightRays.material.color.copy(this.color);null!==this.targetSphere&&(this.targetSphere.material.color.copy(this.color),this.targetLine.material.color.copy(this.color),this.targetLine.geometry.vertices[0].copy(this.light.position),
 THREE.DirectionalLightHelper.prototype.update=function(){this.direction.subVectors(this.light.target.position,this.light.position);var a=THREE.Math.clamp(this.light.intensity,0,1);this.color.copy(this.light.color);this.color.multiplyScalar(a);this.lightSphere.material.color.copy(this.color);this.lightRays.material.color.copy(this.color);null!==this.targetSphere&&(this.targetSphere.material.color.copy(this.color),this.targetLine.material.color.copy(this.color),this.targetLine.geometry.vertices[0].copy(this.light.position),
 this.targetLine.geometry.vertices[1].copy(this.light.target.position),this.targetLine.geometry.computeLineDistances(),this.targetLine.geometry.verticesNeedUpdate=!0)};THREE.HemisphereLightHelper=function(a,b,c){THREE.Object3D.call(this);this.light=a;this.position=a.position;var d=THREE.Math.clamp(a.intensity,0,1);this.color=a.color.clone();this.color.multiplyScalar(d);var e=this.color.getHex();this.groundColor=a.groundColor.clone();this.groundColor.multiplyScalar(d);for(var d=this.groundColor.getHex(),f=new THREE.SphereGeometry(b,16,8,0,2*Math.PI,0,0.5*Math.PI),g=new THREE.SphereGeometry(b,16,8,0,2*Math.PI,0.5*Math.PI,Math.PI),h=new THREE.MeshBasicMaterial({color:e,
 this.targetLine.geometry.vertices[1].copy(this.light.target.position),this.targetLine.geometry.computeLineDistances(),this.targetLine.geometry.verticesNeedUpdate=!0)};THREE.HemisphereLightHelper=function(a,b,c){THREE.Object3D.call(this);this.light=a;this.position=a.position;var d=THREE.Math.clamp(a.intensity,0,1);this.color=a.color.clone();this.color.multiplyScalar(d);var e=this.color.getHex();this.groundColor=a.groundColor.clone();this.groundColor.multiplyScalar(d);for(var d=this.groundColor.getHex(),f=new THREE.SphereGeometry(b,16,8,0,2*Math.PI,0,0.5*Math.PI),g=new THREE.SphereGeometry(b,16,8,0,2*Math.PI,0.5*Math.PI,Math.PI),h=new THREE.MeshBasicMaterial({color:e,
-fog:!1}),i=new THREE.MeshBasicMaterial({color:d,fog:!1}),k=0,l=f.faces.length;k<l;k++)f.faces[k].materialIndex=0;k=0;for(l=g.faces.length;k<l;k++)g.faces[k].materialIndex=1;THREE.GeometryUtils.merge(f,g);this.lightSphere=new THREE.Mesh(f,new THREE.MeshFaceMaterial([h,i]));this.lightArrow=new THREE.ArrowHelper(new THREE.Vector3(0,1,0),new THREE.Vector3(0,1.1*(b+c),0),c,e);this.lightArrow.rotation.x=Math.PI;this.lightArrowGround=new THREE.ArrowHelper(new THREE.Vector3(0,1,0),new THREE.Vector3(0,-1.1*
+fog:!1}),i=new THREE.MeshBasicMaterial({color:d,fog:!1}),j=0,l=f.faces.length;j<l;j++)f.faces[j].materialIndex=0;j=0;for(l=g.faces.length;j<l;j++)g.faces[j].materialIndex=1;THREE.GeometryUtils.merge(f,g);this.lightSphere=new THREE.Mesh(f,new THREE.MeshFaceMaterial([h,i]));this.lightArrow=new THREE.ArrowHelper(new THREE.Vector3(0,1,0),new THREE.Vector3(0,1.1*(b+c),0),c,e);this.lightArrow.rotation.x=Math.PI;this.lightArrowGround=new THREE.ArrowHelper(new THREE.Vector3(0,1,0),new THREE.Vector3(0,-1.1*
 (b+c),0),c,d);b=new THREE.Object3D;b.rotation.x=0.5*-Math.PI;b.add(this.lightSphere);b.add(this.lightArrow);b.add(this.lightArrowGround);this.add(b);this.lightSphere.properties.isGizmo=!0;this.lightSphere.properties.gizmoSubject=a;this.lightSphere.properties.gizmoRoot=this;this.properties.isGizmo=!0;this.target=new THREE.Vector3;this.lookAt(this.target)};THREE.HemisphereLightHelper.prototype=Object.create(THREE.Object3D.prototype);
 (b+c),0),c,d);b=new THREE.Object3D;b.rotation.x=0.5*-Math.PI;b.add(this.lightSphere);b.add(this.lightArrow);b.add(this.lightArrowGround);this.add(b);this.lightSphere.properties.isGizmo=!0;this.lightSphere.properties.gizmoSubject=a;this.lightSphere.properties.gizmoRoot=this;this.properties.isGizmo=!0;this.target=new THREE.Vector3;this.lookAt(this.target)};THREE.HemisphereLightHelper.prototype=Object.create(THREE.Object3D.prototype);
 THREE.HemisphereLightHelper.prototype.update=function(){var a=THREE.Math.clamp(this.light.intensity,0,1);this.color.copy(this.light.color);this.color.multiplyScalar(a);this.groundColor.copy(this.light.groundColor);this.groundColor.multiplyScalar(a);this.lightSphere.material.materials[0].color.copy(this.color);this.lightSphere.material.materials[1].color.copy(this.groundColor);this.lightArrow.setColor(this.color.getHex());this.lightArrowGround.setColor(this.groundColor.getHex());this.lookAt(this.target)};THREE.PointLightHelper=function(a,b){THREE.Object3D.call(this);this.light=a;this.position=a.position;var c=THREE.Math.clamp(a.intensity,0,1);this.color=a.color.clone();this.color.multiplyScalar(c);var d=this.color.getHex(),c=new THREE.SphereGeometry(b,16,8),e=new THREE.AsteriskGeometry(1.25*b,2.25*b),f=new THREE.IcosahedronGeometry(1,2),g=new THREE.MeshBasicMaterial({color:d,fog:!1}),h=new THREE.LineBasicMaterial({color:d,fog:!1}),d=new THREE.MeshBasicMaterial({color:d,fog:!1,wireframe:!0,opacity:0.1,
 THREE.HemisphereLightHelper.prototype.update=function(){var a=THREE.Math.clamp(this.light.intensity,0,1);this.color.copy(this.light.color);this.color.multiplyScalar(a);this.groundColor.copy(this.light.groundColor);this.groundColor.multiplyScalar(a);this.lightSphere.material.materials[0].color.copy(this.color);this.lightSphere.material.materials[1].color.copy(this.groundColor);this.lightArrow.setColor(this.color.getHex());this.lightArrowGround.setColor(this.groundColor.getHex());this.lookAt(this.target)};THREE.PointLightHelper=function(a,b){THREE.Object3D.call(this);this.light=a;this.position=a.position;var c=THREE.Math.clamp(a.intensity,0,1);this.color=a.color.clone();this.color.multiplyScalar(c);var d=this.color.getHex(),c=new THREE.SphereGeometry(b,16,8),e=new THREE.AsteriskGeometry(1.25*b,2.25*b),f=new THREE.IcosahedronGeometry(1,2),g=new THREE.MeshBasicMaterial({color:d,fog:!1}),h=new THREE.LineBasicMaterial({color:d,fog:!1}),d=new THREE.MeshBasicMaterial({color:d,fog:!1,wireframe:!0,opacity:0.1,
 transparent:!0});this.lightSphere=new THREE.Mesh(c,g);this.lightRays=new THREE.Line(e,h,THREE.LinePieces);this.lightDistance=new THREE.Mesh(f,d);c=a.distance;0===c?this.lightDistance.visible=!1:this.lightDistance.scale.set(c,c,c);this.add(this.lightSphere);this.add(this.lightRays);this.add(this.lightDistance);this.lightSphere.properties.isGizmo=!0;this.lightSphere.properties.gizmoSubject=a;this.lightSphere.properties.gizmoRoot=this;this.properties.isGizmo=!0};THREE.PointLightHelper.prototype=Object.create(THREE.Object3D.prototype);
 transparent:!0});this.lightSphere=new THREE.Mesh(c,g);this.lightRays=new THREE.Line(e,h,THREE.LinePieces);this.lightDistance=new THREE.Mesh(f,d);c=a.distance;0===c?this.lightDistance.visible=!1:this.lightDistance.scale.set(c,c,c);this.add(this.lightSphere);this.add(this.lightRays);this.add(this.lightDistance);this.lightSphere.properties.isGizmo=!0;this.lightSphere.properties.gizmoSubject=a;this.lightSphere.properties.gizmoRoot=this;this.properties.isGizmo=!0};THREE.PointLightHelper.prototype=Object.create(THREE.Object3D.prototype);
@@ -663,38 +663,38 @@ THREE.MorphBlendMesh.prototype.setAnimationDirectionForward=function(a){if(a=thi
 THREE.MorphBlendMesh.prototype.setAnimationDuration=function(a,b){var c=this.animationsMap[a];c&&(c.duration=b,c.fps=(c.end-c.start)/c.duration)};THREE.MorphBlendMesh.prototype.setAnimationWeight=function(a,b){var c=this.animationsMap[a];c&&(c.weight=b)};THREE.MorphBlendMesh.prototype.setAnimationTime=function(a,b){var c=this.animationsMap[a];c&&(c.time=b)};THREE.MorphBlendMesh.prototype.getAnimationTime=function(a){var b=0;if(a=this.animationsMap[a])b=a.time;return b};
 THREE.MorphBlendMesh.prototype.setAnimationDuration=function(a,b){var c=this.animationsMap[a];c&&(c.duration=b,c.fps=(c.end-c.start)/c.duration)};THREE.MorphBlendMesh.prototype.setAnimationWeight=function(a,b){var c=this.animationsMap[a];c&&(c.weight=b)};THREE.MorphBlendMesh.prototype.setAnimationTime=function(a,b){var c=this.animationsMap[a];c&&(c.time=b)};THREE.MorphBlendMesh.prototype.getAnimationTime=function(a){var b=0;if(a=this.animationsMap[a])b=a.time;return b};
 THREE.MorphBlendMesh.prototype.getAnimationDuration=function(a){var b=-1;if(a=this.animationsMap[a])b=a.duration;return b};THREE.MorphBlendMesh.prototype.playAnimation=function(a){var b=this.animationsMap[a];b?(b.time=0,b.active=!0):console.warn("animation["+a+"] undefined")};THREE.MorphBlendMesh.prototype.stopAnimation=function(a){if(a=this.animationsMap[a])a.active=!1};
 THREE.MorphBlendMesh.prototype.getAnimationDuration=function(a){var b=-1;if(a=this.animationsMap[a])b=a.duration;return b};THREE.MorphBlendMesh.prototype.playAnimation=function(a){var b=this.animationsMap[a];b?(b.time=0,b.active=!0):console.warn("animation["+a+"] undefined")};THREE.MorphBlendMesh.prototype.stopAnimation=function(a){if(a=this.animationsMap[a])a.active=!1};
 THREE.MorphBlendMesh.prototype.update=function(a){for(var b=0,c=this.animationsList.length;b<c;b++){var d=this.animationsList[b];if(d.active){var e=d.duration/d.length;d.time+=d.direction*a;if(d.mirroredLoop){if(d.time>d.duration||0>d.time)d.direction*=-1,d.time>d.duration&&(d.time=d.duration,d.directionBackwards=!0),0>d.time&&(d.time=0,d.directionBackwards=!1)}else d.time%=d.duration,0>d.time&&(d.time+=d.duration);var f=d.startFrame+THREE.Math.clamp(Math.floor(d.time/e),0,d.length-1),g=d.weight;
 THREE.MorphBlendMesh.prototype.update=function(a){for(var b=0,c=this.animationsList.length;b<c;b++){var d=this.animationsList[b];if(d.active){var e=d.duration/d.length;d.time+=d.direction*a;if(d.mirroredLoop){if(d.time>d.duration||0>d.time)d.direction*=-1,d.time>d.duration&&(d.time=d.duration,d.directionBackwards=!0),0>d.time&&(d.time=0,d.directionBackwards=!1)}else d.time%=d.duration,0>d.time&&(d.time+=d.duration);var f=d.startFrame+THREE.Math.clamp(Math.floor(d.time/e),0,d.length-1),g=d.weight;
-f!==d.currentFrame&&(this.morphTargetInfluences[d.lastFrame]=0,this.morphTargetInfluences[d.currentFrame]=1*g,this.morphTargetInfluences[f]=0,d.lastFrame=d.currentFrame,d.currentFrame=f);e=d.time%e/e;d.directionBackwards&&(e=1-e);this.morphTargetInfluences[d.currentFrame]=e*g;this.morphTargetInfluences[d.lastFrame]=(1-e)*g}}};THREE.LensFlarePlugin=function(){function a(a,c){var d=b.createProgram(),e=b.createShader(b.FRAGMENT_SHADER),f=b.createShader(b.VERTEX_SHADER),g="precision "+c+" float;\n";b.shaderSource(e,g+a.fragmentShader);b.shaderSource(f,g+a.vertexShader);b.compileShader(e);b.compileShader(f);b.attachShader(d,e);b.attachShader(d,f);b.linkProgram(d);return d}var b,c,d,e,f,g,h,i,k,l,n,m,t;this.init=function(r){b=r.context;c=r;d=r.getPrecision();e=new Float32Array(16);f=new Uint16Array(6);r=0;e[r++]=-1;e[r++]=-1;
-e[r++]=0;e[r++]=0;e[r++]=1;e[r++]=-1;e[r++]=1;e[r++]=0;e[r++]=1;e[r++]=1;e[r++]=1;e[r++]=1;e[r++]=-1;e[r++]=1;e[r++]=0;e[r++]=1;r=0;f[r++]=0;f[r++]=1;f[r++]=2;f[r++]=0;f[r++]=2;f[r++]=3;g=b.createBuffer();h=b.createBuffer();b.bindBuffer(b.ARRAY_BUFFER,g);b.bufferData(b.ARRAY_BUFFER,e,b.STATIC_DRAW);b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,h);b.bufferData(b.ELEMENT_ARRAY_BUFFER,f,b.STATIC_DRAW);i=b.createTexture();k=b.createTexture();b.bindTexture(b.TEXTURE_2D,i);b.texImage2D(b.TEXTURE_2D,0,b.RGB,16,16,
-0,b.RGB,b.UNSIGNED_BYTE,null);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_S,b.CLAMP_TO_EDGE);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_T,b.CLAMP_TO_EDGE);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MAG_FILTER,b.NEAREST);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MIN_FILTER,b.NEAREST);b.bindTexture(b.TEXTURE_2D,k);b.texImage2D(b.TEXTURE_2D,0,b.RGBA,16,16,0,b.RGBA,b.UNSIGNED_BYTE,null);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_S,b.CLAMP_TO_EDGE);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_T,b.CLAMP_TO_EDGE);
-b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MAG_FILTER,b.NEAREST);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MIN_FILTER,b.NEAREST);0>=b.getParameter(b.MAX_VERTEX_TEXTURE_IMAGE_UNITS)?(l=!1,n=a(THREE.ShaderFlares.lensFlare,d)):(l=!0,n=a(THREE.ShaderFlares.lensFlareVertexTexture,d));m={};t={};m.vertex=b.getAttribLocation(n,"position");m.uv=b.getAttribLocation(n,"uv");t.renderType=b.getUniformLocation(n,"renderType");t.map=b.getUniformLocation(n,"map");t.occlusionMap=b.getUniformLocation(n,"occlusionMap");t.opacity=
-b.getUniformLocation(n,"opacity");t.color=b.getUniformLocation(n,"color");t.scale=b.getUniformLocation(n,"scale");t.rotation=b.getUniformLocation(n,"rotation");t.screenPosition=b.getUniformLocation(n,"screenPosition")};this.render=function(a,d,e,f){var a=a.__webglFlares,v=a.length;if(v){var z=new THREE.Vector3,s=f/e,C=0.5*e,H=0.5*f,B=16/f,w=new THREE.Vector2(B*s,B),I=new THREE.Vector3(1,1,0),J=new THREE.Vector2(1,1),E=t,B=m;b.useProgram(n);b.enableVertexAttribArray(m.vertex);b.enableVertexAttribArray(m.uv);
-b.uniform1i(E.occlusionMap,0);b.uniform1i(E.map,1);b.bindBuffer(b.ARRAY_BUFFER,g);b.vertexAttribPointer(B.vertex,2,b.FLOAT,!1,16,0);b.vertexAttribPointer(B.uv,2,b.FLOAT,!1,16,8);b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,h);b.disable(b.CULL_FACE);b.depthMask(!1);var Z,A,U,F,G;for(Z=0;Z<v;Z++)if(B=16/f,w.set(B*s,B),F=a[Z],z.set(F.matrixWorld.elements[12],F.matrixWorld.elements[13],F.matrixWorld.elements[14]),z.applyMatrix4(d.matrixWorldInverse),z.applyProjection(d.projectionMatrix),I.copy(z),J.x=I.x*C+C,
-J.y=I.y*H+H,l||0<J.x&&J.x<e&&0<J.y&&J.y<f){b.activeTexture(b.TEXTURE1);b.bindTexture(b.TEXTURE_2D,i);b.copyTexImage2D(b.TEXTURE_2D,0,b.RGB,J.x-8,J.y-8,16,16,0);b.uniform1i(E.renderType,0);b.uniform2f(E.scale,w.x,w.y);b.uniform3f(E.screenPosition,I.x,I.y,I.z);b.disable(b.BLEND);b.enable(b.DEPTH_TEST);b.drawElements(b.TRIANGLES,6,b.UNSIGNED_SHORT,0);b.activeTexture(b.TEXTURE0);b.bindTexture(b.TEXTURE_2D,k);b.copyTexImage2D(b.TEXTURE_2D,0,b.RGBA,J.x-8,J.y-8,16,16,0);b.uniform1i(E.renderType,1);b.disable(b.DEPTH_TEST);
-b.activeTexture(b.TEXTURE1);b.bindTexture(b.TEXTURE_2D,i);b.drawElements(b.TRIANGLES,6,b.UNSIGNED_SHORT,0);F.positionScreen.copy(I);F.customUpdateCallback?F.customUpdateCallback(F):F.updateLensFlares();b.uniform1i(E.renderType,2);b.enable(b.BLEND);A=0;for(U=F.lensFlares.length;A<U;A++)G=F.lensFlares[A],0.001<G.opacity&&0.001<G.scale&&(I.x=G.x,I.y=G.y,I.z=G.z,B=G.size*G.scale/f,w.x=B*s,w.y=B,b.uniform3f(E.screenPosition,I.x,I.y,I.z),b.uniform2f(E.scale,w.x,w.y),b.uniform1f(E.rotation,G.rotation),b.uniform1f(E.opacity,
-G.opacity),b.uniform3f(E.color,G.color.r,G.color.g,G.color.b),c.setBlending(G.blending,G.blendEquation,G.blendSrc,G.blendDst),c.setTexture(G.texture,1),b.drawElements(b.TRIANGLES,6,b.UNSIGNED_SHORT,0))}b.enable(b.CULL_FACE);b.enable(b.DEPTH_TEST);b.depthMask(!0)}}};THREE.ShadowMapPlugin=function(){var a,b,c,d,e,f,g=new THREE.Frustum,h=new THREE.Matrix4,i=new THREE.Vector3,k=new THREE.Vector3,l=new THREE.Vector3;this.init=function(g){a=g.context;b=g;var g=THREE.ShaderLib.depthRGBA,i=THREE.UniformsUtils.clone(g.uniforms);c=new THREE.ShaderMaterial({fragmentShader:g.fragmentShader,vertexShader:g.vertexShader,uniforms:i});d=new THREE.ShaderMaterial({fragmentShader:g.fragmentShader,vertexShader:g.vertexShader,uniforms:i,morphTargets:!0});e=new THREE.ShaderMaterial({fragmentShader:g.fragmentShader,
-vertexShader:g.vertexShader,uniforms:i,skinning:!0});f=new THREE.ShaderMaterial({fragmentShader:g.fragmentShader,vertexShader:g.vertexShader,uniforms:i,morphTargets:!0,skinning:!0});c._shadowPass=!0;d._shadowPass=!0;e._shadowPass=!0;f._shadowPass=!0};this.render=function(a,c){b.shadowMapEnabled&&b.shadowMapAutoUpdate&&this.update(a,c)};this.update=function(n,m){var t,r,p,q,y,v,z,s,C,H=[];q=0;a.clearColor(1,1,1,1);a.disable(a.BLEND);a.enable(a.CULL_FACE);a.frontFace(a.CCW);b.shadowMapCullFace===THREE.CullFaceFront?
-a.cullFace(a.FRONT):a.cullFace(a.BACK);b.setDepthTest(!0);t=0;for(r=n.__lights.length;t<r;t++)if(p=n.__lights[t],p.castShadow)if(p instanceof THREE.DirectionalLight&&p.shadowCascade)for(y=0;y<p.shadowCascadeCount;y++){var B;if(p.shadowCascadeArray[y])B=p.shadowCascadeArray[y];else{C=p;z=y;B=new THREE.DirectionalLight;B.isVirtual=!0;B.onlyShadow=!0;B.castShadow=!0;B.shadowCameraNear=C.shadowCameraNear;B.shadowCameraFar=C.shadowCameraFar;B.shadowCameraLeft=C.shadowCameraLeft;B.shadowCameraRight=C.shadowCameraRight;
-B.shadowCameraBottom=C.shadowCameraBottom;B.shadowCameraTop=C.shadowCameraTop;B.shadowCameraVisible=C.shadowCameraVisible;B.shadowDarkness=C.shadowDarkness;B.shadowBias=C.shadowCascadeBias[z];B.shadowMapWidth=C.shadowCascadeWidth[z];B.shadowMapHeight=C.shadowCascadeHeight[z];B.pointsWorld=[];B.pointsFrustum=[];s=B.pointsWorld;v=B.pointsFrustum;for(var w=0;8>w;w++)s[w]=new THREE.Vector3,v[w]=new THREE.Vector3;s=C.shadowCascadeNearZ[z];C=C.shadowCascadeFarZ[z];v[0].set(-1,-1,s);v[1].set(1,-1,s);v[2].set(-1,
-1,s);v[3].set(1,1,s);v[4].set(-1,-1,C);v[5].set(1,-1,C);v[6].set(-1,1,C);v[7].set(1,1,C);B.originalCamera=m;v=new THREE.Gyroscope;v.position=p.shadowCascadeOffset;v.add(B);v.add(B.target);m.add(v);p.shadowCascadeArray[y]=B;console.log("Created virtualLight",B)}z=p;s=y;C=z.shadowCascadeArray[s];C.position.copy(z.position);C.target.position.copy(z.target.position);C.lookAt(C.target);C.shadowCameraVisible=z.shadowCameraVisible;C.shadowDarkness=z.shadowDarkness;C.shadowBias=z.shadowCascadeBias[s];v=z.shadowCascadeNearZ[s];
-z=z.shadowCascadeFarZ[s];C=C.pointsFrustum;C[0].z=v;C[1].z=v;C[2].z=v;C[3].z=v;C[4].z=z;C[5].z=z;C[6].z=z;C[7].z=z;H[q]=B;q++}else H[q]=p,q++;t=0;for(r=H.length;t<r;t++){p=H[t];p.shadowMap||(y=THREE.LinearFilter,b.shadowMapType===THREE.PCFSoftShadowMap&&(y=THREE.NearestFilter),p.shadowMap=new THREE.WebGLRenderTarget(p.shadowMapWidth,p.shadowMapHeight,{minFilter:y,magFilter:y,format:THREE.RGBAFormat}),p.shadowMapSize=new THREE.Vector2(p.shadowMapWidth,p.shadowMapHeight),p.shadowMatrix=new THREE.Matrix4);
+f!==d.currentFrame&&(this.morphTargetInfluences[d.lastFrame]=0,this.morphTargetInfluences[d.currentFrame]=1*g,this.morphTargetInfluences[f]=0,d.lastFrame=d.currentFrame,d.currentFrame=f);e=d.time%e/e;d.directionBackwards&&(e=1-e);this.morphTargetInfluences[d.currentFrame]=e*g;this.morphTargetInfluences[d.lastFrame]=(1-e)*g}}};THREE.LensFlarePlugin=function(){function a(a,c){var d=b.createProgram(),e=b.createShader(b.FRAGMENT_SHADER),f=b.createShader(b.VERTEX_SHADER),g="precision "+c+" float;\n";b.shaderSource(e,g+a.fragmentShader);b.shaderSource(f,g+a.vertexShader);b.compileShader(e);b.compileShader(f);b.attachShader(d,e);b.attachShader(d,f);b.linkProgram(d);return d}var b,c,d,e,f,g,h,i,j,l,n,m,r;this.init=function(u){b=u.context;c=u;d=u.getPrecision();e=new Float32Array(16);f=new Uint16Array(6);u=0;e[u++]=-1;e[u++]=-1;
+e[u++]=0;e[u++]=0;e[u++]=1;e[u++]=-1;e[u++]=1;e[u++]=0;e[u++]=1;e[u++]=1;e[u++]=1;e[u++]=1;e[u++]=-1;e[u++]=1;e[u++]=0;e[u++]=1;u=0;f[u++]=0;f[u++]=1;f[u++]=2;f[u++]=0;f[u++]=2;f[u++]=3;g=b.createBuffer();h=b.createBuffer();b.bindBuffer(b.ARRAY_BUFFER,g);b.bufferData(b.ARRAY_BUFFER,e,b.STATIC_DRAW);b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,h);b.bufferData(b.ELEMENT_ARRAY_BUFFER,f,b.STATIC_DRAW);i=b.createTexture();j=b.createTexture();b.bindTexture(b.TEXTURE_2D,i);b.texImage2D(b.TEXTURE_2D,0,b.RGB,16,16,
+0,b.RGB,b.UNSIGNED_BYTE,null);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_S,b.CLAMP_TO_EDGE);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_T,b.CLAMP_TO_EDGE);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MAG_FILTER,b.NEAREST);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MIN_FILTER,b.NEAREST);b.bindTexture(b.TEXTURE_2D,j);b.texImage2D(b.TEXTURE_2D,0,b.RGBA,16,16,0,b.RGBA,b.UNSIGNED_BYTE,null);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_S,b.CLAMP_TO_EDGE);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_T,b.CLAMP_TO_EDGE);
+b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MAG_FILTER,b.NEAREST);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MIN_FILTER,b.NEAREST);0>=b.getParameter(b.MAX_VERTEX_TEXTURE_IMAGE_UNITS)?(l=!1,n=a(THREE.ShaderFlares.lensFlare,d)):(l=!0,n=a(THREE.ShaderFlares.lensFlareVertexTexture,d));m={};r={};m.vertex=b.getAttribLocation(n,"position");m.uv=b.getAttribLocation(n,"uv");r.renderType=b.getUniformLocation(n,"renderType");r.map=b.getUniformLocation(n,"map");r.occlusionMap=b.getUniformLocation(n,"occlusionMap");r.opacity=
+b.getUniformLocation(n,"opacity");r.color=b.getUniformLocation(n,"color");r.scale=b.getUniformLocation(n,"scale");r.rotation=b.getUniformLocation(n,"rotation");r.screenPosition=b.getUniformLocation(n,"screenPosition")};this.render=function(a,d,e,f){var a=a.__webglFlares,v=a.length;if(v){var z=new THREE.Vector3,y=f/e,t=0.5*e,D=0.5*f,C=16/f,k=new THREE.Vector2(C*y,C),I=new THREE.Vector3(1,1,0),J=new THREE.Vector2(1,1),B=r,C=m;b.useProgram(n);b.enableVertexAttribArray(m.vertex);b.enableVertexAttribArray(m.uv);
+b.uniform1i(B.occlusionMap,0);b.uniform1i(B.map,1);b.bindBuffer(b.ARRAY_BUFFER,g);b.vertexAttribPointer(C.vertex,2,b.FLOAT,!1,16,0);b.vertexAttribPointer(C.uv,2,b.FLOAT,!1,16,8);b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,h);b.disable(b.CULL_FACE);b.depthMask(!1);var P,A,G,E,F;for(P=0;P<v;P++)if(C=16/f,k.set(C*y,C),E=a[P],z.set(E.matrixWorld.elements[12],E.matrixWorld.elements[13],E.matrixWorld.elements[14]),z.applyMatrix4(d.matrixWorldInverse),z.applyProjection(d.projectionMatrix),I.copy(z),J.x=I.x*t+t,
+J.y=I.y*D+D,l||0<J.x&&J.x<e&&0<J.y&&J.y<f){b.activeTexture(b.TEXTURE1);b.bindTexture(b.TEXTURE_2D,i);b.copyTexImage2D(b.TEXTURE_2D,0,b.RGB,J.x-8,J.y-8,16,16,0);b.uniform1i(B.renderType,0);b.uniform2f(B.scale,k.x,k.y);b.uniform3f(B.screenPosition,I.x,I.y,I.z);b.disable(b.BLEND);b.enable(b.DEPTH_TEST);b.drawElements(b.TRIANGLES,6,b.UNSIGNED_SHORT,0);b.activeTexture(b.TEXTURE0);b.bindTexture(b.TEXTURE_2D,j);b.copyTexImage2D(b.TEXTURE_2D,0,b.RGBA,J.x-8,J.y-8,16,16,0);b.uniform1i(B.renderType,1);b.disable(b.DEPTH_TEST);
+b.activeTexture(b.TEXTURE1);b.bindTexture(b.TEXTURE_2D,i);b.drawElements(b.TRIANGLES,6,b.UNSIGNED_SHORT,0);E.positionScreen.copy(I);E.customUpdateCallback?E.customUpdateCallback(E):E.updateLensFlares();b.uniform1i(B.renderType,2);b.enable(b.BLEND);A=0;for(G=E.lensFlares.length;A<G;A++)F=E.lensFlares[A],0.001<F.opacity&&0.001<F.scale&&(I.x=F.x,I.y=F.y,I.z=F.z,C=F.size*F.scale/f,k.x=C*y,k.y=C,b.uniform3f(B.screenPosition,I.x,I.y,I.z),b.uniform2f(B.scale,k.x,k.y),b.uniform1f(B.rotation,F.rotation),b.uniform1f(B.opacity,
+F.opacity),b.uniform3f(B.color,F.color.r,F.color.g,F.color.b),c.setBlending(F.blending,F.blendEquation,F.blendSrc,F.blendDst),c.setTexture(F.texture,1),b.drawElements(b.TRIANGLES,6,b.UNSIGNED_SHORT,0))}b.enable(b.CULL_FACE);b.enable(b.DEPTH_TEST);b.depthMask(!0)}}};THREE.ShadowMapPlugin=function(){var a,b,c,d,e,f,g=new THREE.Frustum,h=new THREE.Matrix4,i=new THREE.Vector3,j=new THREE.Vector3,l=new THREE.Vector3;this.init=function(g){a=g.context;b=g;var g=THREE.ShaderLib.depthRGBA,h=THREE.UniformsUtils.clone(g.uniforms);c=new THREE.ShaderMaterial({fragmentShader:g.fragmentShader,vertexShader:g.vertexShader,uniforms:h});d=new THREE.ShaderMaterial({fragmentShader:g.fragmentShader,vertexShader:g.vertexShader,uniforms:h,morphTargets:!0});e=new THREE.ShaderMaterial({fragmentShader:g.fragmentShader,
+vertexShader:g.vertexShader,uniforms:h,skinning:!0});f=new THREE.ShaderMaterial({fragmentShader:g.fragmentShader,vertexShader:g.vertexShader,uniforms:h,morphTargets:!0,skinning:!0});c._shadowPass=!0;d._shadowPass=!0;e._shadowPass=!0;f._shadowPass=!0};this.render=function(a,c){b.shadowMapEnabled&&b.shadowMapAutoUpdate&&this.update(a,c)};this.update=function(n,m){var r,u,p,q,w,v,z,y,t,D=[];q=0;a.clearColor(1,1,1,1);a.disable(a.BLEND);a.enable(a.CULL_FACE);a.frontFace(a.CCW);b.shadowMapCullFace===THREE.CullFaceFront?
+a.cullFace(a.FRONT):a.cullFace(a.BACK);b.setDepthTest(!0);r=0;for(u=n.__lights.length;r<u;r++)if(p=n.__lights[r],p.castShadow)if(p instanceof THREE.DirectionalLight&&p.shadowCascade)for(w=0;w<p.shadowCascadeCount;w++){var C;if(p.shadowCascadeArray[w])C=p.shadowCascadeArray[w];else{t=p;z=w;C=new THREE.DirectionalLight;C.isVirtual=!0;C.onlyShadow=!0;C.castShadow=!0;C.shadowCameraNear=t.shadowCameraNear;C.shadowCameraFar=t.shadowCameraFar;C.shadowCameraLeft=t.shadowCameraLeft;C.shadowCameraRight=t.shadowCameraRight;
+C.shadowCameraBottom=t.shadowCameraBottom;C.shadowCameraTop=t.shadowCameraTop;C.shadowCameraVisible=t.shadowCameraVisible;C.shadowDarkness=t.shadowDarkness;C.shadowBias=t.shadowCascadeBias[z];C.shadowMapWidth=t.shadowCascadeWidth[z];C.shadowMapHeight=t.shadowCascadeHeight[z];C.pointsWorld=[];C.pointsFrustum=[];y=C.pointsWorld;v=C.pointsFrustum;for(var k=0;8>k;k++)y[k]=new THREE.Vector3,v[k]=new THREE.Vector3;y=t.shadowCascadeNearZ[z];t=t.shadowCascadeFarZ[z];v[0].set(-1,-1,y);v[1].set(1,-1,y);v[2].set(-1,
+1,y);v[3].set(1,1,y);v[4].set(-1,-1,t);v[5].set(1,-1,t);v[6].set(-1,1,t);v[7].set(1,1,t);C.originalCamera=m;v=new THREE.Gyroscope;v.position=p.shadowCascadeOffset;v.add(C);v.add(C.target);m.add(v);p.shadowCascadeArray[w]=C;console.log("Created virtualLight",C)}z=p;y=w;t=z.shadowCascadeArray[y];t.position.copy(z.position);t.target.position.copy(z.target.position);t.lookAt(t.target);t.shadowCameraVisible=z.shadowCameraVisible;t.shadowDarkness=z.shadowDarkness;t.shadowBias=z.shadowCascadeBias[y];v=z.shadowCascadeNearZ[y];
+z=z.shadowCascadeFarZ[y];t=t.pointsFrustum;t[0].z=v;t[1].z=v;t[2].z=v;t[3].z=v;t[4].z=z;t[5].z=z;t[6].z=z;t[7].z=z;D[q]=C;q++}else D[q]=p,q++;r=0;for(u=D.length;r<u;r++){p=D[r];p.shadowMap||(w=THREE.LinearFilter,b.shadowMapType===THREE.PCFSoftShadowMap&&(w=THREE.NearestFilter),p.shadowMap=new THREE.WebGLRenderTarget(p.shadowMapWidth,p.shadowMapHeight,{minFilter:w,magFilter:w,format:THREE.RGBAFormat}),p.shadowMapSize=new THREE.Vector2(p.shadowMapWidth,p.shadowMapHeight),p.shadowMatrix=new THREE.Matrix4);
 if(!p.shadowCamera){if(p instanceof THREE.SpotLight)p.shadowCamera=new THREE.PerspectiveCamera(p.shadowCameraFov,p.shadowMapWidth/p.shadowMapHeight,p.shadowCameraNear,p.shadowCameraFar);else if(p instanceof THREE.DirectionalLight)p.shadowCamera=new THREE.OrthographicCamera(p.shadowCameraLeft,p.shadowCameraRight,p.shadowCameraTop,p.shadowCameraBottom,p.shadowCameraNear,p.shadowCameraFar);else{console.error("Unsupported light type for shadow");continue}n.add(p.shadowCamera);b.autoUpdateScene&&n.updateMatrixWorld()}p.shadowCameraVisible&&
 if(!p.shadowCamera){if(p instanceof THREE.SpotLight)p.shadowCamera=new THREE.PerspectiveCamera(p.shadowCameraFov,p.shadowMapWidth/p.shadowMapHeight,p.shadowCameraNear,p.shadowCameraFar);else if(p instanceof THREE.DirectionalLight)p.shadowCamera=new THREE.OrthographicCamera(p.shadowCameraLeft,p.shadowCameraRight,p.shadowCameraTop,p.shadowCameraBottom,p.shadowCameraNear,p.shadowCameraFar);else{console.error("Unsupported light type for shadow");continue}n.add(p.shadowCamera);b.autoUpdateScene&&n.updateMatrixWorld()}p.shadowCameraVisible&&
-!p.cameraHelper&&(p.cameraHelper=new THREE.CameraHelper(p.shadowCamera),p.shadowCamera.add(p.cameraHelper));if(p.isVirtual&&B.originalCamera==m){y=m;q=p.shadowCamera;v=p.pointsFrustum;C=p.pointsWorld;i.set(Infinity,Infinity,Infinity);k.set(-Infinity,-Infinity,-Infinity);for(z=0;8>z;z++)s=C[z],s.copy(v[z]),THREE.ShadowMapPlugin.__projector.unprojectVector(s,y),s.applyMatrix4(q.matrixWorldInverse),s.x<i.x&&(i.x=s.x),s.x>k.x&&(k.x=s.x),s.y<i.y&&(i.y=s.y),s.y>k.y&&(k.y=s.y),s.z<i.z&&(i.z=s.z),s.z>k.z&&
-(k.z=s.z);q.left=i.x;q.right=k.x;q.top=k.y;q.bottom=i.y;q.updateProjectionMatrix()}q=p.shadowMap;v=p.shadowMatrix;y=p.shadowCamera;y.position.getPositionFromMatrix(p.matrixWorld);l.getPositionFromMatrix(p.target.matrixWorld);y.lookAt(l);y.updateMatrixWorld();y.matrixWorldInverse.getInverse(y.matrixWorld);p.cameraHelper&&(p.cameraHelper.visible=p.shadowCameraVisible);p.shadowCameraVisible&&p.cameraHelper.update();v.set(0.5,0,0,0.5,0,0.5,0,0.5,0,0,0.5,0.5,0,0,0,1);v.multiply(y.projectionMatrix);v.multiply(y.matrixWorldInverse);
-h.multiplyMatrices(y.projectionMatrix,y.matrixWorldInverse);g.setFromMatrix(h);b.setRenderTarget(q);b.clear();C=n.__webglObjects;p=0;for(q=C.length;p<q;p++)if(z=C[p],v=z.object,z.render=!1,v.visible&&v.castShadow&&(!(v instanceof THREE.Mesh||v instanceof THREE.ParticleSystem)||!v.frustumCulled||g.intersectsObject(v)))v._modelViewMatrix.multiplyMatrices(y.matrixWorldInverse,v.matrixWorld),z.render=!0;p=0;for(q=C.length;p<q;p++)z=C[p],z.render&&(v=z.object,z=z.buffer,w=v.material instanceof THREE.MeshFaceMaterial?
-v.material.materials[0]:v.material,s=0<v.geometry.morphTargets.length&&w.morphTargets,w=v instanceof THREE.SkinnedMesh&&w.skinning,s=v.customDepthMaterial?v.customDepthMaterial:w?s?f:e:s?d:c,z instanceof THREE.BufferGeometry?b.renderBufferDirect(y,n.__lights,null,s,z,v):b.renderBuffer(y,n.__lights,null,s,z,v));C=n.__webglObjectsImmediate;p=0;for(q=C.length;p<q;p++)z=C[p],v=z.object,v.visible&&v.castShadow&&(v._modelViewMatrix.multiplyMatrices(y.matrixWorldInverse,v.matrixWorld),b.renderImmediateObject(y,
-n.__lights,null,c,v))}t=b.getClearColor();r=b.getClearAlpha();a.clearColor(t.r,t.g,t.b,r);a.enable(a.BLEND);b.shadowMapCullFace===THREE.CullFaceFront&&a.cullFace(a.BACK)}};THREE.ShadowMapPlugin.__projector=new THREE.Projector;THREE.SpritePlugin=function(){function a(a,b){return a.z!==b.z?b.z-a.z:b.id-a.id}var b,c,d,e,f,g,h,i,k,l;this.init=function(a){b=a.context;c=a;d=a.getPrecision();e=new Float32Array(16);f=new Uint16Array(6);a=0;e[a++]=-1;e[a++]=-1;e[a++]=0;e[a++]=0;e[a++]=1;e[a++]=-1;e[a++]=1;e[a++]=0;e[a++]=1;e[a++]=1;e[a++]=1;e[a++]=1;e[a++]=-1;e[a++]=1;e[a++]=0;e[a++]=1;a=0;f[a++]=0;f[a++]=1;f[a++]=2;f[a++]=0;f[a++]=2;f[a++]=3;g=b.createBuffer();h=b.createBuffer();b.bindBuffer(b.ARRAY_BUFFER,g);b.bufferData(b.ARRAY_BUFFER,
-e,b.STATIC_DRAW);b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,h);b.bufferData(b.ELEMENT_ARRAY_BUFFER,f,b.STATIC_DRAW);var a=THREE.ShaderSprite.sprite,m=b.createProgram(),t=b.createShader(b.FRAGMENT_SHADER),r=b.createShader(b.VERTEX_SHADER),p="precision "+d+" float;\n";b.shaderSource(t,p+a.fragmentShader);b.shaderSource(r,p+a.vertexShader);b.compileShader(t);b.compileShader(r);b.attachShader(m,t);b.attachShader(m,r);b.linkProgram(m);i=m;k={};l={};k.position=b.getAttribLocation(i,"position");k.uv=b.getAttribLocation(i,
+!p.cameraHelper&&(p.cameraHelper=new THREE.CameraHelper(p.shadowCamera),p.shadowCamera.add(p.cameraHelper));if(p.isVirtual&&C.originalCamera==m){w=m;q=p.shadowCamera;v=p.pointsFrustum;t=p.pointsWorld;i.set(Infinity,Infinity,Infinity);j.set(-Infinity,-Infinity,-Infinity);for(z=0;8>z;z++)y=t[z],y.copy(v[z]),THREE.ShadowMapPlugin.__projector.unprojectVector(y,w),y.applyMatrix4(q.matrixWorldInverse),y.x<i.x&&(i.x=y.x),y.x>j.x&&(j.x=y.x),y.y<i.y&&(i.y=y.y),y.y>j.y&&(j.y=y.y),y.z<i.z&&(i.z=y.z),y.z>j.z&&
+(j.z=y.z);q.left=i.x;q.right=j.x;q.top=j.y;q.bottom=i.y;q.updateProjectionMatrix()}q=p.shadowMap;v=p.shadowMatrix;w=p.shadowCamera;w.position.getPositionFromMatrix(p.matrixWorld);l.getPositionFromMatrix(p.target.matrixWorld);w.lookAt(l);w.updateMatrixWorld();w.matrixWorldInverse.getInverse(w.matrixWorld);p.cameraHelper&&(p.cameraHelper.visible=p.shadowCameraVisible);p.shadowCameraVisible&&p.cameraHelper.update();v.set(0.5,0,0,0.5,0,0.5,0,0.5,0,0,0.5,0.5,0,0,0,1);v.multiply(w.projectionMatrix);v.multiply(w.matrixWorldInverse);
+h.multiplyMatrices(w.projectionMatrix,w.matrixWorldInverse);g.setFromMatrix(h);b.setRenderTarget(q);b.clear();t=n.__webglObjects;p=0;for(q=t.length;p<q;p++)if(z=t[p],v=z.object,z.render=!1,v.visible&&v.castShadow&&(!(v instanceof THREE.Mesh||v instanceof THREE.ParticleSystem)||!v.frustumCulled||g.intersectsObject(v)))v._modelViewMatrix.multiplyMatrices(w.matrixWorldInverse,v.matrixWorld),z.render=!0;p=0;for(q=t.length;p<q;p++)z=t[p],z.render&&(v=z.object,z=z.buffer,k=v.material instanceof THREE.MeshFaceMaterial?
+v.material.materials[0]:v.material,y=0<v.geometry.morphTargets.length&&k.morphTargets,k=v instanceof THREE.SkinnedMesh&&k.skinning,y=v.customDepthMaterial?v.customDepthMaterial:k?y?f:e:y?d:c,z instanceof THREE.BufferGeometry?b.renderBufferDirect(w,n.__lights,null,y,z,v):b.renderBuffer(w,n.__lights,null,y,z,v));t=n.__webglObjectsImmediate;p=0;for(q=t.length;p<q;p++)z=t[p],v=z.object,v.visible&&v.castShadow&&(v._modelViewMatrix.multiplyMatrices(w.matrixWorldInverse,v.matrixWorld),b.renderImmediateObject(w,
+n.__lights,null,c,v))}r=b.getClearColor();u=b.getClearAlpha();a.clearColor(r.r,r.g,r.b,u);a.enable(a.BLEND);b.shadowMapCullFace===THREE.CullFaceFront&&a.cullFace(a.BACK)}};THREE.ShadowMapPlugin.__projector=new THREE.Projector;THREE.SpritePlugin=function(){function a(a,b){return a.z!==b.z?b.z-a.z:b.id-a.id}var b,c,d,e,f,g,h,i,j,l;this.init=function(a){b=a.context;c=a;d=a.getPrecision();e=new Float32Array(16);f=new Uint16Array(6);a=0;e[a++]=-1;e[a++]=-1;e[a++]=0;e[a++]=0;e[a++]=1;e[a++]=-1;e[a++]=1;e[a++]=0;e[a++]=1;e[a++]=1;e[a++]=1;e[a++]=1;e[a++]=-1;e[a++]=1;e[a++]=0;e[a++]=1;a=0;f[a++]=0;f[a++]=1;f[a++]=2;f[a++]=0;f[a++]=2;f[a++]=3;g=b.createBuffer();h=b.createBuffer();b.bindBuffer(b.ARRAY_BUFFER,g);b.bufferData(b.ARRAY_BUFFER,
+e,b.STATIC_DRAW);b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,h);b.bufferData(b.ELEMENT_ARRAY_BUFFER,f,b.STATIC_DRAW);var a=THREE.ShaderSprite.sprite,m=b.createProgram(),r=b.createShader(b.FRAGMENT_SHADER),u=b.createShader(b.VERTEX_SHADER),p="precision "+d+" float;\n";b.shaderSource(r,p+a.fragmentShader);b.shaderSource(u,p+a.vertexShader);b.compileShader(r);b.compileShader(u);b.attachShader(m,r);b.attachShader(m,u);b.linkProgram(m);i=m;j={};l={};j.position=b.getAttribLocation(i,"position");j.uv=b.getAttribLocation(i,
 "uv");l.uvOffset=b.getUniformLocation(i,"uvOffset");l.uvScale=b.getUniformLocation(i,"uvScale");l.rotation=b.getUniformLocation(i,"rotation");l.scale=b.getUniformLocation(i,"scale");l.alignment=b.getUniformLocation(i,"alignment");l.color=b.getUniformLocation(i,"color");l.map=b.getUniformLocation(i,"map");l.opacity=b.getUniformLocation(i,"opacity");l.useScreenCoordinates=b.getUniformLocation(i,"useScreenCoordinates");l.sizeAttenuation=b.getUniformLocation(i,"sizeAttenuation");l.screenPosition=b.getUniformLocation(i,
 "uv");l.uvOffset=b.getUniformLocation(i,"uvOffset");l.uvScale=b.getUniformLocation(i,"uvScale");l.rotation=b.getUniformLocation(i,"rotation");l.scale=b.getUniformLocation(i,"scale");l.alignment=b.getUniformLocation(i,"alignment");l.color=b.getUniformLocation(i,"color");l.map=b.getUniformLocation(i,"map");l.opacity=b.getUniformLocation(i,"opacity");l.useScreenCoordinates=b.getUniformLocation(i,"useScreenCoordinates");l.sizeAttenuation=b.getUniformLocation(i,"sizeAttenuation");l.screenPosition=b.getUniformLocation(i,
-"screenPosition");l.modelViewMatrix=b.getUniformLocation(i,"modelViewMatrix");l.projectionMatrix=b.getUniformLocation(i,"projectionMatrix");l.fogType=b.getUniformLocation(i,"fogType");l.fogDensity=b.getUniformLocation(i,"fogDensity");l.fogNear=b.getUniformLocation(i,"fogNear");l.fogFar=b.getUniformLocation(i,"fogFar");l.fogColor=b.getUniformLocation(i,"fogColor");l.alphaTest=b.getUniformLocation(i,"alphaTest")};this.render=function(d,e,f,r){var p=d.__webglSprites,q=p.length;if(q){var y=k,v=l,z=r/
-f,f=0.5*f,s=0.5*r;b.useProgram(i);b.enableVertexAttribArray(y.position);b.enableVertexAttribArray(y.uv);b.disable(b.CULL_FACE);b.enable(b.BLEND);b.bindBuffer(b.ARRAY_BUFFER,g);b.vertexAttribPointer(y.position,2,b.FLOAT,!1,16,0);b.vertexAttribPointer(y.uv,2,b.FLOAT,!1,16,8);b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,h);b.uniformMatrix4fv(v.projectionMatrix,!1,e.projectionMatrix.elements);b.activeTexture(b.TEXTURE0);b.uniform1i(v.map,0);var C=y=0,H=d.fog;H?(b.uniform3f(v.fogColor,H.color.r,H.color.g,H.color.b),
-H instanceof THREE.Fog?(b.uniform1f(v.fogNear,H.near),b.uniform1f(v.fogFar,H.far),b.uniform1i(v.fogType,1),C=y=1):H instanceof THREE.FogExp2&&(b.uniform1f(v.fogDensity,H.density),b.uniform1i(v.fogType,2),C=y=2)):(b.uniform1i(v.fogType,0),C=y=0);for(var B,w,I=[],H=0;H<q;H++)B=p[H],w=B.material,B.visible&&0!==w.opacity&&(w.useScreenCoordinates?B.z=-B.position.z:(B._modelViewMatrix.multiplyMatrices(e.matrixWorldInverse,B.matrixWorld),B.z=-B._modelViewMatrix.elements[14]));p.sort(a);for(H=0;H<q;H++)B=
-p[H],w=B.material,B.visible&&0!==w.opacity&&(w.map&&w.map.image&&w.map.image.width)&&(b.uniform1f(v.alphaTest,w.alphaTest),!0===w.useScreenCoordinates?(b.uniform1i(v.useScreenCoordinates,1),b.uniform3f(v.screenPosition,(B.position.x*c.devicePixelRatio-f)/f,(s-B.position.y*c.devicePixelRatio)/s,Math.max(0,Math.min(1,B.position.z))),I[0]=c.devicePixelRatio,I[1]=c.devicePixelRatio):(b.uniform1i(v.useScreenCoordinates,0),b.uniform1i(v.sizeAttenuation,w.sizeAttenuation?1:0),b.uniformMatrix4fv(v.modelViewMatrix,
-!1,B._modelViewMatrix.elements),I[0]=1,I[1]=1),e=d.fog&&w.fog?C:0,y!==e&&(b.uniform1i(v.fogType,e),y=e),e=1/(w.scaleByViewport?r:1),I[0]*=e*z*B.scale.x,I[1]*=e*B.scale.y,b.uniform2f(v.uvScale,w.uvScale.x,w.uvScale.y),b.uniform2f(v.uvOffset,w.uvOffset.x,w.uvOffset.y),b.uniform2f(v.alignment,w.alignment.x,w.alignment.y),b.uniform1f(v.opacity,w.opacity),b.uniform3f(v.color,w.color.r,w.color.g,w.color.b),b.uniform1f(v.rotation,B.rotation),b.uniform2fv(v.scale,I),c.setBlending(w.blending,w.blendEquation,
-w.blendSrc,w.blendDst),c.setDepthTest(w.depthTest),c.setDepthWrite(w.depthWrite),c.setTexture(w.map,0),b.drawElements(b.TRIANGLES,6,b.UNSIGNED_SHORT,0));b.enable(b.CULL_FACE)}}};THREE.DepthPassPlugin=function(){this.enabled=!1;this.renderTarget=null;var a,b,c,d,e,f,g=new THREE.Frustum,h=new THREE.Matrix4;this.init=function(g){a=g.context;b=g;var g=THREE.ShaderLib.depthRGBA,h=THREE.UniformsUtils.clone(g.uniforms);c=new THREE.ShaderMaterial({fragmentShader:g.fragmentShader,vertexShader:g.vertexShader,uniforms:h});d=new THREE.ShaderMaterial({fragmentShader:g.fragmentShader,vertexShader:g.vertexShader,uniforms:h,morphTargets:!0});e=new THREE.ShaderMaterial({fragmentShader:g.fragmentShader,
-vertexShader:g.vertexShader,uniforms:h,skinning:!0});f=new THREE.ShaderMaterial({fragmentShader:g.fragmentShader,vertexShader:g.vertexShader,uniforms:h,morphTargets:!0,skinning:!0});c._shadowPass=!0;d._shadowPass=!0;e._shadowPass=!0;f._shadowPass=!0};this.render=function(a,b){this.enabled&&this.update(a,b)};this.update=function(i,k){var l,n,m,t,r,p;a.clearColor(1,1,1,1);a.disable(a.BLEND);b.setDepthTest(!0);b.autoUpdateScene&&i.updateMatrixWorld();k.matrixWorldInverse.getInverse(k.matrixWorld);h.multiplyMatrices(k.projectionMatrix,
-k.matrixWorldInverse);g.setFromMatrix(h);b.setRenderTarget(this.renderTarget);b.clear();p=i.__webglObjects;l=0;for(n=p.length;l<n;l++)if(m=p[l],r=m.object,m.render=!1,r.visible&&(!(r instanceof THREE.Mesh||r instanceof THREE.ParticleSystem)||!r.frustumCulled||g.intersectsObject(r)))r._modelViewMatrix.multiplyMatrices(k.matrixWorldInverse,r.matrixWorld),m.render=!0;var q;l=0;for(n=p.length;l<n;l++)if(m=p[l],m.render&&(r=m.object,m=m.buffer,!(r instanceof THREE.ParticleSystem)||r.customDepthMaterial))(q=
-r.material instanceof THREE.MeshFaceMaterial?r.material.materials[0]:r.material)&&b.setMaterialFaces(r.material),t=0<r.geometry.morphTargets.length&&q.morphTargets,q=r instanceof THREE.SkinnedMesh&&q.skinning,t=r.customDepthMaterial?r.customDepthMaterial:q?t?f:e:t?d:c,m instanceof THREE.BufferGeometry?b.renderBufferDirect(k,i.__lights,null,t,m,r):b.renderBuffer(k,i.__lights,null,t,m,r);p=i.__webglObjectsImmediate;l=0;for(n=p.length;l<n;l++)m=p[l],r=m.object,r.visible&&(r._modelViewMatrix.multiplyMatrices(k.matrixWorldInverse,
-r.matrixWorld),b.renderImmediateObject(k,i.__lights,null,c,r));l=b.getClearColor();n=b.getClearAlpha();a.clearColor(l.r,l.g,l.b,n);a.enable(a.BLEND)}};THREE.ShaderFlares={lensFlareVertexTexture:{vertexShader:"uniform lowp int renderType;\nuniform vec3 screenPosition;\nuniform vec2 scale;\nuniform float rotation;\nuniform sampler2D occlusionMap;\nattribute vec2 position;\nattribute vec2 uv;\nvarying vec2 vUV;\nvarying float vVisibility;\nvoid main() {\nvUV = uv;\nvec2 pos = position;\nif( renderType == 2 ) {\nvec4 visibility = texture2D( occlusionMap, vec2( 0.1, 0.1 ) ) +\ntexture2D( occlusionMap, vec2( 0.5, 0.1 ) ) +\ntexture2D( occlusionMap, vec2( 0.9, 0.1 ) ) +\ntexture2D( occlusionMap, vec2( 0.9, 0.5 ) ) +\ntexture2D( occlusionMap, vec2( 0.9, 0.9 ) ) +\ntexture2D( occlusionMap, vec2( 0.5, 0.9 ) ) +\ntexture2D( occlusionMap, vec2( 0.1, 0.9 ) ) +\ntexture2D( occlusionMap, vec2( 0.1, 0.5 ) ) +\ntexture2D( occlusionMap, vec2( 0.5, 0.5 ) );\nvVisibility = (       visibility.r / 9.0 ) *\n( 1.0 - visibility.g / 9.0 ) *\n(       visibility.b / 9.0 ) *\n( 1.0 - visibility.a / 9.0 );\npos.x = cos( rotation ) * position.x - sin( rotation ) * position.y;\npos.y = sin( rotation ) * position.x + cos( rotation ) * position.y;\n}\ngl_Position = vec4( ( pos * scale + screenPosition.xy ).xy, screenPosition.z, 1.0 );\n}",
+"screenPosition");l.modelViewMatrix=b.getUniformLocation(i,"modelViewMatrix");l.projectionMatrix=b.getUniformLocation(i,"projectionMatrix");l.fogType=b.getUniformLocation(i,"fogType");l.fogDensity=b.getUniformLocation(i,"fogDensity");l.fogNear=b.getUniformLocation(i,"fogNear");l.fogFar=b.getUniformLocation(i,"fogFar");l.fogColor=b.getUniformLocation(i,"fogColor");l.alphaTest=b.getUniformLocation(i,"alphaTest")};this.render=function(d,e,f,u){var p=d.__webglSprites,q=p.length;if(q){var w=j,v=l,z=u/
+f,f=0.5*f,y=0.5*u;b.useProgram(i);b.enableVertexAttribArray(w.position);b.enableVertexAttribArray(w.uv);b.disable(b.CULL_FACE);b.enable(b.BLEND);b.bindBuffer(b.ARRAY_BUFFER,g);b.vertexAttribPointer(w.position,2,b.FLOAT,!1,16,0);b.vertexAttribPointer(w.uv,2,b.FLOAT,!1,16,8);b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,h);b.uniformMatrix4fv(v.projectionMatrix,!1,e.projectionMatrix.elements);b.activeTexture(b.TEXTURE0);b.uniform1i(v.map,0);var t=w=0,D=d.fog;D?(b.uniform3f(v.fogColor,D.color.r,D.color.g,D.color.b),
+D instanceof THREE.Fog?(b.uniform1f(v.fogNear,D.near),b.uniform1f(v.fogFar,D.far),b.uniform1i(v.fogType,1),t=w=1):D instanceof THREE.FogExp2&&(b.uniform1f(v.fogDensity,D.density),b.uniform1i(v.fogType,2),t=w=2)):(b.uniform1i(v.fogType,0),t=w=0);for(var C,k,I=[],D=0;D<q;D++)C=p[D],k=C.material,C.visible&&0!==k.opacity&&(k.useScreenCoordinates?C.z=-C.position.z:(C._modelViewMatrix.multiplyMatrices(e.matrixWorldInverse,C.matrixWorld),C.z=-C._modelViewMatrix.elements[14]));p.sort(a);for(D=0;D<q;D++)C=
+p[D],k=C.material,C.visible&&0!==k.opacity&&(k.map&&k.map.image&&k.map.image.width)&&(b.uniform1f(v.alphaTest,k.alphaTest),!0===k.useScreenCoordinates?(b.uniform1i(v.useScreenCoordinates,1),b.uniform3f(v.screenPosition,(C.position.x*c.devicePixelRatio-f)/f,(y-C.position.y*c.devicePixelRatio)/y,Math.max(0,Math.min(1,C.position.z))),I[0]=c.devicePixelRatio,I[1]=c.devicePixelRatio):(b.uniform1i(v.useScreenCoordinates,0),b.uniform1i(v.sizeAttenuation,k.sizeAttenuation?1:0),b.uniformMatrix4fv(v.modelViewMatrix,
+!1,C._modelViewMatrix.elements),I[0]=1,I[1]=1),e=d.fog&&k.fog?t:0,w!==e&&(b.uniform1i(v.fogType,e),w=e),e=1/(k.scaleByViewport?u:1),I[0]*=e*z*C.scale.x,I[1]*=e*C.scale.y,b.uniform2f(v.uvScale,k.uvScale.x,k.uvScale.y),b.uniform2f(v.uvOffset,k.uvOffset.x,k.uvOffset.y),b.uniform2f(v.alignment,k.alignment.x,k.alignment.y),b.uniform1f(v.opacity,k.opacity),b.uniform3f(v.color,k.color.r,k.color.g,k.color.b),b.uniform1f(v.rotation,C.rotation),b.uniform2fv(v.scale,I),c.setBlending(k.blending,k.blendEquation,
+k.blendSrc,k.blendDst),c.setDepthTest(k.depthTest),c.setDepthWrite(k.depthWrite),c.setTexture(k.map,0),b.drawElements(b.TRIANGLES,6,b.UNSIGNED_SHORT,0));b.enable(b.CULL_FACE)}}};THREE.DepthPassPlugin=function(){this.enabled=!1;this.renderTarget=null;var a,b,c,d,e,f,g=new THREE.Frustum,h=new THREE.Matrix4;this.init=function(g){a=g.context;b=g;var g=THREE.ShaderLib.depthRGBA,h=THREE.UniformsUtils.clone(g.uniforms);c=new THREE.ShaderMaterial({fragmentShader:g.fragmentShader,vertexShader:g.vertexShader,uniforms:h});d=new THREE.ShaderMaterial({fragmentShader:g.fragmentShader,vertexShader:g.vertexShader,uniforms:h,morphTargets:!0});e=new THREE.ShaderMaterial({fragmentShader:g.fragmentShader,
+vertexShader:g.vertexShader,uniforms:h,skinning:!0});f=new THREE.ShaderMaterial({fragmentShader:g.fragmentShader,vertexShader:g.vertexShader,uniforms:h,morphTargets:!0,skinning:!0});c._shadowPass=!0;d._shadowPass=!0;e._shadowPass=!0;f._shadowPass=!0};this.render=function(a,b){this.enabled&&this.update(a,b)};this.update=function(i,j){var l,n,m,r,u,p;a.clearColor(1,1,1,1);a.disable(a.BLEND);b.setDepthTest(!0);b.autoUpdateScene&&i.updateMatrixWorld();j.matrixWorldInverse.getInverse(j.matrixWorld);h.multiplyMatrices(j.projectionMatrix,
+j.matrixWorldInverse);g.setFromMatrix(h);b.setRenderTarget(this.renderTarget);b.clear();p=i.__webglObjects;l=0;for(n=p.length;l<n;l++)if(m=p[l],u=m.object,m.render=!1,u.visible&&(!(u instanceof THREE.Mesh||u instanceof THREE.ParticleSystem)||!u.frustumCulled||g.intersectsObject(u)))u._modelViewMatrix.multiplyMatrices(j.matrixWorldInverse,u.matrixWorld),m.render=!0;var q;l=0;for(n=p.length;l<n;l++)if(m=p[l],m.render&&(u=m.object,m=m.buffer,!(u instanceof THREE.ParticleSystem)||u.customDepthMaterial))(q=
+u.material instanceof THREE.MeshFaceMaterial?u.material.materials[0]:u.material)&&b.setMaterialFaces(u.material),r=0<u.geometry.morphTargets.length&&q.morphTargets,q=u instanceof THREE.SkinnedMesh&&q.skinning,r=u.customDepthMaterial?u.customDepthMaterial:q?r?f:e:r?d:c,m instanceof THREE.BufferGeometry?b.renderBufferDirect(j,i.__lights,null,r,m,u):b.renderBuffer(j,i.__lights,null,r,m,u);p=i.__webglObjectsImmediate;l=0;for(n=p.length;l<n;l++)m=p[l],u=m.object,u.visible&&(u._modelViewMatrix.multiplyMatrices(j.matrixWorldInverse,
+u.matrixWorld),b.renderImmediateObject(j,i.__lights,null,c,u));l=b.getClearColor();n=b.getClearAlpha();a.clearColor(l.r,l.g,l.b,n);a.enable(a.BLEND)}};THREE.ShaderFlares={lensFlareVertexTexture:{vertexShader:"uniform lowp int renderType;\nuniform vec3 screenPosition;\nuniform vec2 scale;\nuniform float rotation;\nuniform sampler2D occlusionMap;\nattribute vec2 position;\nattribute vec2 uv;\nvarying vec2 vUV;\nvarying float vVisibility;\nvoid main() {\nvUV = uv;\nvec2 pos = position;\nif( renderType == 2 ) {\nvec4 visibility = texture2D( occlusionMap, vec2( 0.1, 0.1 ) ) +\ntexture2D( occlusionMap, vec2( 0.5, 0.1 ) ) +\ntexture2D( occlusionMap, vec2( 0.9, 0.1 ) ) +\ntexture2D( occlusionMap, vec2( 0.9, 0.5 ) ) +\ntexture2D( occlusionMap, vec2( 0.9, 0.9 ) ) +\ntexture2D( occlusionMap, vec2( 0.5, 0.9 ) ) +\ntexture2D( occlusionMap, vec2( 0.1, 0.9 ) ) +\ntexture2D( occlusionMap, vec2( 0.1, 0.5 ) ) +\ntexture2D( occlusionMap, vec2( 0.5, 0.5 ) );\nvVisibility = (       visibility.r / 9.0 ) *\n( 1.0 - visibility.g / 9.0 ) *\n(       visibility.b / 9.0 ) *\n( 1.0 - visibility.a / 9.0 );\npos.x = cos( rotation ) * position.x - sin( rotation ) * position.y;\npos.y = sin( rotation ) * position.x + cos( rotation ) * position.y;\n}\ngl_Position = vec4( ( pos * scale + screenPosition.xy ).xy, screenPosition.z, 1.0 );\n}",
 fragmentShader:"uniform lowp int renderType;\nuniform sampler2D map;\nuniform float opacity;\nuniform vec3 color;\nvarying vec2 vUV;\nvarying float vVisibility;\nvoid main() {\nif( renderType == 0 ) {\ngl_FragColor = vec4( 1.0, 0.0, 1.0, 0.0 );\n} else if( renderType == 1 ) {\ngl_FragColor = texture2D( map, vUV );\n} else {\nvec4 texture = texture2D( map, vUV );\ntexture.a *= opacity * vVisibility;\ngl_FragColor = texture;\ngl_FragColor.rgb *= color;\n}\n}"},lensFlare:{vertexShader:"uniform lowp int renderType;\nuniform vec3 screenPosition;\nuniform vec2 scale;\nuniform float rotation;\nattribute vec2 position;\nattribute vec2 uv;\nvarying vec2 vUV;\nvoid main() {\nvUV = uv;\nvec2 pos = position;\nif( renderType == 2 ) {\npos.x = cos( rotation ) * position.x - sin( rotation ) * position.y;\npos.y = sin( rotation ) * position.x + cos( rotation ) * position.y;\n}\ngl_Position = vec4( ( pos * scale + screenPosition.xy ).xy, screenPosition.z, 1.0 );\n}",
 fragmentShader:"uniform lowp int renderType;\nuniform sampler2D map;\nuniform float opacity;\nuniform vec3 color;\nvarying vec2 vUV;\nvarying float vVisibility;\nvoid main() {\nif( renderType == 0 ) {\ngl_FragColor = vec4( 1.0, 0.0, 1.0, 0.0 );\n} else if( renderType == 1 ) {\ngl_FragColor = texture2D( map, vUV );\n} else {\nvec4 texture = texture2D( map, vUV );\ntexture.a *= opacity * vVisibility;\ngl_FragColor = texture;\ngl_FragColor.rgb *= color;\n}\n}"},lensFlare:{vertexShader:"uniform lowp int renderType;\nuniform vec3 screenPosition;\nuniform vec2 scale;\nuniform float rotation;\nattribute vec2 position;\nattribute vec2 uv;\nvarying vec2 vUV;\nvoid main() {\nvUV = uv;\nvec2 pos = position;\nif( renderType == 2 ) {\npos.x = cos( rotation ) * position.x - sin( rotation ) * position.y;\npos.y = sin( rotation ) * position.x + cos( rotation ) * position.y;\n}\ngl_Position = vec4( ( pos * scale + screenPosition.xy ).xy, screenPosition.z, 1.0 );\n}",
 fragmentShader:"precision mediump float;\nuniform lowp int renderType;\nuniform sampler2D map;\nuniform sampler2D occlusionMap;\nuniform float opacity;\nuniform vec3 color;\nvarying vec2 vUV;\nvoid main() {\nif( renderType == 0 ) {\ngl_FragColor = vec4( texture2D( map, vUV ).rgb, 0.0 );\n} else if( renderType == 1 ) {\ngl_FragColor = texture2D( map, vUV );\n} else {\nfloat visibility = texture2D( occlusionMap, vec2( 0.5, 0.1 ) ).a +\ntexture2D( occlusionMap, vec2( 0.9, 0.5 ) ).a +\ntexture2D( occlusionMap, vec2( 0.5, 0.9 ) ).a +\ntexture2D( occlusionMap, vec2( 0.1, 0.5 ) ).a;\nvisibility = ( 1.0 - visibility / 4.0 );\nvec4 texture = texture2D( map, vUV );\ntexture.a *= opacity * visibility;\ngl_FragColor = texture;\ngl_FragColor.rgb *= color;\n}\n}"}};THREE.ShaderSprite={sprite:{vertexShader:"uniform int useScreenCoordinates;\nuniform int sizeAttenuation;\nuniform vec3 screenPosition;\nuniform mat4 modelViewMatrix;\nuniform mat4 projectionMatrix;\nuniform float rotation;\nuniform vec2 scale;\nuniform vec2 alignment;\nuniform vec2 uvOffset;\nuniform vec2 uvScale;\nattribute vec2 position;\nattribute vec2 uv;\nvarying vec2 vUV;\nvoid main() {\nvUV = uvOffset + uv * uvScale;\nvec2 alignedPosition = position + alignment;\nvec2 rotatedPosition;\nrotatedPosition.x = ( cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y ) * scale.x;\nrotatedPosition.y = ( sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y ) * scale.y;\nvec4 finalPosition;\nif( useScreenCoordinates != 0 ) {\nfinalPosition = vec4( screenPosition.xy + rotatedPosition, screenPosition.z, 1.0 );\n} else {\nfinalPosition = projectionMatrix * modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );\nfinalPosition.xy += rotatedPosition * ( sizeAttenuation == 1 ? 1.0 : finalPosition.z );\n}\ngl_Position = finalPosition;\n}",
 fragmentShader:"precision mediump float;\nuniform lowp int renderType;\nuniform sampler2D map;\nuniform sampler2D occlusionMap;\nuniform float opacity;\nuniform vec3 color;\nvarying vec2 vUV;\nvoid main() {\nif( renderType == 0 ) {\ngl_FragColor = vec4( texture2D( map, vUV ).rgb, 0.0 );\n} else if( renderType == 1 ) {\ngl_FragColor = texture2D( map, vUV );\n} else {\nfloat visibility = texture2D( occlusionMap, vec2( 0.5, 0.1 ) ).a +\ntexture2D( occlusionMap, vec2( 0.9, 0.5 ) ).a +\ntexture2D( occlusionMap, vec2( 0.5, 0.9 ) ).a +\ntexture2D( occlusionMap, vec2( 0.1, 0.5 ) ).a;\nvisibility = ( 1.0 - visibility / 4.0 );\nvec4 texture = texture2D( map, vUV );\ntexture.a *= opacity * visibility;\ngl_FragColor = texture;\ngl_FragColor.rgb *= color;\n}\n}"}};THREE.ShaderSprite={sprite:{vertexShader:"uniform int useScreenCoordinates;\nuniform int sizeAttenuation;\nuniform vec3 screenPosition;\nuniform mat4 modelViewMatrix;\nuniform mat4 projectionMatrix;\nuniform float rotation;\nuniform vec2 scale;\nuniform vec2 alignment;\nuniform vec2 uvOffset;\nuniform vec2 uvScale;\nattribute vec2 position;\nattribute vec2 uv;\nvarying vec2 vUV;\nvoid main() {\nvUV = uvOffset + uv * uvScale;\nvec2 alignedPosition = position + alignment;\nvec2 rotatedPosition;\nrotatedPosition.x = ( cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y ) * scale.x;\nrotatedPosition.y = ( sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y ) * scale.y;\nvec4 finalPosition;\nif( useScreenCoordinates != 0 ) {\nfinalPosition = vec4( screenPosition.xy + rotatedPosition, screenPosition.z, 1.0 );\n} else {\nfinalPosition = projectionMatrix * modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );\nfinalPosition.xy += rotatedPosition * ( sizeAttenuation == 1 ? 1.0 : finalPosition.z );\n}\ngl_Position = finalPosition;\n}",
 fragmentShader:"uniform vec3 color;\nuniform sampler2D map;\nuniform float opacity;\nuniform int fogType;\nuniform vec3 fogColor;\nuniform float fogDensity;\nuniform float fogNear;\nuniform float fogFar;\nuniform float alphaTest;\nvarying vec2 vUV;\nvoid main() {\nvec4 texture = texture2D( map, vUV );\nif ( texture.a < alphaTest ) discard;\ngl_FragColor = vec4( color * texture.xyz, texture.a * opacity );\nif ( fogType > 0 ) {\nfloat depth = gl_FragCoord.z / gl_FragCoord.w;\nfloat fogFactor = 0.0;\nif ( fogType == 1 ) {\nfogFactor = smoothstep( fogNear, fogFar, depth );\n} else {\nconst float LOG2 = 1.442695;\nfloat fogFactor = exp2( - fogDensity * fogDensity * depth * depth * LOG2 );\nfogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 );\n}\ngl_FragColor = mix( gl_FragColor, vec4( fogColor, gl_FragColor.w ), fogFactor );\n}\n}"}};
 fragmentShader:"uniform vec3 color;\nuniform sampler2D map;\nuniform float opacity;\nuniform int fogType;\nuniform vec3 fogColor;\nuniform float fogDensity;\nuniform float fogNear;\nuniform float fogFar;\nuniform float alphaTest;\nvarying vec2 vUV;\nvoid main() {\nvec4 texture = texture2D( map, vUV );\nif ( texture.a < alphaTest ) discard;\ngl_FragColor = vec4( color * texture.xyz, texture.a * opacity );\nif ( fogType > 0 ) {\nfloat depth = gl_FragCoord.z / gl_FragCoord.w;\nfloat fogFactor = 0.0;\nif ( fogType == 1 ) {\nfogFactor = smoothstep( fogNear, fogFar, depth );\n} else {\nconst float LOG2 = 1.442695;\nfloat fogFactor = exp2( - fogDensity * fogDensity * depth * depth * LOG2 );\nfogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 );\n}\ngl_FragColor = mix( gl_FragColor, vec4( fogColor, gl_FragColor.w ), fogFactor );\n}\n}"}};

+ 8 - 2
utils/build/includes/common.json

@@ -5,7 +5,6 @@
 	"src/math/Vector2.js",
 	"src/math/Vector2.js",
 	"src/math/Vector3.js",
 	"src/math/Vector3.js",
 	"src/math/Vector4.js",
 	"src/math/Vector4.js",
-	"src/math/Line3.js",
 	"src/math/Box2.js",
 	"src/math/Box2.js",
 	"src/math/Box3.js",
 	"src/math/Box3.js",
 	"src/math/Matrix3.js",
 	"src/math/Matrix3.js",
@@ -75,7 +74,14 @@
 	"src/scenes/FogExp2.js",
 	"src/scenes/FogExp2.js",
 	"src/renderers/CanvasRenderer.js",
 	"src/renderers/CanvasRenderer.js",
 	"src/renderers/WebGLShaders.js",
 	"src/renderers/WebGLShaders.js",
-	"src/renderers/WebGLRenderer.js",
+	"src/renderers/WebGLRenderer2.js",
+	"src/renderers/webgl/LowLevelRenderer.js",
+	"src/renderers/webgl/ShaderBuilder.js",
+	"src/renderers/webgl/objects/Object3DRenderer.js",
+	"src/renderers/webgl/objects/MeshRenderer.js",
+	"src/renderers/webgl/objects/ParticleRenderer.js",
+	"src/renderers/webgl/objects/LineRenderer.js",
+	"src/renderers/webgl/objects/RibbonRenderer.js",
 	"src/renderers/WebGLRenderTarget.js",
 	"src/renderers/WebGLRenderTarget.js",
 	"src/renderers/WebGLRenderTargetCube.js",
 	"src/renderers/WebGLRenderTargetCube.js",
 	"src/renderers/renderables/RenderableVertex.js",
 	"src/renderers/renderables/RenderableVertex.js",

+ 2 - 8
utils/build/includes/common2.json → utils/build/includes/common_old.json

@@ -5,6 +5,7 @@
 	"src/math/Vector2.js",
 	"src/math/Vector2.js",
 	"src/math/Vector3.js",
 	"src/math/Vector3.js",
 	"src/math/Vector4.js",
 	"src/math/Vector4.js",
+	"src/math/Line3.js",
 	"src/math/Box2.js",
 	"src/math/Box2.js",
 	"src/math/Box3.js",
 	"src/math/Box3.js",
 	"src/math/Matrix3.js",
 	"src/math/Matrix3.js",
@@ -74,14 +75,7 @@
 	"src/scenes/FogExp2.js",
 	"src/scenes/FogExp2.js",
 	"src/renderers/CanvasRenderer.js",
 	"src/renderers/CanvasRenderer.js",
 	"src/renderers/WebGLShaders.js",
 	"src/renderers/WebGLShaders.js",
-	"src/renderers/WebGLRenderer2.js",
-	"src/renderers/webgl/LowLevelRenderer.js",
-	"src/renderers/webgl/ShaderBuilder.js",
-	"src/renderers/webgl/objects/Object3DRenderer.js",
-	"src/renderers/webgl/objects/MeshRenderer.js",
-	"src/renderers/webgl/objects/ParticleRenderer.js",
-	"src/renderers/webgl/objects/LineRenderer.js",
-	"src/renderers/webgl/objects/RibbonRenderer.js",
+	"src/renderers/WebGLRenderer.js",
 	"src/renderers/WebGLRenderTarget.js",
 	"src/renderers/WebGLRenderTarget.js",
 	"src/renderers/WebGLRenderTargetCube.js",
 	"src/renderers/WebGLRenderTargetCube.js",
 	"src/renderers/renderables/RenderableVertex.js",
 	"src/renderers/renderables/RenderableVertex.js",