Ray.js 6.2 KB
Newer Older
1
/**
M
Mr.doob 已提交
2
 * @author mrdoob / http://mrdoob.com/
3
 */
M
Mr.doob 已提交
4 5 6

( function ( THREE ) {

L
libra guest 已提交
7
	THREE.Ray = function ( origin, direction, near, far ) {
M
Mr.doob 已提交
8

L
libra guest 已提交
9 10 11 12
		this.origin = origin || new THREE.Vector3();
		this.direction = direction || new THREE.Vector3();
		this.near = near || 0;
		this.far = far || Infinity;
M
Mr.doob 已提交
13

L
libra guest 已提交
14
	};
M
Mr.doob 已提交
15

16
	var originCopy = new THREE.Vector3();
M
Mr.doob 已提交
17

18
	var localOriginCopy = new THREE.Vector3();
19
	var localDirectionCopy = new THREE.Vector3();
M
Mr.doob 已提交
20

21
	var vector = new THREE.Vector3();
M
Mr.doob 已提交
22
	var normal = new THREE.Vector3();
M
Mr.doob 已提交
23
	var intersectPoint = new THREE.Vector3();
M
Mr.doob 已提交
24

25
	var inverseMatrix = new THREE.Matrix4();
M
Mr.doob 已提交
26

27
	var descSort = function ( a, b ) {
M
Mr.doob 已提交
28

L
libra guest 已提交
29
		return a.distance - b.distance;
M
Mr.doob 已提交
30

31
	};
M
Mr.doob 已提交
32

M
Mr.doob 已提交
33 34 35
	var v0 = new THREE.Vector3(), v1 = new THREE.Vector3(), v2 = new THREE.Vector3();

	var distanceFromIntersection = function ( origin, direction, position ) {
M
Mr.doob 已提交
36

M
Mr.doob 已提交
37
		v0.sub( position, origin );
M
Mr.doob 已提交
38 39 40 41 42 43

		var dot = v0.dot( direction );

		var intersect = v1.add( origin, v2.copy( direction ).multiplyScalar( dot ) );
		var distance = position.distanceTo( intersect );

M
Mr.doob 已提交
44
		return distance;
M
Mr.doob 已提交
45

L
libra guest 已提交
46
	};
M
Mr.doob 已提交
47

M
Mr.doob 已提交
48 49 50
	// http://www.blackpawn.com/texts/pointinpoly/default.html

	var pointInFace3 = function ( p, a, b, c ) {
M
Mr.doob 已提交
51

M
Mr.doob 已提交
52 53 54
		v0.sub( c, a );
		v1.sub( b, a );
		v2.sub( p, a );
M
Mr.doob 已提交
55 56 57 58 59 60 61 62 63 64 65

		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 invDenom = 1 / ( dot00 * dot11 - dot01 * dot01 );
		var u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom;
		var v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom;

M
Mr.doob 已提交
66
		return ( u >= 0 ) && ( v >= 0 ) && ( u + v < 1 );
M
Mr.doob 已提交
67

L
libra guest 已提交
68
	};
M
Mr.doob 已提交
69 70 71

	var intersectObject = function ( object, ray, intersects ) {

M
Mr.doob 已提交
72
		var distance,intersect;
M
Mr.doob 已提交
73

74
		if ( object instanceof THREE.Particle ) {
M
Mr.doob 已提交
75

M
Mr.doob 已提交
76
			distance = distanceFromIntersection( ray.origin, ray.direction, object.matrixWorld.getPosition() );
M
Mr.doob 已提交
77

M
Mr.doob 已提交
78
			if ( distance > object.scale.x ) {
M
Mr.doob 已提交
79 80 81

				return intersects;

82
			}
M
Mr.doob 已提交
83

M
Mr.doob 已提交
84
			intersect = {
M
Mr.doob 已提交
85

86 87 88 89
				distance: distance,
				point: object.position,
				face: null,
				object: object
M
Mr.doob 已提交
90

M
Mr.doob 已提交
91
			};
M
Mr.doob 已提交
92

M
Mr.doob 已提交
93
			intersects.push( intersect );
M
Mr.doob 已提交
94

95
		} else if ( object instanceof THREE.Mesh ) {
M
Mr.doob 已提交
96

97
			// Checking boundingSphere
M
Mr.doob 已提交
98

99
			var scaledRadius = object.geometry.boundingSphere.radius * object.matrixWorld.getMaxScaleOnAxis();
M
Mr.doob 已提交
100

101
			// Checking distance to ray
M
Mr.doob 已提交
102

M
Mr.doob 已提交
103
			distance = distanceFromIntersection( ray.origin, ray.direction, object.matrixWorld.getPosition() );
M
Mr.doob 已提交
104

M
Mr.doob 已提交
105
			if ( distance > scaledRadius) {
M
Mr.doob 已提交
106

M
Mr.doob 已提交
107
				return intersects;
M
Mr.doob 已提交
108

109
			}
M
Mr.doob 已提交
110

111
			// Checking faces
M
Mr.doob 已提交
112

113
			var f, fl, face, dot, scalar,
114 115
			geometry = object.geometry,
			vertices = geometry.vertices,
116
			objMatrix, geometryMaterials,
L
libra guest 已提交
117
			isFaceMaterial, material, side, point;
M
Mr.doob 已提交
118

119 120 121
			geometryMaterials = object.geometry.materials;
			isFaceMaterial = object.material instanceof THREE.MeshFaceMaterial;
			side = object.material.side;
M
Mr.doob 已提交
122

L
libra guest 已提交
123
			var a, b, c, d;
M
Mr.doob 已提交
124
			var precision = ray.precision;
M
Mr.doob 已提交
125

M
Mr.doob 已提交
126
			object.matrixRotationWorld.extractRotation( object.matrixWorld );
M
Mr.doob 已提交
127

M
Mr.doob 已提交
128
			originCopy.copy( ray.origin );
M
Mr.doob 已提交
129

130
			objMatrix = object.matrixWorld;
M
Mr.doob 已提交
131 132 133 134 135 136 137 138
			inverseMatrix.getInverse( objMatrix );

			localOriginCopy.copy( originCopy );
			inverseMatrix.multiplyVector3( localOriginCopy );

			localDirectionCopy.copy( ray.direction );
			inverseMatrix.rotateAxis( localDirectionCopy ).normalize();

139
			for ( f = 0, fl = geometry.faces.length; f < fl; f ++ ) {
M
Mr.doob 已提交
140

141
				face = geometry.faces[ f ];
M
Mr.doob 已提交
142

143 144 145
				material = isFaceMaterial === true ? geometryMaterials[ face.materialIndex ] : object.material;
				if ( material === undefined ) continue;
				side = material.side;
M
Mr.doob 已提交
146

147
				vector.sub( face.centroid, localOriginCopy );
148
				normal = face.normal;
149
				dot = localDirectionCopy.dot( normal );
M
Mr.doob 已提交
150

151
				// bail if ray and plane are parallel
M
Mr.doob 已提交
152

153
				if ( Math.abs( dot ) < precision ) continue;
M
Mr.doob 已提交
154

155
				// calc distance to plane
M
Mr.doob 已提交
156

157
				scalar = normal.dot( vector ) / dot;
M
Mr.doob 已提交
158

159
				// if negative distance, then plane is behind ray
M
Mr.doob 已提交
160

161
				if ( scalar < 0 ) continue;
M
Mr.doob 已提交
162

163
				if ( side === THREE.DoubleSide || ( side === THREE.FrontSide ? dot < 0 : dot > 0 ) ) {
M
Mr.doob 已提交
164

165
					intersectPoint.add( localOriginCopy, localDirectionCopy.multiplyScalar( scalar ) );
M
Mr.doob 已提交
166

167
					if ( face instanceof THREE.Face3 ) {
M
Mr.doob 已提交
168

169 170 171
						a = vertices[ face.a ];
						b = vertices[ face.b ];
						c = vertices[ face.c ];
M
Mr.doob 已提交
172

173
						if ( pointInFace3( intersectPoint, a, b, c ) ) {
M
Mr.doob 已提交
174 175 176 177 178 179

							point = object.matrixWorld.multiplyVector3( intersectPoint.clone() );
							distance = originCopy.distanceTo( point );

							if ( distance < ray.near || distance > ray.far ) continue;

180
							intersect = {
M
Mr.doob 已提交
181

N
niklassa 已提交
182
								distance: distance,
183
								point: point,
184
								face: face,
A
alteredq 已提交
185
								faceIndex: f,
186
								object: object
M
Mr.doob 已提交
187

188
							};
M
Mr.doob 已提交
189

190
							intersects.push( intersect );
M
Mr.doob 已提交
191

192
						}
M
Mr.doob 已提交
193

194
					} else if ( face instanceof THREE.Face4 ) {
M
Mr.doob 已提交
195

196 197 198 199
						a = vertices[ face.a ];
						b = vertices[ face.b ];
						c = vertices[ face.c ];
						d = vertices[ face.d ];
M
Mr.doob 已提交
200

201
						if ( pointInFace3( intersectPoint, a, b, d ) || pointInFace3( intersectPoint, b, c, d ) ) {
M
Mr.doob 已提交
202 203 204 205 206 207

							point = object.matrixWorld.multiplyVector3( intersectPoint.clone() );
							distance = originCopy.distanceTo( point );

							if ( distance < ray.near || distance > ray.far ) continue;

208
							intersect = {
M
Mr.doob 已提交
209

N
niklassa 已提交
210
								distance: distance,
211
								point: point,
212
								face: face,
A
alteredq 已提交
213
								faceIndex: f,
214
								object: object
M
Mr.doob 已提交
215

216
							};
M
Mr.doob 已提交
217

218
							intersects.push( intersect );
M
Mr.doob 已提交
219

220
						}
M
Mr.doob 已提交
221

222
					}
M
Mr.doob 已提交
223

224
				}
M
Mr.doob 已提交
225

226
			}
M
Mr.doob 已提交
227

M
Mr.doob 已提交
228
		}
M
Mr.doob 已提交
229

M
Mr.doob 已提交
230
	};
M
Mr.doob 已提交
231

M
Mr.doob 已提交
232
	var intersectDescendants = function ( object, ray, intersects ) {
M
Mr.doob 已提交
233

M
Mr.doob 已提交
234
		var descendants = object.getDescendants();
M
Mr.doob 已提交
235 236 237

		for ( var i = 0, l = descendants.length; i < l; i ++ ) {

M
Mr.doob 已提交
238
			intersectObject( descendants[ i ], ray, intersects );
M
Mr.doob 已提交
239

M
Mr.doob 已提交
240 241
		}
	};
M
Mr.doob 已提交
242

M
Mr.doob 已提交
243
	//
M
Mr.doob 已提交
244

M
Mr.doob 已提交
245
	THREE.Ray.prototype.precision = 0.0001;
246 247 248 249 250 251 252

	THREE.Ray.prototype.set = function ( origin, direction ) {

		this.origin = origin;
		this.direction = direction;

	};
M
Mr.doob 已提交
253

M
Mr.doob 已提交
254
	THREE.Ray.prototype.intersectObject = function ( object, recursive ) {
M
Mr.doob 已提交
255

M
Mr.doob 已提交
256
		var intersects = [];
M
Mr.doob 已提交
257

M
Mr.doob 已提交
258
		if ( recursive === true ) {
M
Mr.doob 已提交
259 260 261

			intersectDescendants( object, this, intersects );

M
Mr.doob 已提交
262
		}
M
Mr.doob 已提交
263

M
Mr.doob 已提交
264
		intersectObject( object, this, intersects );
M
Mr.doob 已提交
265

266
		intersects.sort( descSort );
M
Mr.doob 已提交
267

M
Mr.doob 已提交
268
		return intersects;
M
Mr.doob 已提交
269

M
Mr.doob 已提交
270
	};
M
Mr.doob 已提交
271

L
libra guest 已提交
272
	THREE.Ray.prototype.intersectObjects = function ( objects, recursive ) {
M
Mr.doob 已提交
273

M
Mr.doob 已提交
274
		var intersects = [];
M
Mr.doob 已提交
275

M
Mr.doob 已提交
276
		for ( var i = 0, l = objects.length; i < l; i ++ ) {
M
Mr.doob 已提交
277 278 279 280 281 282 283

			intersectObject( objects[ i ], this, intersects );

			if ( recursive === true ) {

				intersectDescendants( objects[ i ], this, intersects );

M
Mr.doob 已提交
284
			}
M
Mr.doob 已提交
285
		}
M
Mr.doob 已提交
286

287
		intersects.sort( descSort );
M
Mr.doob 已提交
288

M
Mr.doob 已提交
289
		return intersects;
M
Mr.doob 已提交
290

M
Mr.doob 已提交
291
	};
M
Mr.doob 已提交
292 293

}( THREE ) );