/**
 * @author bhouston / http://exocortex.com
 */

THREE.Ray3 = function ( origin, direction ) {


	if ( origin === undefined && direction === undefined ) {

		this.origin = new THREE.Vector3();
		this.direction = new THREE.Vector3( 0, 0, 0 );

	} else {

		this.origin = origin.clone();
		this.direction = direction.clone();

	}

};

THREE.Ray3.prototype = {

	constructor: THREE.Ray3,

	set: function ( origin, direction) {

		this.origin.copy( origin );
		this.direction.copy( direction );

		return this;

	},

	copy: function ( ray ) {

		this.origin.copy( ray.origin );
		this.direction.copy( ray.direction );

		return this;

	},

	at: function( t ) {

		return this.direction.clone().multiplyScalar( t ).addSelf( this.origin );

	},

	recast: function ( t ) {

		return new THREE.Ray3( this.at( t ), this.direction );

	},

	closestPointToPoint: function ( point ) {

		var result = point.clone().subSelf( this.origin );
		var directionDistance = result.dot( this.direction );

		return result.copy( this.direction ).multiplyScalar( directionDistance ).addSelf( this.origin );

	},

	distanceToPoint: function ( point ) {

		// NOTE: this creates a THREE.VEctor3 internally via closestPointToPoint
		// that is never returned, can be further GC optimized

		return this.closestPointToPoint( point ).distanceTo( point );

	},

	closestPointToRay: function ( ray ) {

		// Assumes the lines are normalized
		// based on algorithm in ILM's Imath Plane class.

	    __v1.copy( this.origin ).subSelf( ray.origin );
	    var c = this.direction.dot( __v1 );
	    var a = ray.direction.dot( this.direction );
	    var f = ray.direction.dot( __v1 );
	    var num = c - a * f;
	    var denom = a*a - 1;

	    var absDenom = ( ( denom >= 0 ) ? denom: -denom );

	    if ( absDenom < 1 )
	    {
			var absNum = ( ( num >= 0 ) ? num: -num );

			if (absNum >= absDenom * Number.MAX_VALUE ) {
				return this.origin.clone();
		    }
	    }

	    return this.direction.clone().multipleScalar( num / denom ).addSelf( this.origin );

	},

	distanceToRay: function ( ray ) {

		__v1.copy( this.direction ).crossSelf( ray.direction );
		__v2.copy( ray.origin ).subSelf( this.origin );

		var d = __v1.dot( __v2 );
		if( d >= 0 ) {
			return d;
		}
		return -1;

	},

	isIntersectionPlane: function ( plane ) {

		return ( plane.normal.dot( this.direction ) != 0 );

	},

	intersectPlane: function ( plane ) {

		var a = plane.normal.dot( this.direction );
		if ( a == 0.0 ) {

			// Unsure if this is the correct method to handle this case.
			return undefined;

		}

		var t = - ( ( this.origin ^ plane.normal ) - plane.constant ) / a;
		return this.at( t );

	},

	equals: function ( ray ) {

		return ray.origin.equals( this.origin ) && ray.direction.equals( this.direction );

	},

	clone: function () {

		return new THREE.Ray3().copy( this );

	}

};

THREE.Ray3.__v1 = new THREE.Vector3();
THREE.Ray3.__v2 = new THREE.Vector3();
@@ -743,16 +743,20 @@
 %0A%09recast
+Self
 : functi
@@ -773,59 +773,120 @@
 %0A%0A%09%09
-return new THREE.Ray3( this.at( t ), this.direction
+this.origin = this.at( t );%0A%0A%09%09return this;%0A%0A%09%7D,%0A%0A%09recast: function ( t ) %7B%0A%0A%09%09return this.clone().recastSelf( t
  );%0A
@@ -1941,24 +1941,90 @@
 AX_VALUE ) %7B
+%0A%0A%09%09%09%09// Unsure if this is the correct method to handle this case.
 %0A%09%09%09%09return 
@@ -2044,16 +2044,17 @@
 lone();%0A
+%0A
 %09%09    %7D%0A
@@ -2346,16 +2346,17 @@
 = 0 ) %7B%0A
+%0A
 %09%09%09retur
@@ -2360,20 +2360,94 @@
 turn d;%0A
+%0A
 %09%09%7D
-%0A
+ else %7B%0A%0A%09%09%09// Unsure if this is the correct method to handle this case.%0A%09
 %09%09return
@@ -2452,16 +2452,20 @@
 rn -1;%0A%0A
+%09%09%7D%0A
 %09%7D,%0A%0A%09is
@@ -2831,16 +2831,17 @@
  ) / a;%0A
+%0A
 %09%09return

add recastSelf and document that I am unsure of the best way to handle failure cases.