function CanvasScreen(canvas)
{		
	this.canvas = canvas;
	this.ctx = canvas.getContext('2d'); 
		

	this.reset  = function()
	{
		this.x = this.canvas.width;
		this.y = this.canvas.height;
		
		this.drawer = [];
		this.ticker = [];
	}
	this.reset();



	this.clear = function()
	{	
		this.ctx.clearRect(0,0, this.canvas.width, this.canvas.height);
		this.ctx.save();  
	}	
		
	this.register = function(obj)
	{

		if (typeof obj.draw == "function")
			this.drawer.push(obj);
		if (typeof obj.tick == "function")
			this.ticker.push(obj);
	}
		
	this.frame = function()
	{	
		this.clear();
		
		for(var i = 0; i < this.ticker.length; i ++)
		{
			this.ticker[i].tick();
		}
		
		for(var i = 0; i < this.drawer.length; i ++)
		{
			this.drawer[i].draw(this.ctx);
		}
		
		this.ctx.restore();
	}	
}		

var last = 0;
function framebench()
{
        var now = new Date().getTime() / 1000;
        var offset = now - last;

        last = now;

        return offset;
}

function getRandom(min, max)
{
	var range = max-min;

	var rand = Math.floor(Math.random()*(range+1))
	return min+rand;
}	
	
function Pos3D(x, y, z, w, h)
{	
	
	this.w = w;
	this.h = h;
	
	if (!this.w)
		this.w = scr.x;
	if (!this.h)
		this.h = scr.y;
	
        this.pos = Vector.create([x, y, z]);


        this.getX = function()  { return this.pos.e(1); }
        this.getY = function()  { return this.pos.e(2); }
        this.getZ = function()  { return this.pos.e(3); }

        this.setZ = function(z)
        {
                this.pos = Vector.create([this.pos.e(1), this.pos.e(2), parseInt(z)]);
        }

        this.get2dX = function()
        {
                return this.getX() * 300 / this.getZ() + (this.w/ 2)
        }

        this.get2dY = function()
        {
                return this.getY() * 300 / this.getZ() + (this.h / 2)
        }
}



function Object3D()
{

	this.points = [];

	this.points.push( new Pos3D( -100,-100,500) );
	this.points.push( new Pos3D( -100,100,500) );
	this.points.push( new Pos3D( 100,100,500) );
	this.points.push( new Pos3D( 100,-100,500) );

	this.points.push( new Pos3D( -100,-100,600) );
	this.points.push( new Pos3D( -100,100,600) );
	this.points.push( new Pos3D( 100,100,600) );
	this.points.push( new Pos3D( 100,-100,600) );

	this.points.push( new Pos3D( -100,-100,700) );
	this.points.push( new Pos3D( -100,100,700) );
	this.points.push( new Pos3D( 100,100,700) );
	this.points.push( new Pos3D( 100,-100,700) );

	this.points.push( new Pos3D( -100,-100,400) );
	this.points.push( new Pos3D( -100,100,400) );
	this.points.push( new Pos3D( 100,100,400) );
	this.points.push( new Pos3D( 100,-100,400) );


	this.points.push( new Pos3D( -150,-150,550) );
	this.points.push( new Pos3D( -150,150,550) );
	this.points.push( new Pos3D( 150,150,550) );
	this.points.push( new Pos3D( 150,-150,550) );


	this.points.push( new Pos3D( -50,-50,550) );
	this.points.push( new Pos3D( -50,50,550) );
	this.points.push( new Pos3D( 50,50,550) );
	this.points.push( new Pos3D( 50,-50,550) );

	this.tick = function()
	{
		this.rotate();
	}

	this.counter = 0;

	this.rotate = function(deg)
	{
		if (!deg)
			deg = 0.1;
		var line = Line.create([0,0,600], [0.8,-0.4,0.6]);
		for(i = 0; i < this.points.length; i ++)
		{
			var rot = this.points[i].pos.rotate(deg, line);
			this.points[i].pos = rot;
		}
	}
	
	this.draw = function(ctx)
	{		
		ctx.beginPath();  
		for(var i = 0; i < this.points.length; i ++)
		{	
			var x = this.points[i].get2dX();
			var y = this.points[i].get2dY();

			for(var ii = 0; ii < this.points.length; ii ++)
			{	

				var xx = this.points[ii].get2dX();
				var yy = this.points[ii].get2dY();

				ctx.moveTo(x, y);
				ctx.lineTo(xx, yy);
				
			}
		}	
		ctx.stroke();
	}	
}		


function Letter3D(chr, x, y, z, rot, axis)
{

	if (!rot)
		rot = [0,1,0];
	this.rot = rot;

	if (!axis)
		axis = [0,0,z];
	this.axis = axis;

	this.points = [];
	
	this.x = x;
	this.y = y;
	this.z = z;

	if (chr == "w")
	{
		this.points.push( new Pos3D( -10,-20,z, 20, 20) );
		this.points.push( new Pos3D( -5,0,z, 20, 20) );
		this.points.push( new Pos3D( 0,-8,z, 20, 20) );
		this.points.push( new Pos3D( +5,0,z, 20, 20) );
		this.points.push( new Pos3D( +10,-20,z,20, 20) );
	}
	else if (chr == "d")
	{
		this.points.push( new Pos3D( -2,0-20,z, 20,20) );
		this.points.push( new Pos3D( -2,0,z,20, 20) );
		this.points.push( new Pos3D( +2,-8,z,20, 20) );
		this.points.push( new Pos3D( +2,-12,z,20, 20) );
		this.points.push( new Pos3D( -2,-20,z,20,20) );

	}
	else if (chr == "i")
	{
		this.points.push( new Pos3D( 0,0-20,z,20,20) );
		this.points.push( new Pos3D( 0,0,z,20,20) );

	}
	else if (chr == "k")
	{
		this.points.push( new Pos3D( -5,0-20,z,20,20) );
		this.points.push( new Pos3D( -5,0,z,20,20) );
		this.points.push( new Pos3D( -5,0-8,z,20,20) );
		this.points.push( new Pos3D( +5,0,z,20,20) );
		this.points.push( new Pos3D( -5,-8,z,20,20) );
		this.points.push( new Pos3D( +5,-20,z,20,20) );

	}
	else if (chr == "c")
	{
		this.points.push( new Pos3D( +5,0-20,z,20,20) );
		this.points.push( new Pos3D( -5,0-20,z,20,20) );
		this.points.push( new Pos3D( -5,0,z,20,20) );
		this.points.push( new Pos3D( +5,0,z,20,20) );

	}
	else if (chr == "y")
	{
		this.points.push( new Pos3D( 0,0,z,20,20) );
		this.points.push( new Pos3D( 0,0-8,z,20,20) );
		this.points.push( new Pos3D( 0-5,0-20,z,20,20) );
		this.points.push( new Pos3D( 0,0-8,z,20,20) );
		this.points.push( new Pos3D( 0+5,0-20,z,20,20) );

	}
	else if (chr == "t")
	{
		this.points.push( new Pos3D( -10,-20,z,20,20) );
		this.points.push( new Pos3D( 10,-20,z,20,20) );
		this.points.push( new Pos3D( 0,-20,z,20,20) );
		this.points.push( new Pos3D( 0,0,z,20,20) );

	}
	else if (chr == "h")
	{
		this.points.push( new Pos3D( -10,-20,z,20,20) );
		this.points.push( new Pos3D( -10,0,z,20,20) );
		this.points.push( new Pos3D( -10,-10,z,20,20) );
		this.points.push( new Pos3D( 10,-10,z,20,20) );
		this.points.push( new Pos3D( 10,-20,z,20,20) );
		this.points.push( new Pos3D( 10,0,z,20,20) );

	}
	else if (chr == "f")
	{
		this.points.push( new Pos3D( 10,-20,z,20,20) );
		this.points.push( new Pos3D( -10,-20,z,20,20) );
		this.points.push( new Pos3D( -10,-10,z,20,20) );
		this.points.push( new Pos3D( 10,-10,z,20,20) );
		this.points.push( new Pos3D( -10,-10,z,20,20) );
		this.points.push( new Pos3D( -10,0,z,20,20) );

	}
	else if (chr == "e")
	{
		this.points.push( new Pos3D( 10,-20,z,20,20) );
		this.points.push( new Pos3D( -10,-20,z,20,20) );
		this.points.push( new Pos3D( -10,-10,z,20,20) );
		this.points.push( new Pos3D( 10,-10,z,20,20) );
		this.points.push( new Pos3D( -10,-10,z,20,20) );
		this.points.push( new Pos3D( -10,0,z,20,20) );
		this.points.push( new Pos3D( 10,0,z,20,20) );

	}


	this.tick = function()
	{
		this.rotate();
	}

	this.counter = 0;

	this.rotate = function(deg)
	{
		if (!deg)
			deg = 0.1;
		var line = Line.create(this.axis, this.rot);
		for(i = 0; i < this.points.length; i ++)
		{
			var rot = this.points[i].pos.rotate(deg, line);
			this.points[i].pos = rot;
		}
	}
	
	this.draw = function(ctx)
	{		
		ctx.beginPath();  
		for(var i = 0; i < this.points.length; i ++)
		{	
			var x = this.points[i].get2dX();
			var y = this.points[i].get2dY();

			ctx.lineTo(x+ this.x, y + this.y);
				
		}	
		ctx.stroke();
	}	
}		

function Starfield(num)	
{			
	this.stars = [];
			
	for(var i = 0; i < num; i ++)
	{		
		var p = new Pos3D(getRandom(-5000,5000), getRandom(-5000,5000), getRandom(0,5000) );
		this.stars.push(p);
	}		
			
	this.tick = function()
	{		
		for(var i in this.stars)
		{	
			var z = this.stars[i].getZ();
			z = z - 50;
			if (z < 1)
				z = 5000;
			this.stars[i].setZ(z);
		}	
	}		
			
	this.draw = function(ctx)
	{		
		for(var i = 0; i < this.stars.length; i ++)
		{	
			var x = this.stars[i].get2dX();
			var y = this.stars[i].get2dY();
			
			ctx.beginPath();  
			ctx.moveTo(x, y);
			ctx.lineTo(x, y+1);
			ctx.stroke();
		}	
	}		
}			
			
function BounceLine(x_max, y_max)
{			
	this.a = new Bouncer(x_max, y_max);
	this.b = new Bouncer(x_max, y_max);
	this.c = new Bouncer(x_max, y_max);
			
	this.tick = function()
	{		
		this.a.tick();
		this.b.tick();
		this.c.tick();
	}

	this.draw = function(ctx)
	{
		ctx.beginPath();  
		ctx.moveTo(this.a.pos.e(1),this.a.pos.e(2));
		ctx.lineTo(this.b.pos.e(1),this.b.pos.e(2));
		ctx.lineTo(this.c.pos.e(1),this.c.pos.e(2));
		ctx.lineTo(this.a.pos.e(1),this.a.pos.e(2));
		ctx.stroke();


	}

}

function PixelMap(w, h, factor, ctx)
{
	this.width = Math.ceil(w / factor);
	this.height = Math.ceil(h / factor);

	this.w = w;
	this.h = h;
	this.factor = factor;
	this.ctx = ctx;


	this.map = Array();

	this.getPixel = function(x, y)
	{
		var pos = (y*this.width + x)*3;

		if (!this.map[pos])
			return Array(0,0,0);

		return Array(this.map[pos], this.map[pos+1], this.map[pos+2]);
	}

	this.setPixel = function(x, y, r, g, b)
	{	
		
		r = Math.floor(r)||0;
		g = Math.floor(g)||0;
		b = Math.floor(b)||0;
		

		var pos = (y*this.width + x)*3;

		this.map[pos] = r;
		this.map[pos+1] = g;
		this.map[pos+2] = b;


		this.ctx.fillStyle = 'rgb('+r+','+g+','+b+')';  
		var rx = x * factor;
		var ry = y * factor;
		this.ctx.fillRect(rx, ry, factor, factor);
	}			
		
	this.draw = function() 
	{	
		
	}	
}				

function Plasma(pixelmap)	
{				
	this.pm = pixelmap;	
	this.timeDisplacement = 1;
				
				
	this.radians = function(val)
	{			
		var pi = Math.PI;
		return val*(pi/180);
	}			
				
	this.tick = function()	
	{			
		this.timeDisplacement += 1;
	}			
				
	this.draw = function(ctx)	
	{			
				
		this.calculation1 = Math.sin( this.radians(this.timeDisplacement * 0.61655617));
		this.calculation2 = Math.sin( this.radians(this.timeDisplacement * -3.6352262));
		
		for(var x = 0; x < this.pm.width; x ++)
		{		
			var xc = this.pm.factor * x;
			
			var s1 = 128 + 128 * Math.sin(this.radians(xc) * this.calculation1 );
			
			for(var y = 0; y < this.pm.height; y ++)
			{	
				var yc = this.pm.factor * y;
				var s2 = 128 + 128 * Math.sin(this.radians(yc) * this.calculation2);
				var s3 = 128 + 128 * Math.sin(this.radians((xc + yc + this.timeDisplacement * 5) / 2));  
				
				var s  = (s1+ s2 + s3) / 3;
				
				this.pm.setPixel(x, y, s, 255-s/2, 255, 255/2);
			}	
		}		
		this.pm.draw(ctx);
	}			
}				
				

