Browse Source

Math: Remove closures part III.

Mugen87 6 years ago
parent
commit
0aeeb7dae8
4 changed files with 456 additions and 483 deletions
  1. 20 24
      src/math/Math.js
  2. 114 118
      src/math/Matrix4.js
  3. 171 182
      src/math/Ray.js
  4. 151 159
      src/math/Triangle.js

+ 20 - 24
src/math/Math.js

@@ -3,40 +3,36 @@
  * @author mrdoob / http://mrdoob.com/
  * @author mrdoob / http://mrdoob.com/
  */
  */
 
 
-var _Math = {
-
-	DEG2RAD: Math.PI / 180,
-	RAD2DEG: 180 / Math.PI,
-
-	generateUUID: ( function () {
+var lut = [];
 
 
-		// http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/21963136#21963136
+for ( var i = 0; i < 256; i ++ ) {
 
 
-		var lut = [];
+	lut[ i ] = ( i < 16 ? '0' : '' ) + ( i ).toString( 16 );
 
 
-		for ( var i = 0; i < 256; i ++ ) {
+}
 
 
-			lut[ i ] = ( i < 16 ? '0' : '' ) + ( i ).toString( 16 );
+var _Math = {
 
 
-		}
+	DEG2RAD: Math.PI / 180,
+	RAD2DEG: 180 / Math.PI,
 
 
-		return function generateUUID() {
+	generateUUID: function () {
 
 
-			var d0 = Math.random() * 0xffffffff | 0;
-			var d1 = Math.random() * 0xffffffff | 0;
-			var d2 = Math.random() * 0xffffffff | 0;
-			var d3 = Math.random() * 0xffffffff | 0;
-			var uuid = lut[ d0 & 0xff ] + lut[ d0 >> 8 & 0xff ] + lut[ d0 >> 16 & 0xff ] + lut[ d0 >> 24 & 0xff ] + '-' +
-				lut[ d1 & 0xff ] + lut[ d1 >> 8 & 0xff ] + '-' + lut[ d1 >> 16 & 0x0f | 0x40 ] + lut[ d1 >> 24 & 0xff ] + '-' +
-				lut[ d2 & 0x3f | 0x80 ] + lut[ d2 >> 8 & 0xff ] + '-' + lut[ d2 >> 16 & 0xff ] + lut[ d2 >> 24 & 0xff ] +
-				lut[ d3 & 0xff ] + lut[ d3 >> 8 & 0xff ] + lut[ d3 >> 16 & 0xff ] + lut[ d3 >> 24 & 0xff ];
+		// http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/21963136#21963136
 
 
-			// .toUpperCase() here flattens concatenated strings to save heap memory space.
-			return uuid.toUpperCase();
+		var d0 = Math.random() * 0xffffffff | 0;
+		var d1 = Math.random() * 0xffffffff | 0;
+		var d2 = Math.random() * 0xffffffff | 0;
+		var d3 = Math.random() * 0xffffffff | 0;
+		var uuid = lut[ d0 & 0xff ] + lut[ d0 >> 8 & 0xff ] + lut[ d0 >> 16 & 0xff ] + lut[ d0 >> 24 & 0xff ] + '-' +
+			lut[ d1 & 0xff ] + lut[ d1 >> 8 & 0xff ] + '-' + lut[ d1 >> 16 & 0x0f | 0x40 ] + lut[ d1 >> 24 & 0xff ] + '-' +
+			lut[ d2 & 0x3f | 0x80 ] + lut[ d2 >> 8 & 0xff ] + '-' + lut[ d2 >> 16 & 0xff ] + lut[ d2 >> 24 & 0xff ] +
+			lut[ d3 & 0xff ] + lut[ d3 >> 8 & 0xff ] + lut[ d3 >> 16 & 0xff ] + lut[ d3 >> 24 & 0xff ];
 
 
-		};
+		// .toUpperCase() here flattens concatenated strings to save heap memory space.
+		return uuid.toUpperCase();
 
 
-	} )(),
+	},
 
 
 	clamp: function ( value, min, max ) {
 	clamp: function ( value, min, max ) {
 
 

+ 114 - 118
src/math/Matrix4.js

@@ -13,6 +13,10 @@ import { Vector3 } from './Vector3.js';
  * @author WestLangley / http://github.com/WestLangley
  * @author WestLangley / http://github.com/WestLangley
  */
  */
 
 
+var v1, m1;
+var zero, one;
+var x, y, z;
+
 function Matrix4() {
 function Matrix4() {
 
 
 	this.elements = [
 	this.elements = [
@@ -119,46 +123,42 @@ Object.assign( Matrix4.prototype, {
 
 
 	},
 	},
 
 
-	extractRotation: function () {
-
-		var v1 = new Vector3();
-
-		return function extractRotation( m ) {
+	extractRotation: function ( m ) {
 
 
-			// this method does not support reflection matrices
+		if ( v1 === undefined ) v1 = new Vector3();
 
 
-			var te = this.elements;
-			var me = m.elements;
+		// this method does not support reflection matrices
 
 
-			var scaleX = 1 / v1.setFromMatrixColumn( m, 0 ).length();
-			var scaleY = 1 / v1.setFromMatrixColumn( m, 1 ).length();
-			var scaleZ = 1 / v1.setFromMatrixColumn( m, 2 ).length();
+		var te = this.elements;
+		var me = m.elements;
 
 
-			te[ 0 ] = me[ 0 ] * scaleX;
-			te[ 1 ] = me[ 1 ] * scaleX;
-			te[ 2 ] = me[ 2 ] * scaleX;
-			te[ 3 ] = 0;
+		var scaleX = 1 / v1.setFromMatrixColumn( m, 0 ).length();
+		var scaleY = 1 / v1.setFromMatrixColumn( m, 1 ).length();
+		var scaleZ = 1 / v1.setFromMatrixColumn( m, 2 ).length();
 
 
-			te[ 4 ] = me[ 4 ] * scaleY;
-			te[ 5 ] = me[ 5 ] * scaleY;
-			te[ 6 ] = me[ 6 ] * scaleY;
-			te[ 7 ] = 0;
+		te[ 0 ] = me[ 0 ] * scaleX;
+		te[ 1 ] = me[ 1 ] * scaleX;
+		te[ 2 ] = me[ 2 ] * scaleX;
+		te[ 3 ] = 0;
 
 
-			te[ 8 ] = me[ 8 ] * scaleZ;
-			te[ 9 ] = me[ 9 ] * scaleZ;
-			te[ 10 ] = me[ 10 ] * scaleZ;
-			te[ 11 ] = 0;
+		te[ 4 ] = me[ 4 ] * scaleY;
+		te[ 5 ] = me[ 5 ] * scaleY;
+		te[ 6 ] = me[ 6 ] * scaleY;
+		te[ 7 ] = 0;
 
 
-			te[ 12 ] = 0;
-			te[ 13 ] = 0;
-			te[ 14 ] = 0;
-			te[ 15 ] = 1;
+		te[ 8 ] = me[ 8 ] * scaleZ;
+		te[ 9 ] = me[ 9 ] * scaleZ;
+		te[ 10 ] = me[ 10 ] * scaleZ;
+		te[ 11 ] = 0;
 
 
-			return this;
+		te[ 12 ] = 0;
+		te[ 13 ] = 0;
+		te[ 14 ] = 0;
+		te[ 15 ] = 1;
 
 
-		};
+		return this;
 
 
-	}(),
+	},
 
 
 	makeRotationFromEuler: function ( euler ) {
 	makeRotationFromEuler: function ( euler ) {
 
 
@@ -288,73 +288,73 @@ Object.assign( Matrix4.prototype, {
 
 
 	},
 	},
 
 
-	makeRotationFromQuaternion: function () {
+	makeRotationFromQuaternion: function ( q ) {
 
 
-		var zero = new Vector3( 0, 0, 0 );
-		var one = new Vector3( 1, 1, 1 );
+		if ( zero === undefined ) {
 
 
-		return function makeRotationFromQuaternion( q ) {
+			zero = new Vector3( 0, 0, 0 );
+			one = new Vector3( 1, 1, 1 );
 
 
-			return this.compose( zero, q, one );
+		}
 
 
-		};
+		return this.compose( zero, q, one );
 
 
-	}(),
+	},
 
 
-	lookAt: function () {
+	lookAt: function ( eye, target, up ) {
 
 
-		var x = new Vector3();
-		var y = new Vector3();
-		var z = new Vector3();
+		if ( x === undefined ) {
 
 
-		return function lookAt( eye, target, up ) {
+			x = new Vector3();
+			y = new Vector3();
+			z = new Vector3();
 
 
-			var te = this.elements;
+		}
 
 
-			z.subVectors( eye, target );
+		var te = this.elements;
 
 
-			if ( z.lengthSq() === 0 ) {
+		z.subVectors( eye, target );
 
 
-				// eye and target are in the same position
+		if ( z.lengthSq() === 0 ) {
 
 
-				z.z = 1;
+			// eye and target are in the same position
 
 
-			}
+			z.z = 1;
 
 
-			z.normalize();
-			x.crossVectors( up, z );
-
-			if ( x.lengthSq() === 0 ) {
+		}
 
 
-				// up and z are parallel
+		z.normalize();
+		x.crossVectors( up, z );
 
 
-				if ( Math.abs( up.z ) === 1 ) {
+		if ( x.lengthSq() === 0 ) {
 
 
-					z.x += 0.0001;
+			// up and z are parallel
 
 
-				} else {
+			if ( Math.abs( up.z ) === 1 ) {
 
 
-					z.z += 0.0001;
+				z.x += 0.0001;
 
 
-				}
+			} else {
 
 
-				z.normalize();
-				x.crossVectors( up, z );
+				z.z += 0.0001;
 
 
 			}
 			}
 
 
-			x.normalize();
-			y.crossVectors( z, x );
+			z.normalize();
+			x.crossVectors( up, z );
+
+		}
 
 
-			te[ 0 ] = x.x; te[ 4 ] = y.x; te[ 8 ] = z.x;
-			te[ 1 ] = x.y; te[ 5 ] = y.y; te[ 9 ] = z.y;
-			te[ 2 ] = x.z; te[ 6 ] = y.z; te[ 10 ] = z.z;
+		x.normalize();
+		y.crossVectors( z, x );
 
 
-			return this;
+		te[ 0 ] = x.x; te[ 4 ] = y.x; te[ 8 ] = z.x;
+		te[ 1 ] = x.y; te[ 5 ] = y.y; te[ 9 ] = z.y;
+		te[ 2 ] = x.z; te[ 6 ] = y.z; te[ 10 ] = z.z;
 
 
-		};
+		return this;
 
 
-	}(),
+	},
 
 
 	multiply: function ( m, n ) {
 	multiply: function ( m, n ) {
 
 
@@ -428,29 +428,25 @@ Object.assign( Matrix4.prototype, {
 
 
 	},
 	},
 
 
-	applyToBufferAttribute: function () {
+	applyToBufferAttribute: function ( attribute ) {
 
 
-		var v1 = new Vector3();
+		if ( v1 === undefined ) v1 = new Vector3();
 
 
-		return function applyToBufferAttribute( attribute ) {
+		for ( var i = 0, l = attribute.count; i < l; i ++ ) {
 
 
-			for ( var i = 0, l = attribute.count; i < l; i ++ ) {
+			v1.x = attribute.getX( i );
+			v1.y = attribute.getY( i );
+			v1.z = attribute.getZ( i );
 
 
-				v1.x = attribute.getX( i );
-				v1.y = attribute.getY( i );
-				v1.z = attribute.getZ( i );
+			v1.applyMatrix4( this );
 
 
-				v1.applyMatrix4( this );
+			attribute.setXYZ( i, v1.x, v1.y, v1.z );
 
 
-				attribute.setXYZ( i, v1.x, v1.y, v1.z );
-
-			}
-
-			return attribute;
+		}
 
 
-		};
+		return attribute;
 
 
-	}(),
+	},
 
 
 	determinant: function () {
 	determinant: function () {
 
 
@@ -784,57 +780,57 @@ Object.assign( Matrix4.prototype, {
 
 
 	},
 	},
 
 
-	decompose: function () {
+	decompose: function ( position, quaternion, scale ) {
 
 
-		var vector = new Vector3();
-		var matrix = new Matrix4();
+		if ( m1 === undefined ) {
 
 
-		return function decompose( position, quaternion, scale ) {
+			m1 = new Matrix4();
+			v1 = new Vector3();
 
 
-			var te = this.elements;
+		}
 
 
-			var sx = vector.set( te[ 0 ], te[ 1 ], te[ 2 ] ).length();
-			var sy = vector.set( te[ 4 ], te[ 5 ], te[ 6 ] ).length();
-			var sz = vector.set( te[ 8 ], te[ 9 ], te[ 10 ] ).length();
+		var te = this.elements;
 
 
-			// if determine is negative, we need to invert one scale
-			var det = this.determinant();
-			if ( det < 0 ) sx = - sx;
+		var sx = v1.set( te[ 0 ], te[ 1 ], te[ 2 ] ).length();
+		var sy = v1.set( te[ 4 ], te[ 5 ], te[ 6 ] ).length();
+		var sz = v1.set( te[ 8 ], te[ 9 ], te[ 10 ] ).length();
 
 
-			position.x = te[ 12 ];
-			position.y = te[ 13 ];
-			position.z = te[ 14 ];
+		// if determine is negative, we need to invert one scale
+		var det = this.determinant();
+		if ( det < 0 ) sx = - sx;
 
 
-			// scale the rotation part
-			matrix.copy( this );
+		position.x = te[ 12 ];
+		position.y = te[ 13 ];
+		position.z = te[ 14 ];
 
 
-			var invSX = 1 / sx;
-			var invSY = 1 / sy;
-			var invSZ = 1 / sz;
+		// scale the rotation part
+		m1.copy( this );
 
 
-			matrix.elements[ 0 ] *= invSX;
-			matrix.elements[ 1 ] *= invSX;
-			matrix.elements[ 2 ] *= invSX;
+		var invSX = 1 / sx;
+		var invSY = 1 / sy;
+		var invSZ = 1 / sz;
 
 
-			matrix.elements[ 4 ] *= invSY;
-			matrix.elements[ 5 ] *= invSY;
-			matrix.elements[ 6 ] *= invSY;
+		m1.elements[ 0 ] *= invSX;
+		m1.elements[ 1 ] *= invSX;
+		m1.elements[ 2 ] *= invSX;
 
 
-			matrix.elements[ 8 ] *= invSZ;
-			matrix.elements[ 9 ] *= invSZ;
-			matrix.elements[ 10 ] *= invSZ;
+		m1.elements[ 4 ] *= invSY;
+		m1.elements[ 5 ] *= invSY;
+		m1.elements[ 6 ] *= invSY;
 
 
-			quaternion.setFromRotationMatrix( matrix );
+		m1.elements[ 8 ] *= invSZ;
+		m1.elements[ 9 ] *= invSZ;
+		m1.elements[ 10 ] *= invSZ;
 
 
-			scale.x = sx;
-			scale.y = sy;
-			scale.z = sz;
+		quaternion.setFromRotationMatrix( m1 );
 
 
-			return this;
+		scale.x = sx;
+		scale.y = sy;
+		scale.z = sz;
 
 
-		};
+		return this;
 
 
-	}(),
+	},
 
 
 	makePerspective: function ( left, right, top, bottom, near, far ) {
 	makePerspective: function ( left, right, top, bottom, near, far ) {
 
 

+ 171 - 182
src/math/Ray.js

@@ -4,6 +4,10 @@ import { Vector3 } from './Vector3.js';
  * @author bhouston / http://clara.io
  * @author bhouston / http://clara.io
  */
  */
 
 
+var vector;
+var segCenter, segDir, diff;
+var diff, edge1, edge2, normal;
+
 function Ray( origin, direction ) {
 function Ray( origin, direction ) {
 
 
 	this.origin = ( origin !== undefined ) ? origin : new Vector3();
 	this.origin = ( origin !== undefined ) ? origin : new Vector3();
@@ -58,19 +62,15 @@ Object.assign( Ray.prototype, {
 
 
 	},
 	},
 
 
-	recast: function () {
-
-		var v1 = new Vector3();
+	recast: function ( t ) {
 
 
-		return function recast( t ) {
+		if ( vector === undefined ) vector = new Vector3();
 
 
-			this.origin.copy( this.at( t, v1 ) );
+		this.origin.copy( this.at( t, vector ) );
 
 
-			return this;
-
-		};
+		return this;
 
 
-	}(),
+	},
 
 
 	closestPointToPoint: function ( point, target ) {
 	closestPointToPoint: function ( point, target ) {
 
 
@@ -101,94 +101,82 @@ Object.assign( Ray.prototype, {
 
 
 	},
 	},
 
 
-	distanceSqToPoint: function () {
-
-		var v1 = new Vector3();
-
-		return function distanceSqToPoint( point ) {
-
-			var directionDistance = v1.subVectors( point, this.origin ).dot( this.direction );
+	distanceSqToPoint: function ( point ) {
 
 
-			// point behind the ray
+		if ( vector === undefined ) vector = new Vector3();
 
 
-			if ( directionDistance < 0 ) {
+		var directionDistance = vector.subVectors( point, this.origin ).dot( this.direction );
 
 
-				return this.origin.distanceToSquared( point );
+		// point behind the ray
 
 
-			}
-
-			v1.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin );
-
-			return v1.distanceToSquared( point );
+		if ( directionDistance < 0 ) {
 
 
-		};
+			return this.origin.distanceToSquared( point );
 
 
-	}(),
+		}
 
 
-	distanceSqToSegment: function () {
+		vector.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin );
 
 
-		var segCenter = new Vector3();
-		var segDir = new Vector3();
-		var diff = new Vector3();
+		return vector.distanceToSquared( point );
 
 
-		return function distanceSqToSegment( v0, v1, optionalPointOnRay, optionalPointOnSegment ) {
+	},
 
 
-			// from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteDistRaySegment.h
-			// It returns the min distance between the ray and the segment
-			// defined by v0 and v1
-			// It can also set two optional targets :
-			// - The closest point on the ray
-			// - The closest point on the segment
+	distanceSqToSegment: function ( v0, v1, optionalPointOnRay, optionalPointOnSegment ) {
 
 
-			segCenter.copy( v0 ).add( v1 ).multiplyScalar( 0.5 );
-			segDir.copy( v1 ).sub( v0 ).normalize();
-			diff.copy( this.origin ).sub( segCenter );
+		if ( segCenter === undefined ) {
 
 
-			var segExtent = v0.distanceTo( v1 ) * 0.5;
-			var a01 = - this.direction.dot( segDir );
-			var b0 = diff.dot( this.direction );
-			var b1 = - diff.dot( segDir );
-			var c = diff.lengthSq();
-			var det = Math.abs( 1 - a01 * a01 );
-			var s0, s1, sqrDist, extDet;
+			segCenter = new Vector3();
+			segDir = new Vector3();
+			diff = new Vector3();
 
 
-			if ( det > 0 ) {
+		}
 
 
-				// The ray and segment are not parallel.
+		// from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteDistRaySegment.h
+		// It returns the min distance between the ray and the segment
+		// defined by v0 and v1
+		// It can also set two optional targets :
+		// - The closest point on the ray
+		// - The closest point on the segment
 
 
-				s0 = a01 * b1 - b0;
-				s1 = a01 * b0 - b1;
-				extDet = segExtent * det;
+		segCenter.copy( v0 ).add( v1 ).multiplyScalar( 0.5 );
+		segDir.copy( v1 ).sub( v0 ).normalize();
+		diff.copy( this.origin ).sub( segCenter );
 
 
-				if ( s0 >= 0 ) {
+		var segExtent = v0.distanceTo( v1 ) * 0.5;
+		var a01 = - this.direction.dot( segDir );
+		var b0 = diff.dot( this.direction );
+		var b1 = - diff.dot( segDir );
+		var c = diff.lengthSq();
+		var det = Math.abs( 1 - a01 * a01 );
+		var s0, s1, sqrDist, extDet;
 
 
-					if ( s1 >= - extDet ) {
+		if ( det > 0 ) {
 
 
-						if ( s1 <= extDet ) {
+			// The ray and segment are not parallel.
 
 
-							// region 0
-							// Minimum at interior points of ray and segment.
+			s0 = a01 * b1 - b0;
+			s1 = a01 * b0 - b1;
+			extDet = segExtent * det;
 
 
-							var invDet = 1 / det;
-							s0 *= invDet;
-							s1 *= invDet;
-							sqrDist = s0 * ( s0 + a01 * s1 + 2 * b0 ) + s1 * ( a01 * s0 + s1 + 2 * b1 ) + c;
+			if ( s0 >= 0 ) {
 
 
-						} else {
+				if ( s1 >= - extDet ) {
 
 
-							// region 1
+					if ( s1 <= extDet ) {
 
 
-							s1 = segExtent;
-							s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
-							sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
+						// region 0
+						// Minimum at interior points of ray and segment.
 
 
-						}
+						var invDet = 1 / det;
+						s0 *= invDet;
+						s1 *= invDet;
+						sqrDist = s0 * ( s0 + a01 * s1 + 2 * b0 ) + s1 * ( a01 * s0 + s1 + 2 * b1 ) + c;
 
 
 					} else {
 					} else {
 
 
-						// region 5
+						// region 1
 
 
-						s1 = - segExtent;
+						s1 = segExtent;
 						s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
 						s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
 						sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
 						sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
 
 
@@ -196,97 +184,101 @@ Object.assign( Ray.prototype, {
 
 
 				} else {
 				} else {
 
 
-					if ( s1 <= - extDet ) {
+					// region 5
 
 
-						// region 4
+					s1 = - segExtent;
+					s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
+					sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
 
 
-						s0 = Math.max( 0, - ( - a01 * segExtent + b0 ) );
-						s1 = ( s0 > 0 ) ? - segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );
-						sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
+				}
 
 
-					} else if ( s1 <= extDet ) {
+			} else {
 
 
-						// region 3
+				if ( s1 <= - extDet ) {
 
 
-						s0 = 0;
-						s1 = Math.min( Math.max( - segExtent, - b1 ), segExtent );
-						sqrDist = s1 * ( s1 + 2 * b1 ) + c;
+					// region 4
 
 
-					} else {
+					s0 = Math.max( 0, - ( - a01 * segExtent + b0 ) );
+					s1 = ( s0 > 0 ) ? - segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );
+					sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
 
 
-						// region 2
+				} else if ( s1 <= extDet ) {
 
 
-						s0 = Math.max( 0, - ( a01 * segExtent + b0 ) );
-						s1 = ( s0 > 0 ) ? segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );
-						sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
+					// region 3
 
 
-					}
+					s0 = 0;
+					s1 = Math.min( Math.max( - segExtent, - b1 ), segExtent );
+					sqrDist = s1 * ( s1 + 2 * b1 ) + c;
 
 
-				}
+				} else {
 
 
-			} else {
+					// region 2
 
 
-				// Ray and segment are parallel.
+					s0 = Math.max( 0, - ( a01 * segExtent + b0 ) );
+					s1 = ( s0 > 0 ) ? segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );
+					sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
 
 
-				s1 = ( a01 > 0 ) ? - segExtent : segExtent;
-				s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
-				sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
+				}
 
 
 			}
 			}
 
 
-			if ( optionalPointOnRay ) {
+		} else {
 
 
-				optionalPointOnRay.copy( this.direction ).multiplyScalar( s0 ).add( this.origin );
+			// Ray and segment are parallel.
 
 
-			}
+			s1 = ( a01 > 0 ) ? - segExtent : segExtent;
+			s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
+			sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
 
 
-			if ( optionalPointOnSegment ) {
+		}
 
 
-				optionalPointOnSegment.copy( segDir ).multiplyScalar( s1 ).add( segCenter );
+		if ( optionalPointOnRay ) {
 
 
-			}
+			optionalPointOnRay.copy( this.direction ).multiplyScalar( s0 ).add( this.origin );
 
 
-			return sqrDist;
+		}
 
 
-		};
+		if ( optionalPointOnSegment ) {
 
 
-	}(),
+			optionalPointOnSegment.copy( segDir ).multiplyScalar( s1 ).add( segCenter );
 
 
-	intersectSphere: function () {
+		}
 
 
-		var v1 = new Vector3();
+		return sqrDist;
 
 
-		return function intersectSphere( sphere, target ) {
+	},
 
 
-			v1.subVectors( sphere.center, this.origin );
-			var tca = v1.dot( this.direction );
-			var d2 = v1.dot( v1 ) - tca * tca;
-			var radius2 = sphere.radius * sphere.radius;
+	intersectSphere: function ( sphere, target ) {
 
 
-			if ( d2 > radius2 ) return null;
+		if ( vector === undefined ) vector = new Vector3();
 
 
-			var thc = Math.sqrt( radius2 - d2 );
+		vector.subVectors( sphere.center, this.origin );
+		var tca = vector.dot( this.direction );
+		var d2 = vector.dot( vector ) - tca * tca;
+		var radius2 = sphere.radius * sphere.radius;
 
 
-			// t0 = first intersect point - entrance on front of sphere
-			var t0 = tca - thc;
+		if ( d2 > radius2 ) return null;
 
 
-			// t1 = second intersect point - exit point on back of sphere
-			var t1 = tca + thc;
+		var thc = Math.sqrt( radius2 - d2 );
 
 
-			// test to see if both t0 and t1 are behind the ray - if so, return null
-			if ( t0 < 0 && t1 < 0 ) return null;
+		// t0 = first intersect point - entrance on front of sphere
+		var t0 = tca - thc;
 
 
-			// test to see if t0 is behind the ray:
-			// if it is, the ray is inside the sphere, so return the second exit point scaled by t1,
-			// in order to always return an intersect point that is in front of the ray.
-			if ( t0 < 0 ) return this.at( t1, target );
+		// t1 = second intersect point - exit point on back of sphere
+		var t1 = tca + thc;
 
 
-			// else t0 is in front of the ray, so return the first collision point scaled by t0
-			return this.at( t0, target );
+		// test to see if both t0 and t1 are behind the ray - if so, return null
+		if ( t0 < 0 && t1 < 0 ) return null;
 
 
-		};
+		// test to see if t0 is behind the ray:
+		// if it is, the ray is inside the sphere, so return the second exit point scaled by t1,
+		// in order to always return an intersect point that is in front of the ray.
+		if ( t0 < 0 ) return this.at( t1, target );
 
 
-	}(),
+		// else t0 is in front of the ray, so return the first collision point scaled by t0
+		return this.at( t0, target );
+
+	},
 
 
 	intersectsSphere: function ( sphere ) {
 	intersectsSphere: function ( sphere ) {
 
 
@@ -430,100 +422,97 @@ Object.assign( Ray.prototype, {
 
 
 	},
 	},
 
 
-	intersectsBox: ( function () {
-
-		var v = new Vector3();
-
-		return function intersectsBox( box ) {
+	intersectsBox: function ( box ) {
 
 
-			return this.intersectBox( box, v ) !== null;
+		if ( vector === undefined ) vector = new Vector3();
 
 
-		};
+		return this.intersectBox( box, vector ) !== null;
 
 
-	} )(),
+	},
 
 
-	intersectTriangle: function () {
+	intersectTriangle: function ( a, b, c, backfaceCulling, target ) {
 
 
 		// Compute the offset origin, edges, and normal.
 		// Compute the offset origin, edges, and normal.
-		var diff = new Vector3();
-		var edge1 = new Vector3();
-		var edge2 = new Vector3();
-		var normal = new Vector3();
 
 
-		return function intersectTriangle( a, b, c, backfaceCulling, target ) {
+		if ( diff === undefined ) {
 
 
-			// from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteIntrRay3Triangle3.h
+			diff = new Vector3();
+			edge1 = new Vector3();
+			edge2 = new Vector3();
+			normal = new Vector3();
 
 
-			edge1.subVectors( b, a );
-			edge2.subVectors( c, a );
-			normal.crossVectors( edge1, edge2 );
+		}
 
 
-			// Solve Q + t*D = b1*E1 + b2*E2 (Q = kDiff, D = ray direction,
-			// E1 = kEdge1, E2 = kEdge2, N = Cross(E1,E2)) by
-			//   |Dot(D,N)|*b1 = sign(Dot(D,N))*Dot(D,Cross(Q,E2))
-			//   |Dot(D,N)|*b2 = sign(Dot(D,N))*Dot(D,Cross(E1,Q))
-			//   |Dot(D,N)|*t = -sign(Dot(D,N))*Dot(Q,N)
-			var DdN = this.direction.dot( normal );
-			var sign;
+		// from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteIntrRay3Triangle3.h
 
 
-			if ( DdN > 0 ) {
+		edge1.subVectors( b, a );
+		edge2.subVectors( c, a );
+		normal.crossVectors( edge1, edge2 );
 
 
-				if ( backfaceCulling ) return null;
-				sign = 1;
+		// Solve Q + t*D = b1*E1 + b2*E2 (Q = kDiff, D = ray direction,
+		// E1 = kEdge1, E2 = kEdge2, N = Cross(E1,E2)) by
+		//   |Dot(D,N)|*b1 = sign(Dot(D,N))*Dot(D,Cross(Q,E2))
+		//   |Dot(D,N)|*b2 = sign(Dot(D,N))*Dot(D,Cross(E1,Q))
+		//   |Dot(D,N)|*t = -sign(Dot(D,N))*Dot(Q,N)
+		var DdN = this.direction.dot( normal );
+		var sign;
 
 
-			} else if ( DdN < 0 ) {
+		if ( DdN > 0 ) {
 
 
-				sign = - 1;
-				DdN = - DdN;
+			if ( backfaceCulling ) return null;
+			sign = 1;
 
 
-			} else {
+		} else if ( DdN < 0 ) {
 
 
-				return null;
+			sign = - 1;
+			DdN = - DdN;
 
 
-			}
+		} else {
+
+			return null;
 
 
-			diff.subVectors( this.origin, a );
-			var DdQxE2 = sign * this.direction.dot( edge2.crossVectors( diff, edge2 ) );
+		}
 
 
-			// b1 < 0, no intersection
-			if ( DdQxE2 < 0 ) {
+		diff.subVectors( this.origin, a );
+		var DdQxE2 = sign * this.direction.dot( edge2.crossVectors( diff, edge2 ) );
 
 
-				return null;
+		// b1 < 0, no intersection
+		if ( DdQxE2 < 0 ) {
 
 
-			}
+			return null;
 
 
-			var DdE1xQ = sign * this.direction.dot( edge1.cross( diff ) );
+		}
 
 
-			// b2 < 0, no intersection
-			if ( DdE1xQ < 0 ) {
+		var DdE1xQ = sign * this.direction.dot( edge1.cross( diff ) );
 
 
-				return null;
+		// b2 < 0, no intersection
+		if ( DdE1xQ < 0 ) {
 
 
-			}
+			return null;
 
 
-			// b1+b2 > 1, no intersection
-			if ( DdQxE2 + DdE1xQ > DdN ) {
+		}
 
 
-				return null;
+		// b1+b2 > 1, no intersection
+		if ( DdQxE2 + DdE1xQ > DdN ) {
 
 
-			}
+			return null;
 
 
-			// Line intersects triangle, check if ray does.
-			var QdN = - sign * diff.dot( normal );
+		}
 
 
-			// t < 0, no intersection
-			if ( QdN < 0 ) {
+		// Line intersects triangle, check if ray does.
+		var QdN = - sign * diff.dot( normal );
 
 
-				return null;
+		// t < 0, no intersection
+		if ( QdN < 0 ) {
 
 
-			}
+			return null;
 
 
-			// Ray intersects triangle.
-			return this.at( QdN / DdN, target );
+		}
 
 
-		};
+		// Ray intersects triangle.
+		return this.at( QdN / DdN, target );
 
 
-	}(),
+	},
 
 
 	applyMatrix4: function ( matrix4 ) {
 	applyMatrix4: function ( matrix4 ) {
 
 

+ 151 - 159
src/math/Triangle.js

@@ -5,6 +5,9 @@ import { Vector3 } from './Vector3.js';
  * @author mrdoob / http://mrdoob.com/
  * @author mrdoob / http://mrdoob.com/
  */
  */
 
 
+var v0, v1, v2, v3;
+var vab, vac, vbc, vap, vbp, vcp;
+
 function Triangle( a, b, c ) {
 function Triangle( a, b, c ) {
 
 
 	this.a = ( a !== undefined ) ? a : new Vector3();
 	this.a = ( a !== undefined ) ? a : new Vector3();
@@ -15,134 +18,122 @@ function Triangle( a, b, c ) {
 
 
 Object.assign( Triangle, {
 Object.assign( Triangle, {
 
 
-	getNormal: function () {
-
-		var v0 = new Vector3();
-
-		return function getNormal( a, b, c, target ) {
+	getNormal: function ( a, b, c, target ) {
 
 
-			if ( target === undefined ) {
+		if ( v0 === undefined ) v0 = new Vector3();
 
 
-				console.warn( 'THREE.Triangle: .getNormal() target is now required' );
-				target = new Vector3();
+		if ( target === undefined ) {
 
 
-			}
+			console.warn( 'THREE.Triangle: .getNormal() target is now required' );
+			target = new Vector3();
 
 
-			target.subVectors( c, b );
-			v0.subVectors( a, b );
-			target.cross( v0 );
+		}
 
 
-			var targetLengthSq = target.lengthSq();
-			if ( targetLengthSq > 0 ) {
+		target.subVectors( c, b );
+		v0.subVectors( a, b );
+		target.cross( v0 );
 
 
-				return target.multiplyScalar( 1 / Math.sqrt( targetLengthSq ) );
+		var targetLengthSq = target.lengthSq();
+		if ( targetLengthSq > 0 ) {
 
 
-			}
+			return target.multiplyScalar( 1 / Math.sqrt( targetLengthSq ) );
 
 
-			return target.set( 0, 0, 0 );
+		}
 
 
-		};
+		return target.set( 0, 0, 0 );
 
 
-	}(),
+	},
 
 
 	// static/instance method to calculate barycentric coordinates
 	// static/instance method to calculate barycentric coordinates
 	// based on: http://www.blackpawn.com/texts/pointinpoly/default.html
 	// based on: http://www.blackpawn.com/texts/pointinpoly/default.html
-	getBarycoord: function () {
-
-		var v0 = new Vector3();
-		var v1 = new Vector3();
-		var v2 = new Vector3();
+	getBarycoord: function ( point, a, b, c, target ) {
 
 
-		return function getBarycoord( point, a, b, c, target ) {
+		if ( v1 === undefined ) {
 
 
-			v0.subVectors( c, a );
-			v1.subVectors( b, a );
-			v2.subVectors( point, a );
+			 v0 = new Vector3();
+			 v1 = new Vector3();
+			 v2 = new Vector3();
 
 
-			var dot00 = v0.dot( v0 );
-			var dot01 = v0.dot( v1 );
-			var dot02 = v0.dot( v2 );
-			var dot11 = v1.dot( v1 );
-			var dot12 = v1.dot( v2 );
-
-			var denom = ( dot00 * dot11 - dot01 * dot01 );
-
-			if ( target === undefined ) {
-
-				console.warn( 'THREE.Triangle: .getBarycoord() target is now required' );
-				target = new Vector3();
+		}
 
 
-			}
+		v0.subVectors( c, a );
+		v1.subVectors( b, a );
+		v2.subVectors( point, a );
 
 
-			// collinear or singular triangle
-			if ( denom === 0 ) {
+		var dot00 = v0.dot( v0 );
+		var dot01 = v0.dot( v1 );
+		var dot02 = v0.dot( v2 );
+		var dot11 = v1.dot( v1 );
+		var dot12 = v1.dot( v2 );
 
 
-				// arbitrary location outside of triangle?
-				// not sure if this is the best idea, maybe should be returning undefined
-				return target.set( - 2, - 1, - 1 );
+		var denom = ( dot00 * dot11 - dot01 * dot01 );
 
 
-			}
+		if ( target === undefined ) {
 
 
-			var invDenom = 1 / denom;
-			var u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom;
-			var v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom;
+			console.warn( 'THREE.Triangle: .getBarycoord() target is now required' );
+			target = new Vector3();
 
 
-			// barycentric coordinates must always sum to 1
-			return target.set( 1 - u - v, v, u );
+		}
 
 
-		};
+		// collinear or singular triangle
+		if ( denom === 0 ) {
 
 
-	}(),
+			// arbitrary location outside of triangle?
+			// not sure if this is the best idea, maybe should be returning undefined
+			return target.set( - 2, - 1, - 1 );
 
 
-	containsPoint: function () {
+		}
 
 
-		var v1 = new Vector3();
+		var invDenom = 1 / denom;
+		var u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom;
+		var v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom;
 
 
-		return function containsPoint( point, a, b, c ) {
+		// barycentric coordinates must always sum to 1
+		return target.set( 1 - u - v, v, u );
 
 
-			Triangle.getBarycoord( point, a, b, c, v1 );
+	},
 
 
-			return ( v1.x >= 0 ) && ( v1.y >= 0 ) && ( ( v1.x + v1.y ) <= 1 );
+	containsPoint: function ( point, a, b, c ) {
 
 
-		};
+		if ( v3 === undefined ) v3 = new Vector3();
 
 
-	}(),
+		Triangle.getBarycoord( point, a, b, c, v3 );
 
 
-	getUV: function () {
+		return ( v3.x >= 0 ) && ( v3.y >= 0 ) && ( ( v3.x + v3.y ) <= 1 );
 
 
-		var barycoord = new Vector3();
+	},
 
 
-		return function getUV( point, p1, p2, p3, uv1, uv2, uv3, target ) {
+	getUV: function ( point, p1, p2, p3, uv1, uv2, uv3, target ) {
 
 
-			this.getBarycoord( point, p1, p2, p3, barycoord );
+		if ( v3 === undefined ) v3 = new Vector3();
 
 
-			target.set( 0, 0 );
-			target.addScaledVector( uv1, barycoord.x );
-			target.addScaledVector( uv2, barycoord.y );
-			target.addScaledVector( uv3, barycoord.z );
+		this.getBarycoord( point, p1, p2, p3, v3 );
 
 
-			return target;
+		target.set( 0, 0 );
+		target.addScaledVector( uv1, v3.x );
+		target.addScaledVector( uv2, v3.y );
+		target.addScaledVector( uv3, v3.z );
 
 
-		};
+		return target;
 
 
-	}(),
+	},
 
 
-	isFrontFacing: function () {
+	isFrontFacing: function ( a, b, c, direction ) {
 
 
-		var v0 = new Vector3();
-		var v1 = new Vector3();
+		if ( v1 === undefined ) {
 
 
-		return function isFrontFacing( a, b, c, direction ) {
+			v0 = new Vector3();
+			v1 = new Vector3();
 
 
-			v0.subVectors( c, b );
-			v1.subVectors( a, b );
+		}
 
 
-			// strictly front facing
-			return ( v0.cross( v1 ).dot( direction ) < 0 ) ? true : false;
+		v0.subVectors( c, b );
+		v1.subVectors( a, b );
 
 
-		};
+		// strictly front facing
+		return ( v0.cross( v1 ).dot( direction ) < 0 ) ? true : false;
 
 
-	}()
+	}
 
 
 } );
 } );
 
 
@@ -186,19 +177,19 @@ Object.assign( Triangle.prototype, {
 
 
 	getArea: function () {
 	getArea: function () {
 
 
-		var v0 = new Vector3();
-		var v1 = new Vector3();
+		if ( v1 === undefined ) {
 
 
-		return function getArea() {
+			v0 = new Vector3();
+			v1 = new Vector3();
 
 
-			v0.subVectors( this.c, this.b );
-			v1.subVectors( this.a, this.b );
+		}
 
 
-			return v0.cross( v1 ).length() * 0.5;
+		v0.subVectors( this.c, this.b );
+		v1.subVectors( this.a, this.b );
 
 
-		};
+		return v0.cross( v1 ).length() * 0.5;
 
 
-	}(),
+	},
 
 
 	getMidpoint: function ( target ) {
 	getMidpoint: function ( target ) {
 
 
@@ -262,103 +253,104 @@ Object.assign( Triangle.prototype, {
 
 
 	},
 	},
 
 
-	closestPointToPoint: function () {
+	closestPointToPoint: function ( p, target ) {
+
+		if ( vab === undefined ) {
 
 
-		var vab = new Vector3();
-		var vac = new Vector3();
-		var vbc = new Vector3();
-		var vap = new Vector3();
-		var vbp = new Vector3();
-		var vcp = new Vector3();
+			vab = new Vector3();
+			vac = new Vector3();
+			vbc = new Vector3();
+			vap = new Vector3();
+			vbp = new Vector3();
+			vcp = new Vector3();
 
 
-		return function closestPointToPoint( p, target ) {
+		}
 
 
-			if ( target === undefined ) {
+		if ( target === undefined ) {
 
 
-				console.warn( 'THREE.Triangle: .closestPointToPoint() target is now required' );
-				target = new Vector3();
+			console.warn( 'THREE.Triangle: .closestPointToPoint() target is now required' );
+			target = new Vector3();
 
 
-			}
+		}
 
 
-			var a = this.a, b = this.b, c = this.c;
-			var v, w;
+		var a = this.a, b = this.b, c = this.c;
+		var v, w;
 
 
-			// algorithm thanks to Real-Time Collision Detection by Christer Ericson,
-			// published by Morgan Kaufmann Publishers, (c) 2005 Elsevier Inc.,
-			// under the accompanying license; see chapter 5.1.5 for detailed explanation.
-			// basically, we're distinguishing which of the voronoi regions of the triangle
-			// the point lies in with the minimum amount of redundant computation.
+		// algorithm thanks to Real-Time Collision Detection by Christer Ericson,
+		// published by Morgan Kaufmann Publishers, (c) 2005 Elsevier Inc.,
+		// under the accompanying license; see chapter 5.1.5 for detailed explanation.
+		// basically, we're distinguishing which of the voronoi regions of the triangle
+		// the point lies in with the minimum amount of redundant computation.
 
 
-			vab.subVectors( b, a );
-			vac.subVectors( c, a );
-			vap.subVectors( p, a );
-			var d1 = vab.dot( vap );
-			var d2 = vac.dot( vap );
-			if ( d1 <= 0 && d2 <= 0 ) {
+		vab.subVectors( b, a );
+		vac.subVectors( c, a );
+		vap.subVectors( p, a );
+		var d1 = vab.dot( vap );
+		var d2 = vac.dot( vap );
+		if ( d1 <= 0 && d2 <= 0 ) {
 
 
-				// vertex region of A; barycentric coords (1, 0, 0)
-				return target.copy( a );
+			// vertex region of A; barycentric coords (1, 0, 0)
+			return target.copy( a );
 
 
-			}
+		}
 
 
-			vbp.subVectors( p, b );
-			var d3 = vab.dot( vbp );
-			var d4 = vac.dot( vbp );
-			if ( d3 >= 0 && d4 <= d3 ) {
+		vbp.subVectors( p, b );
+		var d3 = vab.dot( vbp );
+		var d4 = vac.dot( vbp );
+		if ( d3 >= 0 && d4 <= d3 ) {
 
 
-				// vertex region of B; barycentric coords (0, 1, 0)
-				return target.copy( b );
+			// vertex region of B; barycentric coords (0, 1, 0)
+			return target.copy( b );
 
 
-			}
+		}
 
 
-			var vc = d1 * d4 - d3 * d2;
-			if ( vc <= 0 && d1 >= 0 && d3 <= 0 ) {
+		var vc = d1 * d4 - d3 * d2;
+		if ( vc <= 0 && d1 >= 0 && d3 <= 0 ) {
 
 
-				v = d1 / ( d1 - d3 );
-				// edge region of AB; barycentric coords (1-v, v, 0)
-				return target.copy( a ).addScaledVector( vab, v );
+			v = d1 / ( d1 - d3 );
+			// edge region of AB; barycentric coords (1-v, v, 0)
+			return target.copy( a ).addScaledVector( vab, v );
 
 
-			}
+		}
 
 
-			vcp.subVectors( p, c );
-			var d5 = vab.dot( vcp );
-			var d6 = vac.dot( vcp );
-			if ( d6 >= 0 && d5 <= d6 ) {
+		vcp.subVectors( p, c );
+		var d5 = vab.dot( vcp );
+		var d6 = vac.dot( vcp );
+		if ( d6 >= 0 && d5 <= d6 ) {
 
 
-				// vertex region of C; barycentric coords (0, 0, 1)
-				return target.copy( c );
+			// vertex region of C; barycentric coords (0, 0, 1)
+			return target.copy( c );
 
 
-			}
+		}
 
 
-			var vb = d5 * d2 - d1 * d6;
-			if ( vb <= 0 && d2 >= 0 && d6 <= 0 ) {
+		var vb = d5 * d2 - d1 * d6;
+		if ( vb <= 0 && d2 >= 0 && d6 <= 0 ) {
 
 
-				w = d2 / ( d2 - d6 );
-				// edge region of AC; barycentric coords (1-w, 0, w)
-				return target.copy( a ).addScaledVector( vac, w );
+			w = d2 / ( d2 - d6 );
+			// edge region of AC; barycentric coords (1-w, 0, w)
+			return target.copy( a ).addScaledVector( vac, w );
 
 
-			}
+		}
 
 
-			var va = d3 * d6 - d5 * d4;
-			if ( va <= 0 && ( d4 - d3 ) >= 0 && ( d5 - d6 ) >= 0 ) {
+		var va = d3 * d6 - d5 * d4;
+		if ( va <= 0 && ( d4 - d3 ) >= 0 && ( d5 - d6 ) >= 0 ) {
 
 
-				vbc.subVectors( c, b );
-				w = ( d4 - d3 ) / ( ( d4 - d3 ) + ( d5 - d6 ) );
-				// edge region of BC; barycentric coords (0, 1-w, w)
-				return target.copy( b ).addScaledVector( vbc, w ); // edge region of BC
+			vbc.subVectors( c, b );
+			w = ( d4 - d3 ) / ( ( d4 - d3 ) + ( d5 - d6 ) );
+			// edge region of BC; barycentric coords (0, 1-w, w)
+			return target.copy( b ).addScaledVector( vbc, w ); // edge region of BC
 
 
-			}
+		}
 
 
-			// face region
-			var denom = 1 / ( va + vb + vc );
-			// u = va * denom
-			v = vb * denom;
-			w = vc * denom;
-			return target.copy( a ).addScaledVector( vab, v ).addScaledVector( vac, w );
+		// face region
+		var denom = 1 / ( va + vb + vc );
+		// u = va * denom
+		v = vb * denom;
+		w = vc * denom;
 
 
-		};
+		return target.copy( a ).addScaledVector( vab, v ).addScaledVector( vac, w );
 
 
-	}(),
+	},
 
 
 	equals: function ( triangle ) {
 	equals: function ( triangle ) {