/* This demo reads some mocap data from an xml file (selected through a dropDown List)
   and displays a simple collada object to represent each point.  */

// Global variables
var cam;
var scn;
var pick;
var elapsed;
var frame;
var maxFrames;
var xmlDoc;
var x;
var frate;
var origFrate;
var connection;
var pointList;
//var lineList;
var totaltime;
var things = [];
var nummarkers;
var lines = [];
var numconnections;
var labels = [];
var pointsSmooth = true;
var paused = false;
var shiftIt = false;
var pointsVisible = true;
var linesVisible = true;
var redMat;
var greenMat;
var blueMat;

var lastKey = -1;

// load the model before rendering page
c3dl.addMainCallBack(canvasMain, "mocap");
c3dl.addModel("/wp-content/2.0Release/mocap_spheres/models/sphere.dae");

/* This callback function is used by the scene class.  Every time
   the scene is updated, it will get called.  This function tests
   the amount of time elapsed since the last update and selects
   the frame to display accordingly. */
function updatePoints(time)
{
	// totaltime stores amount of time passed since page was loaded.
	// elapsed stores the time since the last update
	// time is in milliseconds.
	if(!paused) {
		paused = true;
		if(frate > 0)
		{
			totaltime += time;
			elapsed += time;
			frame += Math.round(elapsed / (1000/frate));
			if(frame >= maxFrames || frame < 0) {
				frame = 0;
			}
			}
			if(Math.round(elapsed / (1000/frate)) > 0) {
				elapsed = 0;
				var currentObjects = x[frame].getElementsByTagName("point");

				//first do the markers
				if(pointsVisible)
				{
					var px = 0;
					var py = 0;
					var pz = 0;
					for(var i = 0; i < currentObjects.length; i++)
					{
						px = parseInt(currentObjects[i].attributes.item(0).nodeValue);
						py = parseInt(currentObjects[i].attributes.item(1).nodeValue);
						pz = parseInt(currentObjects[i].attributes.item(2).nodeValue);
						if(px != 0 || py != 0 || pz != 0) {
							things[i].translate([px-things[i].getPosition()[0], py-things[i].getPosition()[1], pz-things[i].getPosition()[2]]);
							things[i].setVisible(true);
						}
						else {
							things[i].setVisible(false);
						}
					}
				}

				//now lines
				if(linesVisible)
				{
					var conn = "";
					var ind1 = -1;
					var ind2 = -1;
					var p2x = 0;
					var p2y = 0;
					var p2z = 0;
					for(var i = 0; i < connections.length; i++) {
						conn = connections[i];
						ind1 = parseInt(conn.substring(1,conn.indexOf(",")));
						ind2 = parseInt(conn.substring(conn.indexOf(",")+1,conn.indexOf(")")));
						px = parseInt(currentObjects[ind1].attributes.item(0).nodeValue);
						py = parseInt(currentObjects[ind1].attributes.item(1).nodeValue);
						pz = parseInt(currentObjects[ind1].attributes.item(2).nodeValue);
						p2x = parseInt(currentObjects[ind2].attributes.item(0).nodeValue);
						p2y = parseInt(currentObjects[ind2].attributes.item(1).nodeValue);
						p2z = parseInt(currentObjects[ind2].attributes.item(2).nodeValue);

						//if both these points are valid, draw a line between them
						if((px != 0 || py != 0  || pz != 0) && (p2x != 0 || p2y != 0 || p2z != 0)) {
							lines[i].setCoordinates([px,py,pz],[p2x,p2y,p2z]);
						}
						else {//otherwise draw a null line (we have to tell it something)
							lines[i].setCoordinates([0,0,0],[0,0,0]);
						}
					}
				}
			}
			paused = false;
		}
	//}
	
	document.getElementById('fps').innerHTML = "real FPS = " + scn.getFPS();
}

// the function that will be called by the web page. canvasName is the name
// of the canvas where the scene will show.
function canvasMain(canvasName)
{
	// create a new Scene object
	scn = new c3dl.Scene();
	scn.setCanvasTag(canvasName);
  
	renderer = new c3dl.WebGL();
	renderer.createRenderer(this);

	scn.setRenderer(renderer);

	totaltime = 0;
	elapsed = 0;
	frame = 0;

	// check that it was successful 
	scn.init()

	// default ambient light is full, so turn it all off to 
	// control color with spotlight.
	scn.setAmbientLight([0,0,0,1]);
	
	//now add a spot light to give some depth to the scene
	var spotlight = new c3dl.DirectionalLight();
	spotlight.setName("dir");
	spotlight.setOn(true);
	spotlight.setDiffuse([0.8,0.8,0.8,1]);
	spotlight.setDirection([-1,-1,-1]);
	spotlight.setOn(true);
	scn.addLight(spotlight);

	redMat = new c3dl.Material();
	redMat.setEmission([0.5,0,0]);
	redMat.setDiffuse([0.4,0.4,0.4]);
	greenMat = new c3dl.Material();
	greenMat.setEmission([0,0.5,0]);
	greenMat.setDiffuse([0.4,0.4,0.4]);
	blueMat = new c3dl.Material();
	blueMat.setEmission([0,0,0.5]);
	blueMat.setDiffuse([0.4,0.4,0.4]);

	newScene("/wp-content/2.0Release/mocap_spheres/Stooges-Floor-Run.xml");

	// create a camera
	cam = new c3dl.FreeCamera();
	cam.setPosition(new Array(-200,1500,2800));
	cam.setLookAtPoint(new Array(-200,1000,-100));

	scn.setCamera(cam);
	scn.setUpdateCallback(updatePoints);
	scn.setKeyboardCallback(up,down);
	scn.startScene();
}

function down(event)
{
	var cam = scn.getCamera();
    	var vel = [0,0,0];
    	if(event.keyCode != lastKey) {
        	lastKey = event.keyCode;
        	if(event.shiftKey) {
            		vel = cam.getAngularVel();
          		cam.setLinearVel([0,0,0]);
            		switch(event.keyCode) {//determine the key pressed
                		case 37://left arrow
               				cam.setAngularVel([vel[0],0.001,vel[2]]);//yaw left
                    		break;
                		case 39://right arrow
                    			cam.setAngularVel([vel[0],-0.001,vel[2]]);//yaw right
                    		break;
                		case 40://down arrow
                    			cam.setAngularVel([0.001,vel[1],vel[2]]);//pitch down
                		break;
                		case 38://up arrow
                    			cam.setAngularVel([-0.001,vel[1],vel[2]]);//pitch up
                		break;
            		}
        	}
        	else {
            		var mov = [0,0,0];
            		vel = cam.getLinearVel();
            		switch(event.keyCode) {//determine the key pressed
         	       		case 37://left arrow
                			mov = c3dl.multiplyVector(cam.getLeft(),1,mov);
                		break;
                		case 39://right arrow
                    			mov = c3dl.multiplyVector(cam.getLeft(),-1,mov);
                		break;
                		case 40://down arrow
                    			mov = c3dl.multiplyVector(cam.getDir(),-1,mov); //move the camera 'back' (towards the user)
                		break;
                		case 38://up arrow
                    			mov = c3dl.multiplyVector(cam.getDir(),1,mov);//move the camera 'forward' (into the scene)
                		break;
            		}
            		cam.setLinearVel([vel[0]+mov[0],vel[1]+mov[1],vel[2]+mov[2]]);
        	}
	}
}

function up(event)
{
	// A
	if(event.keyCode == 65)
	{
		if(frate - 5 >= 0)
		{
			frate -= 5;
			document.getElementById('debug').innerHTML = "speed = " + frate/origFrate + " times normal.";
		}
	}

	// Q
	if(event.keyCode == 81)
	{
		frate += 5;
		document.getElementById('debug').innerHTML = "speed = " + frate/origFrate + " times normal.";
	}


	// V change visibility
	if(event.keyCode == 86)
	{
		pointsVisible = !pointsVisible;
		if(!pointsVisible)
		{
			for(var i = 0; i < things.length; i++)
			{
				things[i].setVisible(pointsVisible);
			}
		}
	}
	
	// L toggle line visibility
	if(event.keyCode == 76) {
		linesVisible = !linesVisible;
		for(var i = 0; i < lines.length; i++)
		{
			lines[i].setVisible(linesVisible);
		}
	}

	var cam = scn.getCamera();
        var vel;
        lastKey = -1;
        if(event.shiftKey) {
                vel = cam.getAngularVel();
                switch(event.keyCode) {//determine the key released, if it is any of the angular velocity keys, set angular velocity to 0
			case 37://left arrow
			case 39://right arrow
				cam.setAngularVel([vel[0],0,vel[2]]);//stop yawing
			break;
			case 40://down arrow
			case 38://up arrow
				cam.setAngularVel([0,vel[1],vel[2]]);//stop pitching
			break;
		}
	}
	else {
		var pos = cam.getPosition();
		vel = cam.getLinearVel();
		switch(event.keyCode) {//determine the key released, if it is one of the linear velocity keys, set linear velocity to 0
			case 37://left arrow
			case 39://right arrow
				cam.setLinearVel([0,vel[1],vel[2]]);
			break;
			case 40://down arrow
			case 38://up arrow
				cam.setLinearVel([vel[0],vel[1],0]);
			break;
			case 16://shift key
				cam.setAngularVel([0,0,0]);
			break;
		}
	}	
}

function newScene(fName)
{
	paused = true;
	for(var i = 0; i < things.length; i++)
	{
		scn.removeObjectFromScene(things[i]);
	}
	for(var i = 0; i < lines.length; i++)
	{
		scn.removeObjectFromScene(lines[i]);
	}
	totaltime = 0;
	elapsed = 0;
	frame = 0;

	var xmlReq = new XMLHttpRequest();
	xmlReq.open("GET",fName, false);
	xmlReq.send(null);
	xmlDoc=xmlReq.responseXML;
	labels = xmlDoc.getElementsByTagName("order")[0].childNodes[0].nodeValue.split(" ");
	nummarkers = labels.length;
	var colerMat;
	for(var i = 0; i < nummarkers; i++)
	{
		if(getColor(labels[i])[0] == 1)
		{
			colorMat = redMat;
		}
		else if(getColor(labels[i])[1] == 1)
		{
			colorMat = greenMat;
		}
		else
		{
			colorMat = blueMat;
		}
		things[i] = new c3dl.Collada();
		things[i].init("/wp-content/2.0Release/mocap_spheres/models/sphere.dae");
		things[i].scale([7,7,7]);
		things[i].setMaterial(colorMat);	
		// Add the object to the scene
		scn.addObjectToScene(things[i]);
	}
	
	var hold = xmlDoc.getElementsByTagName("connections")[0];//there can be only 1
	connections = hold.childNodes[0].nodeValue.split(" ");//get the list of marker connections
	numconnections = connections.length;
	var conn = "";
	var ind1 = -1;
	var ind2 = -1;
	for(var i = 0; i < numconnections; i++)
	{
		conn = connections[i];
		ind1 = parseInt(conn.substring(1,conn.indexOf(",")));
		ind2 = parseInt(conn.substring(conn.indexOf(",")+1,conn.indexOf(")")));
		lines[i] = new c3dl.Line();
		lines[i].setCoordinates([0,0,0],[0,0,0]);
		lines[i].setColors(getColor(labels[ind1]),getColor(labels[ind2]));
		scn.addObjectToScene(lines[i]);
	}
	
	x = xmlDoc.getElementsByTagName("frame");
	maxFrames = x.length;
	var fileInfo = xmlDoc.getElementsByTagName("info");
	frate = parseInt(fileInfo[0].attributes.item(3).nodeValue);
	origFrate = frate;
	
	paused = false;
}

//find out what color the marker should be (r,g,b)
function getColor(wholeName)
{
	var startIndex = wholeName.indexOf(":");
	if(startIndex < 0)
	{
		startIndex = -1;
	}
	var markerName = wholeName.substring(startIndex+1,wholeName.length);
	if(markerName.charAt(0) == 'L')
	{
		return [1,0,0];
	}
	else if(markerName.charAt(0) == 'R')
	{
		return [0,1,0];
	}
	else
	{
		return [0,0,1];
	}
}

