Browse Source

The ray is now used as a ray instead as a line.

stephomi 12 years ago
parent
commit
1f7cc3d7f8
3 changed files with 64 additions and 37 deletions
  1. 8 8
      src/core/Raycaster.js
  2. 32 12
      src/math/Ray.js
  3. 24 17
      test/unit/math/Ray.js

+ 8 - 8
src/core/Raycaster.js

@@ -164,11 +164,11 @@
 
 
 						var planeDistance = localRay.distanceToPlane( facePlane );
 						var planeDistance = localRay.distanceToPlane( facePlane );
 
 
-						// bail if raycaster and plane are parallel
-						if ( Math.abs( planeDistance ) < precision ) continue;
+						// bail if the ray is too close to the plane
+						if ( planeDistance < precision ) continue;
 
 
-						// if negative distance, then plane is behind raycaster
-						if ( planeDistance < 0 ) continue;
+						// bail if the ray is behind the plane
+						if ( planeDistance === null ) continue;
 
 
 						// check if we hit the wrong side of a single sided face
 						// check if we hit the wrong side of a single sided face
 						side = material.side;
 						side = material.side;
@@ -244,11 +244,11 @@
 
 
 					var planeDistance = localRay.distanceToPlane( facePlane );
 					var planeDistance = localRay.distanceToPlane( facePlane );
 
 
-					// bail if raycaster and plane are parallel
-					if ( Math.abs( planeDistance ) < precision ) continue;
+					// bail if the ray is too close to the plane
+					if ( planeDistance < precision ) continue;
 
 
-					// if negative distance, then plane is behind raycaster
-					if ( planeDistance < 0 ) continue;
+					// bail if the ray is behind the plane
+					if ( planeDistance === null ) continue;
 
 
 					// check if we hit the wrong side of a single sided face
 					// check if we hit the wrong side of a single sided face
 					side = material.side;
 					side = material.side;

+ 32 - 12
src/math/Ray.js

@@ -59,6 +59,12 @@ THREE.Ray.prototype = {
 		result.subVectors( point, this.origin );
 		result.subVectors( point, this.origin );
 		var directionDistance = result.dot( this.direction );
 		var directionDistance = result.dot( this.direction );
 
 
+		if ( directionDistance < 0 ) {
+
+			return this.origin.clone();
+
+		}
+
 		return result.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin );
 		return result.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin );
 
 
 	},
 	},
@@ -70,6 +76,15 @@ THREE.Ray.prototype = {
 		return function ( point ) {
 		return function ( point ) {
 
 
 			var directionDistance = v1.subVectors( point, this.origin ).dot( this.direction );
 			var directionDistance = v1.subVectors( point, this.origin ).dot( this.direction );
+
+			// point behind the ray
+
+			if ( directionDistance < 0 ) {
+
+				return this.origin.distanceTo( point );
+
+			}
+
 			v1.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin );
 			v1.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin );
 
 
 			return v1.distanceTo( point );
 			return v1.distanceTo( point );
@@ -205,24 +220,26 @@ THREE.Ray.prototype = {
 
 
 	isIntersectionPlane: function ( plane ) {
 	isIntersectionPlane: function ( plane ) {
 
 
-		// check if the line and plane are non-perpendicular, if they
-		// eventually they will intersect.
+		// check if the ray lies on the plane first
 
 
-		var denominator = plane.normal.dot( this.direction );
+		var distToPoint = plane.distanceToPoint( this.origin );
 
 
-		if ( denominator != 0 ) {
+		if ( distToPoint === 0 ) {
 
 
 			return true;
 			return true;
 
 
 		}
 		}
 
 
-		// line is coplanar, return origin
-		if( plane.distanceToPoint( this.origin ) == 0 ) {
+		var denominator = plane.normal.dot( this.direction );
 
 
-			return true;
+		if ( denominator * distToPoint < 0 ) {
+
+			return true
 
 
 		}
 		}
 
 
+		// ray origin is behind the plane (and is pointing behind it)
+
 		return false;
 		return false;
 
 
 	},
 	},
@@ -239,14 +256,17 @@ THREE.Ray.prototype = {
 
 
 			}
 			}
 
 
-			// Unsure if this is the correct method to handle this case.
-			return undefined;
+			// Null is preferable to undefined since undefined means.... it is undefined
+
+			return null;
 
 
 		}
 		}
 
 
 		var t = - ( this.origin.dot( plane.normal ) + plane.constant ) / denominator;
 		var t = - ( this.origin.dot( plane.normal ) + plane.constant ) / denominator;
 
 
-		return t;
+		// Return if the ray never intersects the plane
+
+		return t >= 0 ? t :  null;
 
 
 	},
 	},
 
 
@@ -254,9 +274,9 @@ THREE.Ray.prototype = {
 
 
 		var t = this.distanceToPlane( plane );
 		var t = this.distanceToPlane( plane );
 
 
-		if ( t === undefined ) {
+		if ( t === null ) {
 
 
-			return undefined;
+			return null;
 		}
 		}
 
 
 		return this.at( t, optionalTarget );
 		return this.at( t, optionalTarget );

+ 24 - 17
test/unit/math/Ray.js

@@ -64,25 +64,33 @@ test( "recast/clone", function() {
 test( "closestPointToPoint", function() {
 test( "closestPointToPoint", function() {
 	var a = new THREE.Ray( one3.clone(), new THREE.Vector3( 0, 0, 1 ) );
 	var a = new THREE.Ray( one3.clone(), new THREE.Vector3( 0, 0, 1 ) );
 
 
-	// nearby the ray
+	// behind the ray
 	var b = a.closestPointToPoint( zero3 );
 	var b = a.closestPointToPoint( zero3 );
-	ok( b.equals( new THREE.Vector3( 1, 1, 0 ) ), "Passed!" );
+	ok( b.equals( one3 ), "Passed!" );
+
+	// front of the ray
+	var c = a.closestPointToPoint( new THREE.Vector3( 0, 0, 50 ) );
+	ok( c.equals( new THREE.Vector3( 1, 1, 50 ) ), "Passed!" );
 
 
 	// exactly on the ray
 	// exactly on the ray
-	var c = a.closestPointToPoint( one3 );
-	ok( c.equals( one3 ), "Passed!" );
+	var d = a.closestPointToPoint( one3 );
+	ok( d.equals( one3 ), "Passed!" );
 });
 });
 
 
 test( "distanceToPoint", function() {
 test( "distanceToPoint", function() {
 	var a = new THREE.Ray( one3.clone(), new THREE.Vector3( 0, 0, 1 ) );
 	var a = new THREE.Ray( one3.clone(), new THREE.Vector3( 0, 0, 1 ) );
 
 
-	// nearby the ray
+	// behind the ray
 	var b = a.distanceToPoint( zero3 );
 	var b = a.distanceToPoint( zero3 );
-	ok( b == Math.sqrt( 2 ), "Passed!" );
+	ok( b === Math.sqrt( 3 ), "Passed!" );
+
+	// front of the ray
+	var c = a.distanceToPoint( new THREE.Vector3( 0, 0, 50 ) );
+	ok( c === Math.sqrt( 2 ), "Passed!" );
 
 
 	// exactly on the ray
 	// exactly on the ray
-	var c = a.distanceToPoint( one3 );
-	ok( c == 0, "Passed!" );
+	var d = a.distanceToPoint( one3 );
+	ok( d === 0, "Passed!" );
 });
 });
 
 
 test( "isIntersectionSphere", function() {
 test( "isIntersectionSphere", function() {
@@ -94,7 +102,7 @@ test( "isIntersectionSphere", function() {
 	var f = new THREE.Sphere( two3, 1 );
 	var f = new THREE.Sphere( two3, 1 );
 
 
 	ok( ! a.isIntersectionSphere( b ), "Passed!" );
 	ok( ! a.isIntersectionSphere( b ), "Passed!" );
-	ok( a.isIntersectionSphere( c ), "Passed!" );
+	ok( ! a.isIntersectionSphere( c ), "Passed!" );
 	ok( a.isIntersectionSphere( d ), "Passed!" );
 	ok( a.isIntersectionSphere( d ), "Passed!" );
 	ok( ! a.isIntersectionSphere( e ), "Passed!" );
 	ok( ! a.isIntersectionSphere( e ), "Passed!" );
 	ok( ! a.isIntersectionSphere( f ), "Passed!" );
 	ok( ! a.isIntersectionSphere( f ), "Passed!" );
@@ -103,7 +111,7 @@ test( "isIntersectionSphere", function() {
 test( "isIntersectionPlane", function() {
 test( "isIntersectionPlane", function() {
 	var a = new THREE.Ray( one3.clone(), new THREE.Vector3( 0, 0, 1 ) );
 	var a = new THREE.Ray( one3.clone(), new THREE.Vector3( 0, 0, 1 ) );
 
 
-	// parallel plane behind
+	// parallel plane in front of the ray
 	var b = new THREE.Plane().setFromNormalAndCoplanarPoint( new THREE.Vector3( 0, 0, 1 ), one3.clone().sub( new THREE.Vector3( 0, 0, -1 ) ) );
 	var b = new THREE.Plane().setFromNormalAndCoplanarPoint( new THREE.Vector3( 0, 0, 1 ), one3.clone().sub( new THREE.Vector3( 0, 0, -1 ) ) );
 	ok( a.isIntersectionPlane( b ), "Passed!" );
 	ok( a.isIntersectionPlane( b ), "Passed!" );
 
 
@@ -111,9 +119,9 @@ test( "isIntersectionPlane", function() {
 	var c = new THREE.Plane().setFromNormalAndCoplanarPoint( new THREE.Vector3( 0, 0, 1 ), one3.clone().sub( new THREE.Vector3( 0, 0, 0 ) ) );
 	var c = new THREE.Plane().setFromNormalAndCoplanarPoint( new THREE.Vector3( 0, 0, 1 ), one3.clone().sub( new THREE.Vector3( 0, 0, 0 ) ) );
 	ok( a.isIntersectionPlane( c ), "Passed!" );
 	ok( a.isIntersectionPlane( c ), "Passed!" );
 
 
-	// parallel plane infront
+	// parallel plane behind the ray
 	var d = new THREE.Plane().setFromNormalAndCoplanarPoint( new THREE.Vector3( 0, 0, 1 ), one3.clone().sub( new THREE.Vector3( 0, 0, 1 ) ) );
 	var d = new THREE.Plane().setFromNormalAndCoplanarPoint( new THREE.Vector3( 0, 0, 1 ), one3.clone().sub( new THREE.Vector3( 0, 0, 1 ) ) );
-	ok( a.isIntersectionPlane( d ), "Passed!" );
+	ok( ! a.isIntersectionPlane( d ), "Passed!" );
 
 
 	// perpendical ray that overlaps exactly
 	// perpendical ray that overlaps exactly
 	var e = new THREE.Plane().setFromNormalAndCoplanarPoint( new THREE.Vector3( 1, 0, 0 ), one3 );
 	var e = new THREE.Plane().setFromNormalAndCoplanarPoint( new THREE.Vector3( 1, 0, 0 ), one3 );
@@ -129,15 +137,15 @@ test( "intersectPlane", function() {
 
 
 	// parallel plane behind
 	// parallel plane behind
 	var b = new THREE.Plane().setFromNormalAndCoplanarPoint( new THREE.Vector3( 0, 0, 1 ), new THREE.Vector3( 1, 1, -1 ) );
 	var b = new THREE.Plane().setFromNormalAndCoplanarPoint( new THREE.Vector3( 0, 0, 1 ), new THREE.Vector3( 1, 1, -1 ) );
-	ok( a.intersectPlane( b ).equals( new THREE.Vector3( 1, 1, -1 ) ), "Passed!" );
+	ok( a.intersectPlane( b ) === null, "Passed!" );
 
 
 	// parallel plane coincident with origin
 	// parallel plane coincident with origin
 	var c = new THREE.Plane().setFromNormalAndCoplanarPoint( new THREE.Vector3( 0, 0, 1 ), new THREE.Vector3( 1, 1, 0 ) );
 	var c = new THREE.Plane().setFromNormalAndCoplanarPoint( new THREE.Vector3( 0, 0, 1 ), new THREE.Vector3( 1, 1, 0 ) );
-	ok( a.intersectPlane( c ).equals( new THREE.Vector3( 1, 1, 0 ) ), "Passed!" );
+	ok( a.intersectPlane( c ) === null, "Passed!" );
 
 
 	// parallel plane infront
 	// parallel plane infront
 	var d = new THREE.Plane().setFromNormalAndCoplanarPoint( new THREE.Vector3( 0, 0, 1 ), new THREE.Vector3( 1, 1, 1 ) );
 	var d = new THREE.Plane().setFromNormalAndCoplanarPoint( new THREE.Vector3( 0, 0, 1 ), new THREE.Vector3( 1, 1, 1 ) );
-	ok( a.intersectPlane( d ).equals( new THREE.Vector3( 1, 1, 1 ) ), "Passed!" );
+	ok( a.intersectPlane( d ).equals( a.origin ), "Passed!" );
 
 
 	// perpendical ray that overlaps exactly
 	// perpendical ray that overlaps exactly
 	var e = new THREE.Plane().setFromNormalAndCoplanarPoint( new THREE.Vector3( 1, 0, 0 ), one3 );
 	var e = new THREE.Plane().setFromNormalAndCoplanarPoint( new THREE.Vector3( 1, 0, 0 ), one3 );
@@ -145,7 +153,7 @@ test( "intersectPlane", function() {
 
 
 	// perpendical ray that doesn't overlap
 	// perpendical ray that doesn't overlap
 	var f = new THREE.Plane().setFromNormalAndCoplanarPoint( new THREE.Vector3( 1, 0, 0 ), zero3 );
 	var f = new THREE.Plane().setFromNormalAndCoplanarPoint( new THREE.Vector3( 1, 0, 0 ), zero3 );
-	ok( a.intersectPlane( f ) === undefined, "Passed!" );
+	ok( a.intersectPlane( f ) === null, "Passed!" );
 });
 });
 
 
 
 
@@ -209,4 +217,3 @@ test( "distanceToSegment", function() {
 	ok( distSqr < 0.0001, "Passed!" );
 	ok( distSqr < 0.0001, "Passed!" );
 });
 });
 
 
-