// LightSource object. By John Haggerty (Slime).
// http://www.slimeland.com/
// Created January 21, 2003

// requires vector.js.

function LightSource(pos,color)
{
	this.pos = pos;
	this.color = color;
	
	// area light stuff
	this.samplev1 = this.samplev2 = false;
	//this.v1 = this.v2 = Vector.O.copy();
	//this.minsampledepth = this.maxsampledepth = this.jitteramnt = 0;
	
	// spot light stuff
	this.spotlight = false;
	//this.dir = Vector.X.copy();
	//this.inneranglecosine = -1;
	//this.outerangle = Math.PI;
	//this.outeranglecosine = -1;
	//this.angledifference = 0;
}
LightSource.prototype.transform = function(trans) // requires transform.js
{
	this.pos.transform(trans);
	if (this.samplev1)
		this.v1.transform(trans,true);
	if (this.samplev2)
		this.v2.transform(trans,true);
	if (this.spotlight)
		this.dir.transform(trans,true);
}
LightSource.prototype.copy = function()
{
	return new LightSource(this.pos.copy(),this.color.copy());
}
LightSource.prototype.getLightColorAt = function(objs, pos)
{
	var toreturn, cosineangle;
	if (this.spotlight)
		cosineangle = Vector.dot(Vector.normalize(Vector.add(pos,this.pos.neg())),this.dir);
	if (this.spotlight && cosineangle < this.outeranglecosine) return new Color(0,0,0);
	if (this.samplev1 || this.samplev2)
	{
		toreturn = new Color(0,0,0);
		var numpointssampled = 0, foundblockedpath = false, foundunblockedpath = false, foundpartiallyblockedpath=false, thissample;
		var maxdepthnumcellsminusone = Math.pow(2,this.maxsampledepth), cellsize = 1/(maxdepthnumcellsminusone+1), xoffsetamnt=.5,yoffsetamnt=.5, cellskip;
		if (!this.samplev1) xoffsetamnt = 0;
		if (!this.samplev2) xoffsetamnt = 0;
		var stepxres = stepyres = 1;
		for (var depth=0; depth <= this.maxsampledepth; depth++)
		{
			if (this.samplev1)
				stepxres = Math.pow(2,depth)+1;
			if (this.samplev2)
				stepyres = Math.pow(2,depth)+1;
			cellskip = maxdepthnumcellsminusone/Math.pow(2,depth);
			if (depth > this.minsampledepth && (!foundpartiallyblockedpath && (foundblockedpath != foundunblockedpath)))
				break;
			for (var y=0; y < stepyres; y++)
			{
				var x=0; xstep=1;
				if (y%2 == 0 && depth != 0) {	
					x=1; xstep=2;
				}
				for (; x < stepxres; x+=xstep)
				{
					if (this.jitteramnt != 0)
					{
						if (this.samplev1)
							xoffsetamnt = .5+(Math.random()-.5)*this.jitteramnt;
						if (this.samplev2)
							yoffsetamnt = .5+(Math.random()-.5)*this.jitteramnt;
					}
					thissample = this.samplePoint(objs, Vector.add(
						Vector.add(
							this.pos,
							Vector.scalar(this.v1,((x*cellskip+xoffsetamnt)*cellsize)*2-1)
						),
						Vector.scalar(this.v2,((y*cellskip+yoffsetamnt)*cellsize)*2-1)
					),pos);
					if (thissample == this.color) foundunblockedpath = true;
					else if (thissample.red == 0 && thissample.green == 0 && thissample.blue == 0) foundblockedpath = true;
					else foundpartiallyblockedpath = true;
					toreturn = Color.add(toreturn,thissample);
					++numpointssampled;
				}
			}
		}
		toreturn = Color.scalar(toreturn,1/numpointssampled);
	}
	else
		toreturn = this.samplePoint(objs, this.pos,pos);
	if (this.spotlight && cosineangle < this.inneranglecosine)
	{
		var theangle = Math.acos(cosineangle);
		toreturn = Color.scalar(toreturn,LightSource.scurve((this.outerangle-theangle)/this.angledifference));
	}
	return toreturn;
}
LightSource.scurve = function(x){return x*x*(3-2*x);}
LightSource.prototype.samplePoint = function(objs, point,pos) // needs to be rewritten if transparency is ever supported; right now it just checks for any intersection at all between point and pos
{
	var dist = Vector.add(point,pos.neg());
	var shadowray = new Ray(pos,dist);
	shadowray.isshadowtest = true;
	dist = dist.length();
	var shadowisect = shadowray.trace(objs, dist);
	if (shadowisect.depth != -1 && shadowisect.depth <= dist)
		return new Color(0,0,0);
	else
		return this.color;
}