Ray.js 4.5 KB
Newer Older
1 2 3 4
/**
 * @author mr.doob / http://mrdoob.com/
 */

5
THREE.Ray = function ( origin, direction ) {
6 7 8 9 10 11 12 13

	this.origin = origin || new THREE.Vector3();
	this.direction = direction || new THREE.Vector3();

}

THREE.Ray.prototype = {

14 15
	constructor: THREE.Ray,

16
	intersectScene: function ( scene ) {
17

18
		return this.intersectObjects( scene.objects );
19 20 21

	},

22
	intersectObjects: function ( objects ) {
23

24 25 26
		var i, l, object,
		intersects = [];

27
		for ( i = 0, l = objects.length; i < l; i ++ ) {
28

29
			Array.prototype.push.apply( intersects, this.intersectObject( objects[ i ] ) );
30 31 32 33 34 35 36

		}

		intersects.sort( function ( a, b ) { return a.distance - b.distance; } );

		return intersects;

37
	},
38

39
	intersectObject: function ( object ) {
40

41
		if ( object instanceof THREE.Particle ) {
42

43
			var distance = distanceFromIntersection( this.origin, this.direction, object.matrixWorld.getPosition() );
44

45
			if ( distance == null || distance > object.scale.x ) {
46

47
				return [];
48

49
			}
50

51
			return [ {
52

53 54 55 56
				distance: distance,
				point: object.position,
				face: null,
				object: object
57

58
			} ];
59

60
		} else if ( object instanceof THREE.Mesh ) {
61

62 63
			// Checking boundingSphere

64
			var distance = distanceFromIntersection( this.origin, this.direction, object.matrixWorld.getPosition() );
65

66
			if ( distance == null || distance > object.geometry.boundingSphere.radius * Math.max( object.scale.x, Math.max( object.scale.y, object.scale.z ) ) ) {
67 68 69 70 71 72 73

				return [];

			}

			// Checking faces

74 75 76
			var f, fl, face,
			a, b, c, d, normal,
			vector, dot, scalar,
77 78 79 80 81 82
			origin, direction,
			geometry = object.geometry,
			vertices = geometry.vertices,
			objMatrix,
			intersect, intersects = [],
			intersectPoint;
83

84
			for ( f = 0, fl = geometry.faces.length; f < fl; f ++ ) {
85

86
				face = geometry.faces[ f ];
87

88 89
				origin = this.origin.clone();
				direction = this.direction.clone();
90

91
				objMatrix = object.matrixWorld;
92

93 94 95 96 97
				// check if face.centroid is behind the origin

				vector = objMatrix.multiplyVector3( face.centroid.clone() ).subSelf( origin );
				dot = vector.dot( direction );

M
Mr.doob 已提交
98
				if ( dot <= 0 ) continue;
99 100 101

				//

102 103 104 105
				a = objMatrix.multiplyVector3( vertices[ face.a ].position.clone() );
				b = objMatrix.multiplyVector3( vertices[ face.b ].position.clone() );
				c = objMatrix.multiplyVector3( vertices[ face.c ].position.clone() );
				d = face instanceof THREE.Face4 ? objMatrix.multiplyVector3( vertices[ face.d ].position.clone() ) : null;
106

107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
				normal = object.matrixRotationWorld.multiplyVector3( face.normal.clone() );
				dot = direction.dot( normal );

				if ( object.doubleSided || ( object.flipSided ? dot > 0 : dot < 0 ) ) { // Math.abs( dot ) > 0.0001

					scalar = normal.dot( new THREE.Vector3().sub( a, origin ) ) / dot;
					intersectPoint = origin.addSelf( direction.multiplyScalar( scalar ) );

					if ( face instanceof THREE.Face3 ) {

						if ( pointInFace3( intersectPoint, a, b, c ) ) {

							intersect = {

								distance: this.origin.distanceTo( intersectPoint ),
								point: intersectPoint,
								face: face,
								object: object

							};
127

128
							intersects.push( intersect );
129

130
						}
131

132
					} else if ( face instanceof THREE.Face4 ) {
133

134
						if ( pointInFace3( intersectPoint, a, b, d ) || pointInFace3( intersectPoint, b, c, d ) ) {
135

136
							intersect = {
137

138 139 140 141 142 143 144 145 146 147
								distance: this.origin.distanceTo( intersectPoint ),
								point: intersectPoint,
								face: face,
								object: object

							};

							intersects.push( intersect );

						}
148 149 150 151 152 153

					}

				}

			}
154

155 156
			intersects.sort( function ( a, b ) { return a.distance - b.distance; } );

157 158
			return intersects;

159 160 161 162
		} else {

			return [];

163
		}
164

165
		function distanceFromIntersection( origin, direction, position ) {
166

167
			var vector, dot, intersect, distance;
168

169
			vector = position.clone().subSelf( origin );
170 171
			dot = vector.dot( direction );

M
Mr.doob 已提交
172
			if ( dot <= 0 ) return null; // check if position behind origin.
173

174
			intersect = origin.clone().addSelf( direction.clone().multiplyScalar( dot ) );
175
			distance = position.distanceTo( intersect );
176 177 178 179

			return distance;

		}
180

181
		// http://www.blackpawn.com/texts/pointinpoly/default.html
182

183 184 185 186 187 188 189 190 191 192 193 194 195
		function pointInFace3( p, a, b, c ) {

			var v0 = c.clone().subSelf( a ), v1 = b.clone().subSelf( a ), v2 = p.clone().subSelf( a ),
			dot00 = v0.dot( v0 ), dot01 = v0.dot( v1 ), dot02 = v0.dot( v2 ), dot11 = v1.dot( v1 ), dot12 = v1.dot( v2 ),

			invDenom = 1 / ( dot00 * dot11 - dot01 * dot01 ),
			u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom,
			v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom;

			return ( u > 0 ) && ( v > 0 ) && ( u + v < 1 );

		}

196
	}
197 198

};