package classes.away3d.materials.utils.data
{
	import flash.geom.*;
	
	public class Ray{
		
		private var _orig:Vector3D = new Vector3D();
		private var _dir:Vector3D = new Vector3D();
		private var _intersect:Vector3D = new Vector3D();
		private var _tu:Vector3D = new Vector3D();
		private var _tv:Vector3D = new Vector3D();
		private var _w:Vector3D = new Vector3D();
		//private var _refresh:Boolean;
		
		//plane
		private var _pn:Vector3D = new Vector3D();
		private var _npn:Vector3D = new Vector3D();
		//private var _eps:Number = 1/10000;
		
		function Ray(){
		}
		/**
		* Defines the origin point of the Ray object
		* 
		* @return	Vector3D		The origin point of the Ray object
		*/
		public function set orig(o:Vector3D):void
		{
			_orig.x = o.x;
			_orig.y = o.y;
			_orig.z = o.z;
		}
		
		public function get orig():Vector3D
		{
			return _orig;
		}
		
		/**
		* Defines the directional vector of the Ray object
		* 
		* @return	Vector3D		The directional vector
		*/
		public function set dir(n:Vector3D):void
		{
			_dir.x = n.x;
			_dir.y = n.y;
			_dir.z = n.z;
		}
		
		public function get dir():Vector3D
		{
			return _dir;
		}
		
		/**
		* Defines the directional normal of the Ray object
		* 
		* @return	Vector3D		The normal of the plane
		*/
		public function get planeNormal():Vector3D
		{
			return _pn;
		}
		
		/**
		* Checks ray intersection by mesh.boundingRadius
		* 
		* @return	Boolean		If the ray intersect the mesh boundery
		*/
    	public function intersectBoundingRadius(pos:Vector3D, radius:Number):Boolean
		{
			var rsx:Number = _orig.x - pos.x;
			var rsy:Number = _orig.y - pos.y;
			var rsz:Number = _orig.z - pos.z;
			var B:Number = rsx*_dir.x + rsy*_dir.y + rsz*_dir.z;
			var C:Number = rsx*rsx + rsy*rsy + rsz*rsz - (radius*radius);
			
			return (B * B - C) > 0;
		}
		
		public function getIntersect(p0:Vector3D, p1:Vector3D, v0:Vector3D, v1:Vector3D, v2:Vector3D):Vector3D
		{

			_tu = v1.subtract(v0);
			_tv = v2.subtract(v0);
			
			_pn.x =  _tu.y*_tv.z - _tu.z*_tv.y;
			_pn.y =  _tu.z*_tv.x - _tu.x*_tv.z;
			_pn.z =  _tu.x*_tv.y - _tu.y*_tv.x;
			 
			if (_pn.length ==0)
				return null;
			
			_dir = p1.subtract(p0);
			_orig = p0.subtract(v0);
			 
			_npn.x = -_pn.x;
			_npn.y = -_pn.y;
			_npn.z = -_pn.z;
			
			var a:Number = _npn.dotProduct( _orig);
			
			if (a ==0)
				return null;
				
			var b:Number = _pn.dotProduct( _dir);
			var r:Number = a / b;
			
			//no hit
			if (r < 0 || r > 1)
				return null;
			
			//the ray intersects the plane at.
			_intersect.x = p0.x+(_dir.x*r);
			_intersect.y = p0.y+(_dir.y*r);
			_intersect.z = p0.z+(_dir.z*r);
 
			var uu:Number = _tu.dotProduct(_tu);
			var uv:Number = _tu.dotProduct(_tv);
			var vv:Number = _tv.dotProduct(_tv);
			_w = _intersect.subtract(v0);
			var wu:Number = _w.dotProduct(_tu);
			var wv:Number = _w.dotProduct(_tv);
			var d:Number = uv * uv - uu * vv;

			var v:Number = (uv * wv - vv * wu) / d;
			if (v < 0 || v > 1)
				return null;
			 
			var t:Number = (uv * wu - uu * wv) / d;
			if (t < 0 || (v + t) > 1.0)
				return null;
			
			return _intersect;
		}
		 
		
		
	}
}