Browse Source

Raycaster improvements: ensure input ray is normalized, move up quick distance/near-far testing, unnest logic in Raycaster and centralize the addition of hits to the list of intersects.

Ben Houston 12 years ago
parent
commit
ea832104ac
1 changed files with 26 additions and 35 deletions
  1. 26 35
      src/core/Raycaster.js

+ 26 - 35
src/core/Raycaster.js

@@ -7,6 +7,9 @@
 	THREE.Raycaster = function ( origin, direction, near, far ) {
 
 		this.ray = new THREE.Ray( origin, direction );
+		if( this.ray.direction.length() > 0 ) {
+			this.ray.direction.normalize();	// required for accurate distance calculations
+		}
 		this.near = near || 0;
 		this.far = far || Infinity;
 
@@ -129,6 +132,9 @@
 						continue;
 					}
 				}
+
+				// this can be done using the planeDistance from localRay because localRay wasn't normalized, but ray was
+				if ( planeDistance < raycaster.near || planeDistance > raycaster.far ) continue;
 				
 				intersectPoint = localRay.at( planeDistance, intersectPoint ); // passing in intersectPoint avoids a copy
 
@@ -138,25 +144,8 @@
 					b = vertices[ face.b ];
 					c = vertices[ face.c ];
 
-					if ( pointInFace3( intersectPoint, a, b, c ) ) {
-
-						var point = raycaster.ray.at( planeDistance );
-						// Optimization: if input ray was guarrented to be normalized, we can just set distance = planeDistance
-						distance = raycaster.ray.origin.distanceTo( point );
-
-						// Optimization: clipping based on distance can be done earlier if plane is normalized.
-						if ( distance < raycaster.near || distance > raycaster.far ) continue;
-
-						intersects.push( {
-
-							distance: distance,
-							point: point,
-							face: face,
-							faceIndex: f,
-							object: object
-
-						} );
-
+					if ( ! pointInFace3( intersectPoint, a, b, c ) ) {
+						continue;
 					}
 
 				} else if ( face instanceof THREE.Face4 ) {
@@ -166,28 +155,27 @@
 					c = vertices[ face.c ];
 					d = vertices[ face.d ];
 
-					if ( pointInFace3( intersectPoint, a, b, d ) || pointInFace3( intersectPoint, b, c, d ) ) {
-
-						var point = raycaster.ray.at( planeDistance );
-						// Optimization: if input ray was guarrented to be normalized, we can just set distance = planeDistance
-						distance = raycaster.ray.origin.distanceTo( point );
+					if ( ( ! pointInFace3( intersectPoint, a, b, d ) ) && ( ! pointInFace3( intersectPoint, b, c, d ) ) ) {
+						continue;
+					}
 
-						// Optimization: clipping based on distance can be done earlier if plane is normalized.
-						if ( distance < raycaster.near || distance > raycaster.far ) continue;
+				} else {
 
-						intersects.push( {
+					// This is added because if we call out of this if/else group when none of the cases
+					//    match it will add a point to the intersection list erroneously.
+					throw Error( "face type not supported" );
 
-							distance: distance,
-							point: point,
-							face: face,
-							faceIndex: f,
-							object: object
+				}
 
-						} );
+				intersects.push( {
 
-					}
+					distance: planeDistance,	// this works because the original ray was normalized, and the transformed localRay wasn't
+					point: raycaster.ray.at( planeDistance ),
+					face: face,
+					faceIndex: f,
+					object: object
 
-				}
+				} );
 
 			}
 
@@ -213,6 +201,9 @@
 	THREE.Raycaster.prototype.set = function ( origin, direction ) {
 
 		this.ray.set( origin, direction );
+		if( this.ray.direction.length() > 0 ) {
+			this.ray.direction.normalize();	// required for accurate distance calculations
+		}
 
 	};