瀏覽代碼

Merge pull request #17195 from Mugen87/dev31

Objects: Remove IIFEs.
Mr.doob 6 年之前
父節點
當前提交
ea5c7ed570
共有 7 個文件被更改,包括 584 次插入566 次删除
  1. 30 32
      src/objects/LOD.js
  2. 123 120
      src/objects/Line.js
  3. 34 32
      src/objects/LineSegments.js
  4. 220 214
      src/objects/Mesh.js
  5. 63 61
      src/objects/Points.js
  6. 22 20
      src/objects/Skeleton.js
  7. 92 87
      src/objects/Sprite.js

+ 30 - 32
src/objects/LOD.js

@@ -7,6 +7,8 @@ import { Object3D } from '../core/Object3D.js';
  * @author mrdoob / http://mrdoob.com/
  */
 
+var _v1, _v2;
+
 function LOD() {
 
 	Object3D.call( this );
@@ -92,66 +94,62 @@ LOD.prototype = Object.assign( Object.create( Object3D.prototype ), {
 
 	},
 
-	raycast: ( function () {
-
-		var matrixPosition = new Vector3();
-
-		return function raycast( raycaster, intersects ) {
+	raycast: function ( raycaster, intersects ) {
 
-			matrixPosition.setFromMatrixPosition( this.matrixWorld );
+		if ( _v1 === undefined ) _v1 = new Vector3();
 
-			var distance = raycaster.ray.origin.distanceTo( matrixPosition );
+		_v1.setFromMatrixPosition( this.matrixWorld );
 
-			this.getObjectForDistance( distance ).raycast( raycaster, intersects );
+		var distance = raycaster.ray.origin.distanceTo( _v1 );
 
-		};
+		this.getObjectForDistance( distance ).raycast( raycaster, intersects );
 
-	}() ),
+	},
 
-	update: function () {
+	update: function ( camera ) {
 
-		var v1 = new Vector3();
-		var v2 = new Vector3();
+		if ( _v2 === undefined ) {
 
-		return function update( camera ) {
+			_v1 = new Vector3();
+			_v2 = new Vector3();
 
-			var levels = this.levels;
+		}
 
-			if ( levels.length > 1 ) {
+		var levels = this.levels;
 
-				v1.setFromMatrixPosition( camera.matrixWorld );
-				v2.setFromMatrixPosition( this.matrixWorld );
+		if ( levels.length > 1 ) {
 
-				var distance = v1.distanceTo( v2 );
+			_v1.setFromMatrixPosition( camera.matrixWorld );
+			_v2.setFromMatrixPosition( this.matrixWorld );
 
-				levels[ 0 ].object.visible = true;
+			var distance = _v1.distanceTo( _v2 );
 
-				for ( var i = 1, l = levels.length; i < l; i ++ ) {
+			levels[ 0 ].object.visible = true;
 
-					if ( distance >= levels[ i ].distance ) {
+			for ( var i = 1, l = levels.length; i < l; i ++ ) {
 
-						levels[ i - 1 ].object.visible = false;
-						levels[ i ].object.visible = true;
+				if ( distance >= levels[ i ].distance ) {
 
-					} else {
+					levels[ i - 1 ].object.visible = false;
+					levels[ i ].object.visible = true;
 
-						break;
+				} else {
 
-					}
+					break;
 
 				}
 
-				for ( ; i < l; i ++ ) {
+			}
 
-					levels[ i ].object.visible = false;
+			for ( ; i < l; i ++ ) {
 
-				}
+				levels[ i ].object.visible = false;
 
 			}
 
-		};
+		}
 
-	}(),
+	},
 
 	toJSON: function ( meta ) {
 

+ 123 - 120
src/objects/Line.js

@@ -11,6 +11,9 @@ import { Float32BufferAttribute } from '../core/BufferAttribute.js';
  * @author mrdoob / http://mrdoob.com/
  */
 
+var _start, _end;
+var _inverseMatrix, _ray, _sphere;
+
 function Line( geometry, material, mode ) {
 
 	if ( mode === 1 ) {
@@ -34,186 +37,154 @@ Line.prototype = Object.assign( Object.create( Object3D.prototype ), {
 
 	isLine: true,
 
-	computeLineDistances: ( function () {
-
-		var start = new Vector3();
-		var end = new Vector3();
-
-		return function computeLineDistances() {
-
-			var geometry = this.geometry;
-
-			if ( geometry.isBufferGeometry ) {
-
-				// we assume non-indexed geometry
+	computeLineDistances: function () {
 
-				if ( geometry.index === null ) {
+		if ( _end === undefined ) {
 
-					var positionAttribute = geometry.attributes.position;
-					var lineDistances = [ 0 ];
+			_start = new Vector3();
+			_end = new Vector3();
 
-					for ( var i = 1, l = positionAttribute.count; i < l; i ++ ) {
+		}
 
-						start.fromBufferAttribute( positionAttribute, i - 1 );
-						end.fromBufferAttribute( positionAttribute, i );
+		var geometry = this.geometry;
 
-						lineDistances[ i ] = lineDistances[ i - 1 ];
-						lineDistances[ i ] += start.distanceTo( end );
+		if ( geometry.isBufferGeometry ) {
 
-					}
-
-					geometry.addAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) );
-
-				} else {
-
-					console.warn( 'THREE.Line.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' );
-
-				}
+			// we assume non-indexed geometry
 
-			} else if ( geometry.isGeometry ) {
+			if ( geometry.index === null ) {
 
-				var vertices = geometry.vertices;
-				var lineDistances = geometry.lineDistances;
+				var positionAttribute = geometry.attributes.position;
+				var lineDistances = [ 0 ];
 
-				lineDistances[ 0 ] = 0;
+				for ( var i = 1, l = positionAttribute.count; i < l; i ++ ) {
 
-				for ( var i = 1, l = vertices.length; i < l; i ++ ) {
+					_start.fromBufferAttribute( positionAttribute, i - 1 );
+					_end.fromBufferAttribute( positionAttribute, i );
 
 					lineDistances[ i ] = lineDistances[ i - 1 ];
-					lineDistances[ i ] += vertices[ i - 1 ].distanceTo( vertices[ i ] );
+					lineDistances[ i ] += _start.distanceTo( _end );
 
 				}
 
-			}
-
-			return this;
-
-		};
+				geometry.addAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) );
 
-	}() ),
+			} else {
 
-	raycast: ( function () {
+				console.warn( 'THREE.Line.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' );
 
-		var inverseMatrix = new Matrix4();
-		var ray = new Ray();
-		var sphere = new Sphere();
-
-		return function raycast( raycaster, intersects ) {
+			}
 
-			var precision = raycaster.linePrecision;
+		} else if ( geometry.isGeometry ) {
 
-			var geometry = this.geometry;
-			var matrixWorld = this.matrixWorld;
+			var vertices = geometry.vertices;
+			var lineDistances = geometry.lineDistances;
 
-			// Checking boundingSphere distance to ray
+			lineDistances[ 0 ] = 0;
 
-			if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
+			for ( var i = 1, l = vertices.length; i < l; i ++ ) {
 
-			sphere.copy( geometry.boundingSphere );
-			sphere.applyMatrix4( matrixWorld );
-			sphere.radius += precision;
+				lineDistances[ i ] = lineDistances[ i - 1 ];
+				lineDistances[ i ] += vertices[ i - 1 ].distanceTo( vertices[ i ] );
 
-			if ( raycaster.ray.intersectsSphere( sphere ) === false ) return;
+			}
 
-			//
+		}
 
-			inverseMatrix.getInverse( matrixWorld );
-			ray.copy( raycaster.ray ).applyMatrix4( inverseMatrix );
+		return this;
 
-			var localPrecision = precision / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 );
-			var localPrecisionSq = localPrecision * localPrecision;
+	},
 
-			var vStart = new Vector3();
-			var vEnd = new Vector3();
-			var interSegment = new Vector3();
-			var interRay = new Vector3();
-			var step = ( this && this.isLineSegments ) ? 2 : 1;
+	raycast: function ( raycaster, intersects ) {
 
-			if ( geometry.isBufferGeometry ) {
+		if ( _sphere === undefined ) {
 
-				var index = geometry.index;
-				var attributes = geometry.attributes;
-				var positions = attributes.position.array;
+			_inverseMatrix = new Matrix4();
+			_ray = new Ray();
+			_sphere = new Sphere();
 
-				if ( index !== null ) {
+		}
 
-					var indices = index.array;
+		var precision = raycaster.linePrecision;
 
-					for ( var i = 0, l = indices.length - 1; i < l; i += step ) {
+		var geometry = this.geometry;
+		var matrixWorld = this.matrixWorld;
 
-						var a = indices[ i ];
-						var b = indices[ i + 1 ];
+		// Checking boundingSphere distance to ray
 
-						vStart.fromArray( positions, a * 3 );
-						vEnd.fromArray( positions, b * 3 );
+		if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
 
-						var distSq = ray.distanceSqToSegment( vStart, vEnd, interRay, interSegment );
+		_sphere.copy( geometry.boundingSphere );
+		_sphere.applyMatrix4( matrixWorld );
+		_sphere.radius += precision;
 
-						if ( distSq > localPrecisionSq ) continue;
+		if ( raycaster.ray.intersectsSphere( _sphere ) === false ) return;
 
-						interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation
+		//
 
-						var distance = raycaster.ray.origin.distanceTo( interRay );
+		_inverseMatrix.getInverse( matrixWorld );
+		_ray.copy( raycaster.ray ).applyMatrix4( _inverseMatrix );
 
-						if ( distance < raycaster.near || distance > raycaster.far ) continue;
+		var localPrecision = precision / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 );
+		var localPrecisionSq = localPrecision * localPrecision;
 
-						intersects.push( {
+		var vStart = new Vector3();
+		var vEnd = new Vector3();
+		var interSegment = new Vector3();
+		var interRay = new Vector3();
+		var step = ( this && this.isLineSegments ) ? 2 : 1;
 
-							distance: distance,
-							// What do we want? intersection point on the ray or on the segment??
-							// point: raycaster.ray.at( distance ),
-							point: interSegment.clone().applyMatrix4( this.matrixWorld ),
-							index: i,
-							face: null,
-							faceIndex: null,
-							object: this
+		if ( geometry.isBufferGeometry ) {
 
-						} );
+			var index = geometry.index;
+			var attributes = geometry.attributes;
+			var positions = attributes.position.array;
 
-					}
+			if ( index !== null ) {
 
-				} else {
+				var indices = index.array;
 
-					for ( var i = 0, l = positions.length / 3 - 1; i < l; i += step ) {
+				for ( var i = 0, l = indices.length - 1; i < l; i += step ) {
 
-						vStart.fromArray( positions, 3 * i );
-						vEnd.fromArray( positions, 3 * i + 3 );
+					var a = indices[ i ];
+					var b = indices[ i + 1 ];
 
-						var distSq = ray.distanceSqToSegment( vStart, vEnd, interRay, interSegment );
+					vStart.fromArray( positions, a * 3 );
+					vEnd.fromArray( positions, b * 3 );
 
-						if ( distSq > localPrecisionSq ) continue;
+					var distSq = _ray.distanceSqToSegment( vStart, vEnd, interRay, interSegment );
 
-						interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation
+					if ( distSq > localPrecisionSq ) continue;
 
-						var distance = raycaster.ray.origin.distanceTo( interRay );
+					interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation
 
-						if ( distance < raycaster.near || distance > raycaster.far ) continue;
+					var distance = raycaster.ray.origin.distanceTo( interRay );
 
-						intersects.push( {
+					if ( distance < raycaster.near || distance > raycaster.far ) continue;
 
-							distance: distance,
-							// What do we want? intersection point on the ray or on the segment??
-							// point: raycaster.ray.at( distance ),
-							point: interSegment.clone().applyMatrix4( this.matrixWorld ),
-							index: i,
-							face: null,
-							faceIndex: null,
-							object: this
+					intersects.push( {
 
-						} );
+						distance: distance,
+						// What do we want? intersection point on the ray or on the segment??
+						// point: raycaster.ray.at( distance ),
+						point: interSegment.clone().applyMatrix4( this.matrixWorld ),
+						index: i,
+						face: null,
+						faceIndex: null,
+						object: this
 
-					}
+					} );
 
 				}
 
-			} else if ( geometry.isGeometry ) {
+			} else {
 
-				var vertices = geometry.vertices;
-				var nbVertices = vertices.length;
+				for ( var i = 0, l = positions.length / 3 - 1; i < l; i += step ) {
 
-				for ( var i = 0; i < nbVertices - 1; i += step ) {
+					vStart.fromArray( positions, 3 * i );
+					vEnd.fromArray( positions, 3 * i + 3 );
 
-					var distSq = ray.distanceSqToSegment( vertices[ i ], vertices[ i + 1 ], interRay, interSegment );
+					var distSq = _ray.distanceSqToSegment( vStart, vEnd, interRay, interSegment );
 
 					if ( distSq > localPrecisionSq ) continue;
 
@@ -240,9 +211,41 @@ Line.prototype = Object.assign( Object.create( Object3D.prototype ), {
 
 			}
 
-		};
+		} else if ( geometry.isGeometry ) {
+
+			var vertices = geometry.vertices;
+			var nbVertices = vertices.length;
+
+			for ( var i = 0; i < nbVertices - 1; i += step ) {
+
+				var distSq = _ray.distanceSqToSegment( vertices[ i ], vertices[ i + 1 ], interRay, interSegment );
+
+				if ( distSq > localPrecisionSq ) continue;
+
+				interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation
+
+				var distance = raycaster.ray.origin.distanceTo( interRay );
+
+				if ( distance < raycaster.near || distance > raycaster.far ) continue;
+
+				intersects.push( {
+
+					distance: distance,
+					// What do we want? intersection point on the ray or on the segment??
+					// point: raycaster.ray.at( distance ),
+					point: interSegment.clone().applyMatrix4( this.matrixWorld ),
+					index: i,
+					face: null,
+					faceIndex: null,
+					object: this
+
+				} );
+
+			}
+
+		}
 
-	}() ),
+	},
 
 	clone: function () {
 

+ 34 - 32
src/objects/LineSegments.js

@@ -6,6 +6,8 @@ import { Float32BufferAttribute } from '../core/BufferAttribute.js';
  * @author mrdoob / http://mrdoob.com/
  */
 
+var _start, _end;
+
 function LineSegments( geometry, material ) {
 
 	Line.call( this, geometry, material );
@@ -20,64 +22,64 @@ LineSegments.prototype = Object.assign( Object.create( Line.prototype ), {
 
 	isLineSegments: true,
 
-	computeLineDistances: ( function () {
+	computeLineDistances: function () {
 
-		var start = new Vector3();
-		var end = new Vector3();
+		if ( _end === undefined ) {
 
-		return function computeLineDistances() {
+			_start = new Vector3();
+			_end = new Vector3();
 
-			var geometry = this.geometry;
+		}
 
-			if ( geometry.isBufferGeometry ) {
+		var geometry = this.geometry;
 
-				// we assume non-indexed geometry
+		if ( geometry.isBufferGeometry ) {
 
-				if ( geometry.index === null ) {
+			// we assume non-indexed geometry
 
-					var positionAttribute = geometry.attributes.position;
-					var lineDistances = [];
+			if ( geometry.index === null ) {
 
-					for ( var i = 0, l = positionAttribute.count; i < l; i += 2 ) {
+				var positionAttribute = geometry.attributes.position;
+				var lineDistances = [];
 
-						start.fromBufferAttribute( positionAttribute, i );
-						end.fromBufferAttribute( positionAttribute, i + 1 );
+				for ( var i = 0, l = positionAttribute.count; i < l; i += 2 ) {
 
-						lineDistances[ i ] = ( i === 0 ) ? 0 : lineDistances[ i - 1 ];
-						lineDistances[ i + 1 ] = lineDistances[ i ] + start.distanceTo( end );
+					_start.fromBufferAttribute( positionAttribute, i );
+					_end.fromBufferAttribute( positionAttribute, i + 1 );
 
-					}
+					lineDistances[ i ] = ( i === 0 ) ? 0 : lineDistances[ i - 1 ];
+					lineDistances[ i + 1 ] = lineDistances[ i ] + _start.distanceTo( _end );
 
-					geometry.addAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) );
+				}
 
-				} else {
+				geometry.addAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) );
 
-					console.warn( 'THREE.LineSegments.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' );
+			} else {
 
-				}
+				console.warn( 'THREE.LineSegments.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' );
 
-			} else if ( geometry.isGeometry ) {
+			}
 
-				var vertices = geometry.vertices;
-				var lineDistances = geometry.lineDistances;
+		} else if ( geometry.isGeometry ) {
 
-				for ( var i = 0, l = vertices.length; i < l; i += 2 ) {
+			var vertices = geometry.vertices;
+			var lineDistances = geometry.lineDistances;
 
-					start.copy( vertices[ i ] );
-					end.copy( vertices[ i + 1 ] );
+			for ( var i = 0, l = vertices.length; i < l; i += 2 ) {
 
-					lineDistances[ i ] = ( i === 0 ) ? 0 : lineDistances[ i - 1 ];
-					lineDistances[ i + 1 ] = lineDistances[ i ] + start.distanceTo( end );
+				_start.copy( vertices[ i ] );
+				_end.copy( vertices[ i + 1 ] );
 
-				}
+				lineDistances[ i ] = ( i === 0 ) ? 0 : lineDistances[ i - 1 ];
+				lineDistances[ i + 1 ] = lineDistances[ i ] + _start.distanceTo( _end );
 
 			}
 
-			return this;
+		}
 
-		};
+		return this;
 
-	}() )
+	}
 
 } );
 

+ 220 - 214
src/objects/Mesh.js

@@ -17,6 +17,13 @@ import { BufferGeometry } from '../core/BufferGeometry.js';
  * @author jonobr1 / http://jonobr1.com/
  */
 
+var _inverseMatrix, _ray, _sphere;
+var _vA, _vB, _vC;
+var _tempA, _tempB, _tempC;
+var _morphA, _morphB, _morphC;
+var _uvA, _uvB, _uvC;
+var _intersectionPoint, _intersectionPointWorld;
+
 function Mesh( geometry, material ) {
 
 	Object3D.call( this );
@@ -112,357 +119,356 @@ Mesh.prototype = Object.assign( Object.create( Object3D.prototype ), {
 
 	},
 
-	raycast: ( function () {
+	raycast: function ( raycaster, intersects ) {
 
-		var inverseMatrix = new Matrix4();
-		var ray = new Ray();
-		var sphere = new Sphere();
+		if ( _intersectionPointWorld === undefined ) {
 
-		var vA = new Vector3();
-		var vB = new Vector3();
-		var vC = new Vector3();
+			_inverseMatrix = new Matrix4();
+			_ray = new Ray();
+			_sphere = new Sphere();
 
-		var tempA = new Vector3();
-		var tempB = new Vector3();
-		var tempC = new Vector3();
+			_vA = new Vector3();
+			_vB = new Vector3();
+			_vC = new Vector3();
 
-		var morphA = new Vector3();
-		var morphB = new Vector3();
-		var morphC = new Vector3();
+			_tempA = new Vector3();
+			_tempB = new Vector3();
+			_tempC = new Vector3();
 
-		var uvA = new Vector2();
-		var uvB = new Vector2();
-		var uvC = new Vector2();
+			_morphA = new Vector3();
+			_morphB = new Vector3();
+			_morphC = new Vector3();
 
-		var intersectionPoint = new Vector3();
-		var intersectionPointWorld = new Vector3();
+			_uvA = new Vector2();
+			_uvB = new Vector2();
+			_uvC = new Vector2();
 
-		function checkIntersection( object, material, raycaster, ray, pA, pB, pC, point ) {
+			_intersectionPoint = new Vector3();
+			_intersectionPointWorld = new Vector3();
 
-			var intersect;
+		}
 
-			if ( material.side === BackSide ) {
+		var geometry = this.geometry;
+		var material = this.material;
+		var matrixWorld = this.matrixWorld;
 
-				intersect = ray.intersectTriangle( pC, pB, pA, true, point );
+		if ( material === undefined ) return;
 
-			} else {
+		// Checking boundingSphere distance to ray
 
-				intersect = ray.intersectTriangle( pA, pB, pC, material.side !== DoubleSide, point );
+		if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
 
-			}
+		_sphere.copy( geometry.boundingSphere );
+		_sphere.applyMatrix4( matrixWorld );
 
-			if ( intersect === null ) return null;
+		if ( raycaster.ray.intersectsSphere( _sphere ) === false ) return;
 
-			intersectionPointWorld.copy( point );
-			intersectionPointWorld.applyMatrix4( object.matrixWorld );
+		//
 
-			var distance = raycaster.ray.origin.distanceTo( intersectionPointWorld );
+		_inverseMatrix.getInverse( matrixWorld );
+		_ray.copy( raycaster.ray ).applyMatrix4( _inverseMatrix );
 
-			if ( distance < raycaster.near || distance > raycaster.far ) return null;
+		// Check boundingBox before continuing
 
-			return {
-				distance: distance,
-				point: intersectionPointWorld.clone(),
-				object: object
-			};
+		if ( geometry.boundingBox !== null ) {
 
-		}
+			if ( _ray.intersectsBox( geometry.boundingBox ) === false ) return;
 
-		function checkBufferGeometryIntersection( object, material, raycaster, ray, position, morphPosition, uv, uv2, a, b, c ) {
+		}
 
-			vA.fromBufferAttribute( position, a );
-			vB.fromBufferAttribute( position, b );
-			vC.fromBufferAttribute( position, c );
+		var intersection;
 
-			var morphInfluences = object.morphTargetInfluences;
+		if ( geometry.isBufferGeometry ) {
 
-			if ( material.morphTargets && morphPosition && morphInfluences ) {
+			var a, b, c;
+			var index = geometry.index;
+			var position = geometry.attributes.position;
+			var morphPosition = geometry.morphAttributes.position;
+			var uv = geometry.attributes.uv;
+			var uv2 = geometry.attributes.uv2;
+			var groups = geometry.groups;
+			var drawRange = geometry.drawRange;
+			var i, j, il, jl;
+			var group, groupMaterial;
+			var start, end;
 
-				morphA.set( 0, 0, 0 );
-				morphB.set( 0, 0, 0 );
-				morphC.set( 0, 0, 0 );
+			if ( index !== null ) {
 
-				for ( var i = 0, il = morphPosition.length; i < il; i ++ ) {
+				// indexed buffer geometry
 
-					var influence = morphInfluences[ i ];
-					var morphAttribute = morphPosition[ i ];
+				if ( Array.isArray( material ) ) {
 
-					if ( influence === 0 ) continue;
+					for ( i = 0, il = groups.length; i < il; i ++ ) {
 
-					tempA.fromBufferAttribute( morphAttribute, a );
-					tempB.fromBufferAttribute( morphAttribute, b );
-					tempC.fromBufferAttribute( morphAttribute, c );
+						group = groups[ i ];
+						groupMaterial = material[ group.materialIndex ];
 
-					morphA.addScaledVector( tempA.sub( vA ), influence );
-					morphB.addScaledVector( tempB.sub( vB ), influence );
-					morphC.addScaledVector( tempC.sub( vC ), influence );
+						start = Math.max( group.start, drawRange.start );
+						end = Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) );
 
-				}
+						for ( j = start, jl = end; j < jl; j += 3 ) {
 
-				vA.add( morphA );
-				vB.add( morphB );
-				vC.add( morphC );
+							a = index.getX( j );
+							b = index.getX( j + 1 );
+							c = index.getX( j + 2 );
 
-			}
+							intersection = checkBufferGeometryIntersection( this, groupMaterial, raycaster, _ray, position, morphPosition, uv, uv2, a, b, c );
 
-			var intersection = checkIntersection( object, material, raycaster, ray, vA, vB, vC, intersectionPoint );
-
-			if ( intersection ) {
+							if ( intersection ) {
 
-				if ( uv ) {
+								intersection.faceIndex = Math.floor( j / 3 ); // triangle number in indexed buffer semantics
+								intersection.face.materialIndex = group.materialIndex;
+								intersects.push( intersection );
 
-					uvA.fromBufferAttribute( uv, a );
-					uvB.fromBufferAttribute( uv, b );
-					uvC.fromBufferAttribute( uv, c );
+							}
 
-					intersection.uv = Triangle.getUV( intersectionPoint, vA, vB, vC, uvA, uvB, uvC, new Vector2() );
+						}
 
-				}
+					}
 
-				if ( uv2 ) {
+				} else {
 
-					uvA.fromBufferAttribute( uv2, a );
-					uvB.fromBufferAttribute( uv2, b );
-					uvC.fromBufferAttribute( uv2, c );
+					start = Math.max( 0, drawRange.start );
+					end = Math.min( index.count, ( drawRange.start + drawRange.count ) );
 
-					intersection.uv2 = Triangle.getUV( intersectionPoint, vA, vB, vC, uvA, uvB, uvC, new Vector2() );
+					for ( i = start, il = end; i < il; i += 3 ) {
 
-				}
+						a = index.getX( i );
+						b = index.getX( i + 1 );
+						c = index.getX( i + 2 );
 
-				var face = new Face3( a, b, c );
-				Triangle.getNormal( vA, vB, vC, face.normal );
+						intersection = checkBufferGeometryIntersection( this, material, raycaster, _ray, position, morphPosition, uv, uv2, a, b, c );
 
-				intersection.face = face;
+						if ( intersection ) {
 
-			}
+							intersection.faceIndex = Math.floor( i / 3 ); // triangle number in indexed buffer semantics
+							intersects.push( intersection );
 
-			return intersection;
+						}
 
-		}
+					}
 
-		return function raycast( raycaster, intersects ) {
+				}
 
-			var geometry = this.geometry;
-			var material = this.material;
-			var matrixWorld = this.matrixWorld;
+			} else if ( position !== undefined ) {
 
-			if ( material === undefined ) return;
+				// non-indexed buffer geometry
 
-			// Checking boundingSphere distance to ray
+				if ( Array.isArray( material ) ) {
 
-			if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
+					for ( i = 0, il = groups.length; i < il; i ++ ) {
 
-			sphere.copy( geometry.boundingSphere );
-			sphere.applyMatrix4( matrixWorld );
+						group = groups[ i ];
+						groupMaterial = material[ group.materialIndex ];
 
-			if ( raycaster.ray.intersectsSphere( sphere ) === false ) return;
+						start = Math.max( group.start, drawRange.start );
+						end = Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) );
 
-			//
+						for ( j = start, jl = end; j < jl; j += 3 ) {
 
-			inverseMatrix.getInverse( matrixWorld );
-			ray.copy( raycaster.ray ).applyMatrix4( inverseMatrix );
+							a = j;
+							b = j + 1;
+							c = j + 2;
 
-			// Check boundingBox before continuing
+							intersection = checkBufferGeometryIntersection( this, groupMaterial, raycaster, _ray, position, morphPosition, uv, uv2, a, b, c );
 
-			if ( geometry.boundingBox !== null ) {
+							if ( intersection ) {
 
-				if ( ray.intersectsBox( geometry.boundingBox ) === false ) return;
+								intersection.faceIndex = Math.floor( j / 3 ); // triangle number in non-indexed buffer semantics
+								intersection.face.materialIndex = group.materialIndex;
+								intersects.push( intersection );
 
-			}
+							}
 
-			var intersection;
+						}
 
-			if ( geometry.isBufferGeometry ) {
+					}
 
-				var a, b, c;
-				var index = geometry.index;
-				var position = geometry.attributes.position;
-				var morphPosition = geometry.morphAttributes.position;
-				var uv = geometry.attributes.uv;
-				var uv2 = geometry.attributes.uv2;
-				var groups = geometry.groups;
-				var drawRange = geometry.drawRange;
-				var i, j, il, jl;
-				var group, groupMaterial;
-				var start, end;
+				} else {
 
-				if ( index !== null ) {
+					start = Math.max( 0, drawRange.start );
+					end = Math.min( position.count, ( drawRange.start + drawRange.count ) );
 
-					// indexed buffer geometry
+					for ( i = start, il = end; i < il; i += 3 ) {
 
-					if ( Array.isArray( material ) ) {
+						a = i;
+						b = i + 1;
+						c = i + 2;
 
-						for ( i = 0, il = groups.length; i < il; i ++ ) {
+						intersection = checkBufferGeometryIntersection( this, material, raycaster, _ray, position, morphPosition, uv, uv2, a, b, c );
 
-							group = groups[ i ];
-							groupMaterial = material[ group.materialIndex ];
+						if ( intersection ) {
 
-							start = Math.max( group.start, drawRange.start );
-							end = Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) );
+							intersection.faceIndex = Math.floor( i / 3 ); // triangle number in non-indexed buffer semantics
+							intersects.push( intersection );
 
-							for ( j = start, jl = end; j < jl; j += 3 ) {
+						}
 
-								a = index.getX( j );
-								b = index.getX( j + 1 );
-								c = index.getX( j + 2 );
+					}
 
-								intersection = checkBufferGeometryIntersection( this, groupMaterial, raycaster, ray, position, morphPosition, uv, uv2, a, b, c );
+				}
 
-								if ( intersection ) {
+			}
 
-									intersection.faceIndex = Math.floor( j / 3 ); // triangle number in indexed buffer semantics
-									intersection.face.materialIndex = group.materialIndex;
-									intersects.push( intersection );
+		} else if ( geometry.isGeometry ) {
 
-								}
+			var fvA, fvB, fvC;
+			var isMultiMaterial = Array.isArray( material );
 
-							}
+			var vertices = geometry.vertices;
+			var faces = geometry.faces;
+			var uvs;
 
-						}
+			var faceVertexUvs = geometry.faceVertexUvs[ 0 ];
+			if ( faceVertexUvs.length > 0 ) uvs = faceVertexUvs;
 
-					} else {
+			for ( var f = 0, fl = faces.length; f < fl; f ++ ) {
 
-						start = Math.max( 0, drawRange.start );
-						end = Math.min( index.count, ( drawRange.start + drawRange.count ) );
+				var face = faces[ f ];
+				var faceMaterial = isMultiMaterial ? material[ face.materialIndex ] : material;
 
-						for ( i = start, il = end; i < il; i += 3 ) {
+				if ( faceMaterial === undefined ) continue;
 
-							a = index.getX( i );
-							b = index.getX( i + 1 );
-							c = index.getX( i + 2 );
+				fvA = vertices[ face.a ];
+				fvB = vertices[ face.b ];
+				fvC = vertices[ face.c ];
 
-							intersection = checkBufferGeometryIntersection( this, material, raycaster, ray, position, morphPosition, uv, uv2, a, b, c );
+				intersection = checkIntersection( this, faceMaterial, raycaster, _ray, fvA, fvB, fvC, _intersectionPoint );
 
-							if ( intersection ) {
+				if ( intersection ) {
 
-								intersection.faceIndex = Math.floor( i / 3 ); // triangle number in indexed buffer semantics
-								intersects.push( intersection );
+					if ( uvs && uvs[ f ] ) {
 
-							}
+						var uvs_f = uvs[ f ];
+						_uvA.copy( uvs_f[ 0 ] );
+						_uvB.copy( uvs_f[ 1 ] );
+						_uvC.copy( uvs_f[ 2 ] );
 
-						}
+						intersection.uv = Triangle.getUV( _intersectionPoint, fvA, fvB, fvC, _uvA, _uvB, _uvC, new Vector2() );
 
 					}
 
-				} else if ( position !== undefined ) {
+					intersection.face = face;
+					intersection.faceIndex = f;
+					intersects.push( intersection );
 
-					// non-indexed buffer geometry
+				}
 
-					if ( Array.isArray( material ) ) {
+			}
 
-						for ( i = 0, il = groups.length; i < il; i ++ ) {
+		}
 
-							group = groups[ i ];
-							groupMaterial = material[ group.materialIndex ];
+	},
 
-							start = Math.max( group.start, drawRange.start );
-							end = Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) );
+	clone: function () {
 
-							for ( j = start, jl = end; j < jl; j += 3 ) {
+		return new this.constructor( this.geometry, this.material ).copy( this );
 
-								a = j;
-								b = j + 1;
-								c = j + 2;
+	}
 
-								intersection = checkBufferGeometryIntersection( this, groupMaterial, raycaster, ray, position, morphPosition, uv, uv2, a, b, c );
+} );
 
-								if ( intersection ) {
+function checkIntersection( object, material, raycaster, ray, pA, pB, pC, point ) {
 
-									intersection.faceIndex = Math.floor( j / 3 ); // triangle number in non-indexed buffer semantics
-									intersection.face.materialIndex = group.materialIndex;
-									intersects.push( intersection );
+	var intersect;
 
-								}
+	if ( material.side === BackSide ) {
 
-							}
+		intersect = ray.intersectTriangle( pC, pB, pA, true, point );
 
-						}
+	} else {
 
-					} else {
+		intersect = ray.intersectTriangle( pA, pB, pC, material.side !== DoubleSide, point );
 
-						start = Math.max( 0, drawRange.start );
-						end = Math.min( position.count, ( drawRange.start + drawRange.count ) );
+	}
 
-						for ( i = start, il = end; i < il; i += 3 ) {
+	if ( intersect === null ) return null;
 
-							a = i;
-							b = i + 1;
-							c = i + 2;
+	_intersectionPointWorld.copy( point );
+	_intersectionPointWorld.applyMatrix4( object.matrixWorld );
 
-							intersection = checkBufferGeometryIntersection( this, material, raycaster, ray, position, morphPosition, uv, uv2, a, b, c );
+	var distance = raycaster.ray.origin.distanceTo( _intersectionPointWorld );
 
-							if ( intersection ) {
+	if ( distance < raycaster.near || distance > raycaster.far ) return null;
 
-								intersection.faceIndex = Math.floor( i / 3 ); // triangle number in non-indexed buffer semantics
-								intersects.push( intersection );
+	return {
+		distance: distance,
+		point: _intersectionPointWorld.clone(),
+		object: object
+	};
 
-							}
+}
 
-						}
+function checkBufferGeometryIntersection( object, material, raycaster, ray, position, morphPosition, uv, uv2, a, b, c ) {
 
-					}
+	_vA.fromBufferAttribute( position, a );
+	_vB.fromBufferAttribute( position, b );
+	_vC.fromBufferAttribute( position, c );
 
-				}
+	var morphInfluences = object.morphTargetInfluences;
 
-			} else if ( geometry.isGeometry ) {
+	if ( material.morphTargets && morphPosition && morphInfluences ) {
 
-				var fvA, fvB, fvC;
-				var isMultiMaterial = Array.isArray( material );
+		_morphA.set( 0, 0, 0 );
+		_morphB.set( 0, 0, 0 );
+		_morphC.set( 0, 0, 0 );
 
-				var vertices = geometry.vertices;
-				var faces = geometry.faces;
-				var uvs;
+		for ( var i = 0, il = morphPosition.length; i < il; i ++ ) {
 
-				var faceVertexUvs = geometry.faceVertexUvs[ 0 ];
-				if ( faceVertexUvs.length > 0 ) uvs = faceVertexUvs;
+			var influence = morphInfluences[ i ];
+			var morphAttribute = morphPosition[ i ];
 
-				for ( var f = 0, fl = faces.length; f < fl; f ++ ) {
+			if ( influence === 0 ) continue;
 
-					var face = faces[ f ];
-					var faceMaterial = isMultiMaterial ? material[ face.materialIndex ] : material;
+			_tempA.fromBufferAttribute( morphAttribute, a );
+			_tempB.fromBufferAttribute( morphAttribute, b );
+			_tempC.fromBufferAttribute( morphAttribute, c );
 
-					if ( faceMaterial === undefined ) continue;
+			_morphA.addScaledVector( _tempA.sub( _vA ), influence );
+			_morphB.addScaledVector( _tempB.sub( _vB ), influence );
+			_morphC.addScaledVector( _tempC.sub( _vC ), influence );
 
-					fvA = vertices[ face.a ];
-					fvB = vertices[ face.b ];
-					fvC = vertices[ face.c ];
+		}
 
-					intersection = checkIntersection( this, faceMaterial, raycaster, ray, fvA, fvB, fvC, intersectionPoint );
+		_vA.add( _morphA );
+		_vB.add( _morphB );
+		_vC.add( _morphC );
 
-					if ( intersection ) {
+	}
 
-						if ( uvs && uvs[ f ] ) {
+	var intersection = checkIntersection( object, material, raycaster, ray, _vA, _vB, _vC, _intersectionPoint );
 
-							var uvs_f = uvs[ f ];
-							uvA.copy( uvs_f[ 0 ] );
-							uvB.copy( uvs_f[ 1 ] );
-							uvC.copy( uvs_f[ 2 ] );
+	if ( intersection ) {
 
-							intersection.uv = Triangle.getUV( intersectionPoint, fvA, fvB, fvC, uvA, uvB, uvC, new Vector2() );
+		if ( uv ) {
 
-						}
+			_uvA.fromBufferAttribute( uv, a );
+			_uvB.fromBufferAttribute( uv, b );
+			_uvC.fromBufferAttribute( uv, c );
 
-						intersection.face = face;
-						intersection.faceIndex = f;
-						intersects.push( intersection );
+			intersection.uv = Triangle.getUV( _intersectionPoint, _vA, _vB, _vC, _uvA, _uvB, _uvC, new Vector2() );
 
-					}
+		}
 
-				}
+		if ( uv2 ) {
 
-			}
+			_uvA.fromBufferAttribute( uv2, a );
+			_uvB.fromBufferAttribute( uv2, b );
+			_uvC.fromBufferAttribute( uv2, c );
 
-		};
+			intersection.uv2 = Triangle.getUV( _intersectionPoint, _vA, _vB, _vC, _uvA, _uvB, _uvC, new Vector2() );
 
-	}() ),
+		}
 
-	clone: function () {
+		var face = new Face3( a, b, c );
+		Triangle.getNormal( _vA, _vB, _vC, face.normal );
 
-		return new this.constructor( this.geometry, this.material ).copy( this );
+		intersection.face = face;
 
 	}
 
-} );
+	return intersection;
 
+}
 
 export { Mesh };

+ 63 - 61
src/objects/Points.js

@@ -10,6 +10,8 @@ import { BufferGeometry } from '../core/BufferGeometry.js';
  * @author alteredq / http://alteredqualia.com/
  */
 
+var _inverseMatrix, _ray, _sphere;
+
 function Points( geometry, material ) {
 
 	Object3D.call( this );
@@ -29,114 +31,114 @@ Points.prototype = Object.assign( Object.create( Object3D.prototype ), {
 
 	isPoints: true,
 
-	raycast: ( function () {
+	raycast: function ( raycaster, intersects ) {
 
-		var inverseMatrix = new Matrix4();
-		var ray = new Ray();
-		var sphere = new Sphere();
+		if ( _sphere === undefined ) {
 
-		return function raycast( raycaster, intersects ) {
+			_inverseMatrix = new Matrix4();
+			_ray = new Ray();
+			_sphere = new Sphere();
 
-			var object = this;
-			var geometry = this.geometry;
-			var matrixWorld = this.matrixWorld;
-			var threshold = raycaster.params.Points.threshold;
+		}
 
-			// Checking boundingSphere distance to ray
+		var object = this;
+		var geometry = this.geometry;
+		var matrixWorld = this.matrixWorld;
+		var threshold = raycaster.params.Points.threshold;
 
-			if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
+		// Checking boundingSphere distance to ray
 
-			sphere.copy( geometry.boundingSphere );
-			sphere.applyMatrix4( matrixWorld );
-			sphere.radius += threshold;
+		if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
 
-			if ( raycaster.ray.intersectsSphere( sphere ) === false ) return;
+		_sphere.copy( geometry.boundingSphere );
+		_sphere.applyMatrix4( matrixWorld );
+		_sphere.radius += threshold;
 
-			//
+		if ( raycaster.ray.intersectsSphere( _sphere ) === false ) return;
 
-			inverseMatrix.getInverse( matrixWorld );
-			ray.copy( raycaster.ray ).applyMatrix4( inverseMatrix );
+		//
 
-			var localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 );
-			var localThresholdSq = localThreshold * localThreshold;
-			var position = new Vector3();
-			var intersectPoint = new Vector3();
+		_inverseMatrix.getInverse( matrixWorld );
+		_ray.copy( raycaster.ray ).applyMatrix4( _inverseMatrix );
 
-			function testPoint( point, index ) {
+		var localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 );
+		var localThresholdSq = localThreshold * localThreshold;
+		var position = new Vector3();
+		var intersectPoint = new Vector3();
 
-				var rayPointDistanceSq = ray.distanceSqToPoint( point );
+		function testPoint( point, index ) {
 
-				if ( rayPointDistanceSq < localThresholdSq ) {
+			var rayPointDistanceSq = _ray.distanceSqToPoint( point );
 
-					ray.closestPointToPoint( point, intersectPoint );
-					intersectPoint.applyMatrix4( matrixWorld );
+			if ( rayPointDistanceSq < localThresholdSq ) {
 
-					var distance = raycaster.ray.origin.distanceTo( intersectPoint );
+				_ray.closestPointToPoint( point, intersectPoint );
+				intersectPoint.applyMatrix4( matrixWorld );
 
-					if ( distance < raycaster.near || distance > raycaster.far ) return;
+				var distance = raycaster.ray.origin.distanceTo( intersectPoint );
 
-					intersects.push( {
+				if ( distance < raycaster.near || distance > raycaster.far ) return;
 
-						distance: distance,
-						distanceToRay: Math.sqrt( rayPointDistanceSq ),
-						point: intersectPoint.clone(),
-						index: index,
-						face: null,
-						object: object
+				intersects.push( {
 
-					} );
+					distance: distance,
+					distanceToRay: Math.sqrt( rayPointDistanceSq ),
+					point: intersectPoint.clone(),
+					index: index,
+					face: null,
+					object: object
 
-				}
+				} );
 
 			}
 
-			if ( geometry.isBufferGeometry ) {
+		}
 
-				var index = geometry.index;
-				var attributes = geometry.attributes;
-				var positions = attributes.position.array;
+		if ( geometry.isBufferGeometry ) {
 
-				if ( index !== null ) {
+			var index = geometry.index;
+			var attributes = geometry.attributes;
+			var positions = attributes.position.array;
 
-					var indices = index.array;
+			if ( index !== null ) {
 
-					for ( var i = 0, il = indices.length; i < il; i ++ ) {
+				var indices = index.array;
 
-						var a = indices[ i ];
+				for ( var i = 0, il = indices.length; i < il; i ++ ) {
 
-						position.fromArray( positions, a * 3 );
+					var a = indices[ i ];
 
-						testPoint( position, a );
+					position.fromArray( positions, a * 3 );
 
-					}
+					testPoint( position, a );
 
-				} else {
+				}
 
-					for ( var i = 0, l = positions.length / 3; i < l; i ++ ) {
+			} else {
 
-						position.fromArray( positions, i * 3 );
+				for ( var i = 0, l = positions.length / 3; i < l; i ++ ) {
 
-						testPoint( position, i );
+					position.fromArray( positions, i * 3 );
 
-					}
+					testPoint( position, i );
 
 				}
 
-			} else {
+			}
 
-				var vertices = geometry.vertices;
+		} else {
 
-				for ( var i = 0, l = vertices.length; i < l; i ++ ) {
+			var vertices = geometry.vertices;
 
-					testPoint( vertices[ i ], i );
+			for ( var i = 0, l = vertices.length; i < l; i ++ ) {
 
-				}
+				testPoint( vertices[ i ], i );
 
 			}
 
-		};
+		}
 
-	}() ),
+	},
 
 	updateMorphTargets: function () {
 

+ 22 - 20
src/objects/Skeleton.js

@@ -7,6 +7,8 @@ import { Matrix4 } from '../math/Matrix4.js';
  * @author ikerr / http://verold.com
  */
 
+var _offsetMatrix, _identityMatrix;
+
 function Skeleton( bones, boneInverses ) {
 
 	// copy the bone array
@@ -113,40 +115,40 @@ Object.assign( Skeleton.prototype, {
 
 	},
 
-	update: ( function () {
+	update: function () {
 
-		var offsetMatrix = new Matrix4();
-		var identityMatrix = new Matrix4();
+		if ( _identityMatrix ) {
 
-		return function update() {
+			_offsetMatrix = new Matrix4();
+			_identityMatrix = new Matrix4();
 
-			var bones = this.bones;
-			var boneInverses = this.boneInverses;
-			var boneMatrices = this.boneMatrices;
-			var boneTexture = this.boneTexture;
+		}
 
-			// flatten bone matrices to array
+		var bones = this.bones;
+		var boneInverses = this.boneInverses;
+		var boneMatrices = this.boneMatrices;
+		var boneTexture = this.boneTexture;
 
-			for ( var i = 0, il = bones.length; i < il; i ++ ) {
+		// flatten bone matrices to array
 
-				// compute the offset between the current and the original transform
+		for ( var i = 0, il = bones.length; i < il; i ++ ) {
 
-				var matrix = bones[ i ] ? bones[ i ].matrixWorld : identityMatrix;
+			// compute the offset between the current and the original transform
 
-				offsetMatrix.multiplyMatrices( matrix, boneInverses[ i ] );
-				offsetMatrix.toArray( boneMatrices, i * 16 );
+			var matrix = bones[ i ] ? bones[ i ].matrixWorld : _identityMatrix;
 
-			}
+			_offsetMatrix.multiplyMatrices( matrix, boneInverses[ i ] );
+			_offsetMatrix.toArray( boneMatrices, i * 16 );
 
-			if ( boneTexture !== undefined ) {
+		}
 
-				boneTexture.needsUpdate = true;
+		if ( boneTexture !== undefined ) {
 
-			}
+			boneTexture.needsUpdate = true;
 
-		};
+		}
 
-	} )(),
+	},
 
 	clone: function () {
 

+ 92 - 87
src/objects/Sprite.js

@@ -13,7 +13,12 @@ import { InterleavedBuffer } from '../core/InterleavedBuffer.js';
 import { InterleavedBufferAttribute } from '../core/InterleavedBufferAttribute.js';
 import { SpriteMaterial } from '../materials/SpriteMaterial.js';
 
-var geometry;
+var _geometry;
+
+var _intersectPoint, _worldScale, _mvPosition;
+var _alignedPosition, _rotatedPosition, _viewWorldMatrix;
+var _vA, _vB, _vC;
+var _uvA, _uvB, _uvC;
 
 function Sprite( material ) {
 
@@ -21,9 +26,9 @@ function Sprite( material ) {
 
 	this.type = 'Sprite';
 
-	if ( geometry === undefined ) {
+	if ( _geometry === undefined ) {
 
-		geometry = new BufferGeometry();
+		_geometry = new BufferGeometry();
 
 		var float32Array = new Float32Array( [
 			- 0.5, - 0.5, 0, 0, 0,
@@ -34,13 +39,13 @@ function Sprite( material ) {
 
 		var interleavedBuffer = new InterleavedBuffer( float32Array, 5 );
 
-		geometry.setIndex( [ 0, 1, 2,	0, 2, 3 ] );
-		geometry.addAttribute( 'position', new InterleavedBufferAttribute( interleavedBuffer, 3, 0, false ) );
-		geometry.addAttribute( 'uv', new InterleavedBufferAttribute( interleavedBuffer, 2, 3, false ) );
+		_geometry.setIndex( [ 0, 1, 2,	0, 2, 3 ] );
+		_geometry.addAttribute( 'position', new InterleavedBufferAttribute( interleavedBuffer, 3, 0, false ) );
+		_geometry.addAttribute( 'uv', new InterleavedBufferAttribute( interleavedBuffer, 2, 3, false ) );
 
 	}
 
-	this.geometry = geometry;
+	this.geometry = _geometry;
 	this.material = ( material !== undefined ) ? material : new SpriteMaterial();
 
 	this.center = new Vector2( 0.5, 0.5 );
@@ -53,120 +58,93 @@ Sprite.prototype = Object.assign( Object.create( Object3D.prototype ), {
 
 	isSprite: true,
 
-	raycast: ( function () {
-
-		var intersectPoint = new Vector3();
-		var worldScale = new Vector3();
-		var mvPosition = new Vector3();
-
-		var alignedPosition = new Vector2();
-		var rotatedPosition = new Vector2();
-		var viewWorldMatrix = new Matrix4();
-
-		var vA = new Vector3();
-		var vB = new Vector3();
-		var vC = new Vector3();
+	raycast: function ( raycaster, intersects ) {
 
-		var uvA = new Vector2();
-		var uvB = new Vector2();
-		var uvC = new Vector2();
+		if ( _uvC === undefined ) {
 
-		function transformVertex( vertexPosition, mvPosition, center, scale, sin, cos ) {
+			_intersectPoint = new Vector3();
+			_worldScale = new Vector3();
+			_mvPosition = new Vector3();
 
-			// compute position in camera space
-			alignedPosition.subVectors( vertexPosition, center ).addScalar( 0.5 ).multiply( scale );
+			_alignedPosition = new Vector2();
+			_rotatedPosition = new Vector2();
+			_viewWorldMatrix = new Matrix4();
 
-			// to check if rotation is not zero
-			if ( sin !== undefined ) {
+			_vA = new Vector3();
+			_vB = new Vector3();
+			_vC = new Vector3();
 
-				rotatedPosition.x = ( cos * alignedPosition.x ) - ( sin * alignedPosition.y );
-				rotatedPosition.y = ( sin * alignedPosition.x ) + ( cos * alignedPosition.y );
+			_uvA = new Vector2();
+			_uvB = new Vector2();
+			_uvC = new Vector2();
 
-			} else {
+		}
 
-				rotatedPosition.copy( alignedPosition );
+		_worldScale.setFromMatrixScale( this.matrixWorld );
 
-			}
+		_viewWorldMatrix.copy( raycaster._camera.matrixWorld );
+		this.modelViewMatrix.multiplyMatrices( raycaster._camera.matrixWorldInverse, this.matrixWorld );
 
+		_mvPosition.setFromMatrixPosition( this.modelViewMatrix );
 
-			vertexPosition.copy( mvPosition );
-			vertexPosition.x += rotatedPosition.x;
-			vertexPosition.y += rotatedPosition.y;
+		if ( raycaster._camera.isPerspectiveCamera && this.material.sizeAttenuation === false ) {
 
-			// transform to world space
-			vertexPosition.applyMatrix4( viewWorldMatrix );
+			_worldScale.multiplyScalar( - _mvPosition.z );
 
 		}
 
-		return function raycast( raycaster, intersects ) {
-
-			worldScale.setFromMatrixScale( this.matrixWorld );
-
-			viewWorldMatrix.copy( raycaster._camera.matrixWorld );
-			this.modelViewMatrix.multiplyMatrices( raycaster._camera.matrixWorldInverse, this.matrixWorld );
+		var rotation = this.material.rotation;
+		var sin, cos;
+		if ( rotation !== 0 ) {
 
-			mvPosition.setFromMatrixPosition( this.modelViewMatrix );
+			cos = Math.cos( rotation );
+			sin = Math.sin( rotation );
 
-			if ( raycaster._camera.isPerspectiveCamera && this.material.sizeAttenuation === false ) {
-
-				worldScale.multiplyScalar( - mvPosition.z );
-
-			}
-
-			var rotation = this.material.rotation;
-			var sin, cos;
-			if ( rotation !== 0 ) {
+		}
 
-				cos = Math.cos( rotation );
-				sin = Math.sin( rotation );
+		var center = this.center;
 
-			}
+		transformVertex( _vA.set( - 0.5, - 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
+		transformVertex( _vB.set( 0.5, - 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
+		transformVertex( _vC.set( 0.5, 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
 
-			var center = this.center;
+		_uvA.set( 0, 0 );
+		_uvB.set( 1, 0 );
+		_uvC.set( 1, 1 );
 
-			transformVertex( vA.set( - 0.5, - 0.5, 0 ), mvPosition, center, worldScale, sin, cos );
-			transformVertex( vB.set( 0.5, - 0.5, 0 ), mvPosition, center, worldScale, sin, cos );
-			transformVertex( vC.set( 0.5, 0.5, 0 ), mvPosition, center, worldScale, sin, cos );
+		// check first triangle
+		var intersect = raycaster.ray.intersectTriangle( _vA, _vB, _vC, false, _intersectPoint );
 
-			uvA.set( 0, 0 );
-			uvB.set( 1, 0 );
-			uvC.set( 1, 1 );
+		if ( intersect === null ) {
 
-			// check first triangle
-			var intersect = raycaster.ray.intersectTriangle( vA, vB, vC, false, intersectPoint );
+			// check second triangle
+			transformVertex( _vB.set( - 0.5, 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
+			_uvB.set( 0, 1 );
 
+			intersect = raycaster.ray.intersectTriangle( _vA, _vC, _vB, false, _intersectPoint );
 			if ( intersect === null ) {
 
-				// check second triangle
-				transformVertex( vB.set( - 0.5, 0.5, 0 ), mvPosition, center, worldScale, sin, cos );
-				uvB.set( 0, 1 );
-
-				intersect = raycaster.ray.intersectTriangle( vA, vC, vB, false, intersectPoint );
-				if ( intersect === null ) {
-
-					return;
-
-				}
+				return;
 
 			}
 
-			var distance = raycaster.ray.origin.distanceTo( intersectPoint );
+		}
 
-			if ( distance < raycaster.near || distance > raycaster.far ) return;
+		var distance = raycaster.ray.origin.distanceTo( _intersectPoint );
 
-			intersects.push( {
+		if ( distance < raycaster.near || distance > raycaster.far ) return;
 
-				distance: distance,
-				point: intersectPoint.clone(),
-				uv: Triangle.getUV( intersectPoint, vA, vB, vC, uvA, uvB, uvC, new Vector2() ),
-				face: null,
-				object: this
+		intersects.push( {
 
-			} );
+			distance: distance,
+			point: _intersectPoint.clone(),
+			uv: Triangle.getUV( _intersectPoint, _vA, _vB, _vC, _uvA, _uvB, _uvC, new Vector2() ),
+			face: null,
+			object: this
 
-		};
+		} );
 
-	}() ),
+	},
 
 	clone: function () {
 
@@ -187,4 +165,31 @@ Sprite.prototype = Object.assign( Object.create( Object3D.prototype ), {
 
 } );
 
+function transformVertex( vertexPosition, mvPosition, center, scale, sin, cos ) {
+
+	// compute position in camera space
+	_alignedPosition.subVectors( vertexPosition, center ).addScalar( 0.5 ).multiply( scale );
+
+	// to check if rotation is not zero
+	if ( sin !== undefined ) {
+
+		_rotatedPosition.x = ( cos * _alignedPosition.x ) - ( sin * _alignedPosition.y );
+		_rotatedPosition.y = ( sin * _alignedPosition.x ) + ( cos * _alignedPosition.y );
+
+	} else {
+
+		_rotatedPosition.copy( _alignedPosition );
+
+	}
+
+
+	vertexPosition.copy( mvPosition );
+	vertexPosition.x += _rotatedPosition.x;
+	vertexPosition.y += _rotatedPosition.y;
+
+	// transform to world space
+	vertexPosition.applyMatrix4( _viewWorldMatrix );
+
+}
+
 export { Sprite };