source: other-projects/playing-in-the-street/summer-2013/trunk/Playing-in-the-Street-WPF/Content/Web/mrdoob-three.js-4862f5f/src/core/Raycaster.js@ 28897

Last change on this file since 28897 was 28897, checked in by davidb, 10 years ago

GUI front-end to server base plus web page content

File size: 10.7 KB
Line 
1/**
2 * @author mrdoob / http://mrdoob.com/
3 * @author bhouston / http://exocortex.com/
4 * @author stephomi / http://stephaneginier.com/
5 */
6
7( function ( THREE ) {
8
9 THREE.Raycaster = function ( origin, direction, near, far ) {
10
11 this.ray = new THREE.Ray( origin, direction );
12 // direction is assumed to be normalized (for accurate distance calculations)
13
14 this.near = near || 0;
15 this.far = far || Infinity;
16
17 };
18
19 var sphere = new THREE.Sphere();
20 var localRay = new THREE.Ray();
21 var facePlane = new THREE.Plane();
22 var intersectPoint = new THREE.Vector3();
23 var matrixPosition = new THREE.Vector3();
24
25 var inverseMatrix = new THREE.Matrix4();
26
27 var descSort = function ( a, b ) {
28
29 return a.distance - b.distance;
30
31 };
32
33 var vA = new THREE.Vector3();
34 var vB = new THREE.Vector3();
35 var vC = new THREE.Vector3();
36
37 var intersectObject = function ( object, raycaster, intersects ) {
38
39 if ( object instanceof THREE.Sprite ) {
40
41 matrixPosition.setFromMatrixPosition( object.matrixWorld );
42 var distance = raycaster.ray.distanceToPoint( matrixPosition );
43
44 if ( distance > object.scale.x ) {
45
46 return intersects;
47
48 }
49
50 intersects.push( {
51
52 distance: distance,
53 point: object.position,
54 face: null,
55 object: object
56
57 } );
58
59 } else if ( object instanceof THREE.LOD ) {
60
61 matrixPosition.setFromMatrixPosition( object.matrixWorld );
62 var distance = raycaster.ray.origin.distanceTo( matrixPosition );
63
64 intersectObject( object.getObjectForDistance( distance ), raycaster, intersects );
65
66 } else if ( object instanceof THREE.Mesh ) {
67
68 var geometry = object.geometry;
69
70 // Checking boundingSphere distance to ray
71
72 if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
73
74 sphere.copy( geometry.boundingSphere );
75 sphere.applyMatrix4( object.matrixWorld );
76
77 if ( raycaster.ray.isIntersectionSphere( sphere ) === false ) {
78
79 return intersects;
80
81 }
82
83 // Check boundingBox before continuing
84
85 inverseMatrix.getInverse( object.matrixWorld );
86 localRay.copy( raycaster.ray ).applyMatrix4( inverseMatrix );
87
88 if ( geometry.boundingBox !== null ) {
89
90 if ( localRay.isIntersectionBox( geometry.boundingBox ) === false ) {
91
92 return intersects;
93
94 }
95
96 }
97
98 if ( geometry instanceof THREE.BufferGeometry ) {
99
100 var material = object.material;
101
102 if ( material === undefined ) return intersects;
103 if ( geometry.dynamic === false ) return intersects;
104
105 var a, b, c;
106 var precision = raycaster.precision;
107
108 if ( geometry.attributes.index !== undefined ) {
109
110 var offsets = geometry.offsets;
111 var indices = geometry.attributes.index.array;
112 var positions = geometry.attributes.position.array;
113 var offLength = geometry.offsets.length;
114
115 var fl = geometry.attributes.index.array.length / 3;
116
117 for ( var oi = 0; oi < offLength; ++oi ) {
118
119 var start = offsets[ oi ].start;
120 var count = offsets[ oi ].count;
121 var index = offsets[ oi ].index;
122
123 for ( var i = start, il = start + count; i < il; i += 3 ) {
124
125 a = index + indices[ i ];
126 b = index + indices[ i + 1 ];
127 c = index + indices[ i + 2 ];
128
129 vA.set(
130 positions[ a * 3 ],
131 positions[ a * 3 + 1 ],
132 positions[ a * 3 + 2 ]
133 );
134 vB.set(
135 positions[ b * 3 ],
136 positions[ b * 3 + 1 ],
137 positions[ b * 3 + 2 ]
138 );
139 vC.set(
140 positions[ c * 3 ],
141 positions[ c * 3 + 1 ],
142 positions[ c * 3 + 2 ]
143 );
144
145
146 if ( material.side === THREE.BackSide ) {
147
148 var intersectionPoint = localRay.intersectTriangle( vC, vB, vA, true );
149
150 } else {
151
152 var intersectionPoint = localRay.intersectTriangle( vA, vB, vC, material.side !== THREE.DoubleSide );
153
154 }
155
156 if ( intersectionPoint === null ) continue;
157
158 intersectionPoint.applyMatrix4( object.matrixWorld );
159
160 var distance = raycaster.ray.origin.distanceTo( intersectionPoint );
161
162 if ( distance < precision || distance < raycaster.near || distance > raycaster.far ) continue;
163
164 intersects.push( {
165
166 distance: distance,
167 point: intersectionPoint,
168 face: null,
169 faceIndex: null,
170 object: object
171
172 } );
173
174 }
175
176 }
177
178 } else {
179
180 var offsets = geometry.offsets;
181 var positions = geometry.attributes.position.array;
182 var offLength = geometry.offsets.length;
183
184 var fl = geometry.attributes.position.array.length;
185
186 for ( var i = 0; i < fl; i += 3 ) {
187
188 a = i;
189 b = i + 1;
190 c = i + 2;
191
192 vA.set(
193 positions[ a * 3 ],
194 positions[ a * 3 + 1 ],
195 positions[ a * 3 + 2 ]
196 );
197 vB.set(
198 positions[ b * 3 ],
199 positions[ b * 3 + 1 ],
200 positions[ b * 3 + 2 ]
201 );
202 vC.set(
203 positions[ c * 3 ],
204 positions[ c * 3 + 1 ],
205 positions[ c * 3 + 2 ]
206 );
207
208
209 if ( material.side === THREE.BackSide ) {
210
211 var intersectionPoint = localRay.intersectTriangle( vC, vB, vA, true );
212
213 } else {
214
215 var intersectionPoint = localRay.intersectTriangle( vA, vB, vC, material.side !== THREE.DoubleSide );
216
217 }
218
219 if ( intersectionPoint === null ) continue;
220
221 intersectionPoint.applyMatrix4( object.matrixWorld );
222
223 var distance = raycaster.ray.origin.distanceTo( intersectionPoint );
224
225 if ( distance < precision || distance < raycaster.near || distance > raycaster.far ) continue;
226
227 intersects.push( {
228
229 distance: distance,
230 point: intersectionPoint,
231 face: null,
232 faceIndex: null,
233 object: object
234
235 } );
236
237 }
238
239 }
240
241 } else if ( geometry instanceof THREE.Geometry ) {
242
243 var isFaceMaterial = object.material instanceof THREE.MeshFaceMaterial;
244 var objectMaterials = isFaceMaterial === true ? object.material.materials : null;
245
246 var a, b, c, d;
247 var precision = raycaster.precision;
248
249 var vertices = geometry.vertices;
250
251 for ( var f = 0, fl = geometry.faces.length; f < fl; f ++ ) {
252
253 var face = geometry.faces[ f ];
254
255 var material = isFaceMaterial === true ? objectMaterials[ face.materialIndex ] : object.material;
256
257 if ( material === undefined ) continue;
258
259 a = vertices[ face.a ];
260 b = vertices[ face.b ];
261 c = vertices[ face.c ];
262
263 if ( material.morphTargets === true ) {
264
265 var morphTargets = geometry.morphTargets;
266 var morphInfluences = object.morphTargetInfluences;
267
268 vA.set( 0, 0, 0 );
269 vB.set( 0, 0, 0 );
270 vC.set( 0, 0, 0 );
271
272 for ( var t = 0, tl = morphTargets.length; t < tl; t ++ ) {
273
274 var influence = morphInfluences[ t ];
275
276 if ( influence === 0 ) continue;
277
278 var targets = morphTargets[ t ].vertices;
279
280 vA.x += ( targets[ face.a ].x - a.x ) * influence;
281 vA.y += ( targets[ face.a ].y - a.y ) * influence;
282 vA.z += ( targets[ face.a ].z - a.z ) * influence;
283
284 vB.x += ( targets[ face.b ].x - b.x ) * influence;
285 vB.y += ( targets[ face.b ].y - b.y ) * influence;
286 vB.z += ( targets[ face.b ].z - b.z ) * influence;
287
288 vC.x += ( targets[ face.c ].x - c.x ) * influence;
289 vC.y += ( targets[ face.c ].y - c.y ) * influence;
290 vC.z += ( targets[ face.c ].z - c.z ) * influence;
291
292 }
293
294 vA.add( a );
295 vB.add( b );
296 vC.add( c );
297
298 a = vA;
299 b = vB;
300 c = vC;
301
302 }
303
304 if ( material.side === THREE.BackSide ) {
305
306 var intersectionPoint = localRay.intersectTriangle( c, b, a, true );
307
308 } else {
309
310 var intersectionPoint = localRay.intersectTriangle( a, b, c, material.side !== THREE.DoubleSide );
311
312 }
313
314 if ( intersectionPoint === null ) continue;
315
316 intersectionPoint.applyMatrix4( object.matrixWorld );
317
318 var distance = raycaster.ray.origin.distanceTo( intersectionPoint );
319
320 if ( distance < precision || distance < raycaster.near || distance > raycaster.far ) continue;
321
322 intersects.push( {
323
324 distance: distance,
325 point: intersectionPoint,
326 face: face,
327 faceIndex: f,
328 object: object
329
330 } );
331
332 }
333
334 }
335
336 } else if ( object instanceof THREE.Line ) {
337
338 var precision = raycaster.linePrecision;
339 var precisionSq = precision * precision;
340
341 var geometry = object.geometry;
342
343 if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
344
345 // Checking boundingSphere distance to ray
346
347 sphere.copy( geometry.boundingSphere );
348 sphere.applyMatrix4( object.matrixWorld );
349
350 if ( raycaster.ray.isIntersectionSphere( sphere ) === false ) {
351
352 return intersects;
353
354 }
355
356 inverseMatrix.getInverse( object.matrixWorld );
357 localRay.copy( raycaster.ray ).applyMatrix4( inverseMatrix );
358
359 /* if ( geometry instanceof THREE.BufferGeometry ) {
360
361 } else */ if ( geometry instanceof THREE.Geometry ) {
362
363 var vertices = geometry.vertices;
364 var nbVertices = vertices.length;
365 var interSegment = new THREE.Vector3();
366 var interRay = new THREE.Vector3();
367 var step = object.type === THREE.LineStrip ? 1 : 2;
368
369 for ( var i = 0; i < nbVertices - 1; i = i + step ) {
370
371 var distSq = localRay.distanceSqToSegment( vertices[ i ], vertices[ i + 1 ], interRay, interSegment );
372
373 if ( distSq > precisionSq ) continue;
374
375 var distance = localRay.origin.distanceTo( interRay );
376
377 if ( distance < raycaster.near || distance > raycaster.far ) continue;
378
379 intersects.push( {
380
381 distance: distance,
382 // What do we want? intersection point on the ray or on the segment??
383 // point: raycaster.ray.at( distance ),
384 point: interSegment.clone().applyMatrix4( object.matrixWorld ),
385 face: null,
386 faceIndex: null,
387 object: object
388
389 } );
390
391 }
392
393 }
394
395 }
396
397 };
398
399 var intersectDescendants = function ( object, raycaster, intersects ) {
400
401 var descendants = object.getDescendants();
402
403 for ( var i = 0, l = descendants.length; i < l; i ++ ) {
404
405 intersectObject( descendants[ i ], raycaster, intersects );
406
407 }
408 };
409
410 //
411
412 THREE.Raycaster.prototype.precision = 0.0001;
413 THREE.Raycaster.prototype.linePrecision = 1;
414
415 THREE.Raycaster.prototype.set = function ( origin, direction ) {
416
417 this.ray.set( origin, direction );
418 // direction is assumed to be normalized (for accurate distance calculations)
419
420 };
421
422 THREE.Raycaster.prototype.intersectObject = function ( object, recursive ) {
423
424 var intersects = [];
425
426 if ( recursive === true ) {
427
428 intersectDescendants( object, this, intersects );
429
430 }
431
432 intersectObject( object, this, intersects );
433
434 intersects.sort( descSort );
435
436 return intersects;
437
438 };
439
440 THREE.Raycaster.prototype.intersectObjects = function ( objects, recursive ) {
441
442 var intersects = [];
443
444 for ( var i = 0, l = objects.length; i < l; i ++ ) {
445
446 intersectObject( objects[ i ], this, intersects );
447
448 if ( recursive === true ) {
449
450 intersectDescendants( objects[ i ], this, intersects );
451
452 }
453
454 }
455
456 intersects.sort( descSort );
457
458 return intersects;
459
460 };
461
462}( THREE ) );
Note: See TracBrowser for help on using the repository browser.