// Ray and Intersection objects (for raytracing). By John Haggerty (Slime).
// http://www.slimeland.com/
// Created January 21, 2003

// requires vector.js.

function Ray(start,dir, distmult)
{
	this.start = start;
	this.dir = Vector.normalize(dir);
	if (distmult) this.distmult = distmult;
	else this.distmult = 1;
	
	this.isshadowtest = false;
}
Ray.prototype.copy = function() {
	var toreturn = new Ray(this.start.copy(),this.dir.copy(),this.distmult);
	toreturn.shadowtest = this.shadowtest;
	return toreturn;
}
Ray.prototype.toString = function() {
	return '[Ray from ' + this.start + ' in the direction of ' + this.dir + ']';
}
Ray.prototype.transform = function(trans) {
	this.start.transform(trans);
	this.dir.transform(trans, true);
	var dirlength = this.dir.length();
	this.distmult = this.distmult/dirlength;
	this.dir = Vector.scalar(this.dir,1/dirlength); // (normalize)
}
Ray.prototype.transformed = function(trans) {
	var toreturn = this.copy();
	toreturn.distmult = 1;
	toreturn.transform(trans);
	return toreturn;
}
Ray.prototype.trace = function(objs, giveupat) // requires objects.js
{
	var winningisect = new Intersection(-1,this,null), intersections;
	for (var a=0; a < objs.length; a++)
	{
		intersections = objs[a].findIntersections(this);
		for (var b=0; b < intersections.length; b++)
		{
			if (intersections[b].depth > Ray.accuracy)
			{
				if (winningisect.depth == -1 || intersections[b].depth < winningisect.depth)
				{
					winningisect = intersections[b];
					if (this.isshadowtest && intersections[b].depth <= giveupat) return winningisect;
				}
				break;
			}
		}
	}
	return winningisect;
}
Ray.prototype.traceforcolor = function(objs,lights, tracelevel,effect) // requires objects.js, lightsource.js, texture.js
{
	var isect = this.trace(objs);

	if (isect.depth == -1) return new Color(0,0,0);
	return isect.objectstack[0].getColorAt(isect, objs,lights, tracelevel,effect);
}

function Intersection(depth, ray, obj)
{
	this.depth = depth;
	this.ray = ray;
	this.objectstack = [obj]; // first element is the lowest level object; rest of elements are unions/intersections/etc
}
Intersection.prototype.getpos = function()
{
	return Vector.add(this.ray.start,Vector.scalar(this.ray.dir,this.depth));
}
Intersection.prototype.addobject = function(obj)
{
	this.objectstack[this.objectstack.length] = obj;
}
Intersection.closerintersection = function(i1,i2) // for sorting
{
	return i1.depth - i2.depth;
}

Ray.accuracy = .00000001




