/* 
 * DHTML 3-D demonstration
 * Tested to work in FireFox 2+ and Internet Explorer 5.5+
 * 
 * 2007-10-05 FF compatibility and IE<7 PNG fix by Tyler Uebele, with permission
 * 
 * Original code:
 * Copyright (c) Corey Tabaka 2005-2007
 * All rights reserved.
 *
 * This work may not be reused or modified without express permission.
 */


function degToRad(deg) {
	return Math.PI*deg/180.0;
}

function T(p, x, y, z, np) { //Transpose
	np[0] = p[0]+x;
	np[1] = p[1]+y;
	np[2] = p[2]+z;
	np[3] = p[3];
}

function Rz(p, q, np) { //Rotate on Z
	var c = Math.cos(q);
	var s = Math.sin(q);
	
	var x = p[0]*c - p[1]*s;
	var y = p[0]*s + p[1]*c;
	
	np[0] = x;
	np[1] = y;
	np[2] = p[2];
	np[3] = p[3];
}

function Rx(p, q, np) { //Rotate on X
	var c = Math.cos(q);
	var s = Math.sin(q);
	
	var y = p[1]*c - p[2]*s;
	var z = p[1]*s + p[2]*c;
	
	np[1] = y;
	np[2] = z;
	np[0] = p[0];
	np[3] = p[3];
}

function Ry(p, q, np) { //Rotate on Y
	var c = Math.cos(q);
	var s = Math.sin(q);
	
	var z = p[2]*c - p[0]*s;
	var x = p[2]*s + p[0]*c;
	
	np[2] = z;
	np[0] = x;
	np[1] = p[1];
	np[3] = p[3];
}

function perspective( fov, aspect, zNear, zFar ) {
	var xmin, xmax, ymin, ymax;
	var one_deltax, one_deltay, one_deltaz, doubleznear;

	xmax = zNear * Math.tan( Math.PI/180 * fov/2 );
	xmin = 0-xmax;

	ymax = xmax / aspect;
	ymin = 0-ymax;

	var m = new Array(16);

	doubleznear = 2 * zNear;
	one_deltax = 1 / (xmax - xmin);
	one_deltay = 1 / (ymax - ymin);
	one_deltaz = 1 / (zFar - zNear);

	m[0] = doubleznear * one_deltax;
	m[1] = 0;
	m[2] = 0;
	m[3] = 0;
	m[4] = 0;
	m[5] = 0;
	m[6] = (zFar + zNear) * one_deltaz;
	m[7] = 1;
	m[8] = 0;
	m[9] = doubleznear * one_deltay;
	m[10] = 0;
	m[11] = 0;
	m[12] = 0;
	m[13] = 0;
	m[14] = 0- zFar * doubleznear * one_deltaz;
	m[15] = 0;
	
	return m;
}

function project(p, m) {
	var np = new Array(4);

	var oow = 1 / p[3];
	np[0] = m[0] * p[0] * oow + m[12];
	np[1] = m[5] * p[1] * oow + m[13];
	np[2] = m[10] * p[2] * oow + m[14];
	np[3] = oow;
	
	return np;
}

function transform(p, m) {
	var np = new Array(4);
	
	np[0] = p[0]*m[0] + p[1]*m[4] + p[2]*m[8] + p[3]*m[12];
	np[1] = p[0]*m[1] + p[1]*m[5] + p[2]*m[9] + p[3]*m[13];
	np[2] = p[0]*m[2] + p[1]*m[6] + p[2]*m[10] + p[3]*m[14];
	np[3] = p[0]*m[3] + p[1]*m[7] + p[2]*m[11] + p[3]*m[15];

	return np;
}	
	

function view(x, y, width, height) {
	var m = [ 1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1 ];

	m[0] =  width / 2.0;
	m[12] = m[0] + x;
	m[5] = height / 2.0;
	m[13] = m[5] + y;
	m[10] = 0.5 * 1;
	m[14] = 0.5 * 1;
	
	return m;
}

function update(t) {
	// get the icons
	var icons = [];
	for (i in document.getElementById('world').childNodes) {
		if (document.getElementById('world').childNodes[i].className=='icons')
			icons.push(document.getElementById('world').childNodes[i]);
		
	}
	var np = [0, 0, 0, 1];
	for (var i=0; i<icons.length; i++) {
		Rz(points[i], theta*time, np);
		Rx(np, theta*time*0.98, np);
		Ry(np, theta*time*0.89, np);
		T(np,
			16*Math.sin(theta*time/4), 
			16*Math.sin(theta*time/2) -100,
			16*Math.sin(theta*time/3), np);
		
		var blend = 1 - Math.abs(np[1])/zFar;
		
		var width = Math.abs(64*mat[viewMinor] / np[1])*64;
		
		np = transform(np, mat);
		np = project(np, oView);
		
		icons[i].style.width = width+'px';
		icons[i].style.height = width+'px';
		icons[i].style.left = (np[0] - width/2)+'px';
		icons[i].style.top = (np[1] - width/2)+'px';
		icons[i].style.zIndex = Math.floor(blend*zFar);
	}
	
	time += t;
}


function dpx(i) {
	return i.replace(/px$/,'');
}

var points,world,time,theta,zFar,mat,oView,viewMinor;
function demoStart() {
	world = document.getElementById('world');
	//fill the world with some points
	points = new Array();
	for (var x=-16; x<=16; x+=16) {
		for (var y=-16; y<=16; y+=16) {
			for (var z=-16; z<=16; z+=16) {
				points[points.length] = [x, y, z, 1];
			}
		}
	}
	for (i in points) {
		if (bUseGif) {
			var img=document.createElement('img');
			img.className='icons';
			img.style.position='absolute';
			img.src='lightball.gif';
		} else if (!bPngFix) {
			var img=document.createElement('img');
			img.className='icons';
			img.style.position='absolute';
			img.src='transphere.png';
        } else {
			var img=document.createElement('span');
			img.className='icons';
			img.style.position='absolute';
			img.style.width='64px';
			img.style.height='64px';
			img.style.filter='progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'transphere.png\', sizingMethod=\'scale\')';
		}
		world.appendChild(img);
	}
	
	time = 0.0;
	theta = degToRad(100);
	zFar = 300;
	mat = perspective(60,  dpx(world.style.width)/dpx(world.style.height), 1, zFar);
	oView = view(0, 0, dpx(world.style.width), dpx(world.style.height));
	viewMinor = (dpx(world.style.width)/dpx(world.style.height)) <= 1 ? 9 : 0;

	//start 'loop'
	window.setInterval("update(1.0/40.0)", 1000/40);
//	update(1/40);
}