//  Mitch Lee   cs184-al
//  mitchl@uclink4.berkeley.edu
//  Gordon Huang  cs184-am
//  gordonh@uclink4.berkeley.edu
//	10/18/98
//	Project 1
//	playback.java
//	Based on time figures out keyframes and interpolation
//  Controls all 6 legs and movement

import vrml.*;
import vrml.node.*;
import vrml.field.*;
import java.lang.Math;

public class playback extends Script {

	private float l1j1rot[] = {
			0.9949368f, -0.08917375f, -0.04635104f, 0.7287968f,
		0.28730604f, 0.33447927f, 0.89754015f, 0.68134195f,
0.89989936f, 0.14172056f, 0.41242877f, 0.36786878f,
0.9540405f, 0.07744094f, -0.28949788f, 0.3946001f,
0.9949368f, -0.08917375f, -0.04635104f, 0.7287968f,
	};
	private float l1j2rot[] = {
			
0.0f, 1.0f, 0.0f, -2.359097f,
0.0f, 1.0f, 0.0f, -2.383498f,
0.0f, 1.0f, 0.0f, -2.5588436f,
0.0f, 1.0f, 0.0f, -2.6332743f,
0.0f, 1.0f, 0.0f, -2.359097f,
	};
	private float l2j1rot[] = {
				0.9678557f, -0.1274012f, -0.21684927f, 0.37437147f,
0.9536081f, -0.17113975f, 0.24767244f, 0.38971546f,
0.9248219f, -0.18669914f, -0.33143246f, 0.66532016f,
0.295357f, -0.47923216f, -0.8264993f, 0.8452174f,
0.9678557f, -0.1274012f, -0.21684927f, 0.37437147f,
	};
	private float l2j2rot[] = {
				0.0f, 1.0f, 0.0f, -2.5718644f,
0.0f, 1.0f, 0.0f, -2.5718644f,
0.0f, 1.0f, 0.0f, -2.045474f,
0.0f, 1.0f, 0.0f, -2.503487f,
0.0f, 1.0f, 0.0f, -2.5718644f,
	};	
	private float l3j1rot[] = {
			0.99992496f, -6.689596E-5f, -0.012247752f, 0.4087012f,
0.8476589f, -0.08312724f, -0.52398866f, 0.4772813f,
0.9997639f, 0.0057087536f, 0.020965943f, 0.85237247f,
0.5369517f, 0.53624487f, 0.6512483f, 0.51731414f,
0.99992496f, -6.689596E-5f, -0.012247752f, 0.4087012f,
	};
	private float l3j2rot[] = {
				0.0f, 1.0f, 0.0f, -2.8645346f,
0.0f, 1.0f, 0.0f, -2.8645346f,
0.0f, 1.0f, 0.0f, -2.3151836f,
0.0f, 1.0f, 0.0f, -2.7054083f,
0.0f, 1.0f, 0.0f, -2.8645346f,
		};
	private float l4j1rot[] = {
				0.9996091f, -0.0062208893f, -0.027260588f, 0.9218731f,
0.2965087f, -0.77653766f, -0.5559422f, 0.5107717f,
0.9528182f, -0.29107788f, 0.08609088f, 0.28360817f,
0.60835546f, -0.17341053f, 0.77448857f, 0.44391876f,
0.9996091f, -0.0062208893f, -0.027260588f, 0.9218731f,
		};
	private float l4j2rot[] = {
				0.0f, 1.0f, 0.0f, -3.108174f,
0.0f, 1.0f, 0.0f, -2.5140347f,
0.0f, 1.0f, 0.0f, -2.5381017f,
0.0f, 1.0f, 0.0f, -2.517754f,
0.0f, 1.0f, 0.0f, -2.88114f,
0.0f, 1.0f, 0.0f, -3.108174f,
		};
	private float l5j1rot[] = {
				0.9332065f, 0.20679013f, 0.29387882f, 0.35900125f,
0.6466921f, -0.14652857f, 0.7485446f, 0.59388775f,
0.93510044f, -0.3479998f, -0.06695765f, 0.66251016f,
0.39582986f, -0.68051827f, -0.6166143f, 0.4274474f,
0.9332065f, 0.20679013f, 0.29387882f, 0.35900125f,
		};

	private float l5j2rot[] = {
				0.0f, 1.0f, 0.0f, -2.9855738f,
0.0f, 1.0f, 0.0f, -2.7761695f,
0.0f, 1.0f, 0.0f, -2.2663805f,
0.0f, 1.0f, 0.0f, -2.651967f,
0.0f, 1.0f, 0.0f, -2.9855738f,
		};
	private float l6j1rot[] = {
				0.9902485f, -0.016790086f, -0.13829562f, 0.741867f,
0.6600457f, 0.18175314f, 0.7289071f, 0.54624254f,
0.99095345f, 0.07302619f, 0.11259114f, 0.3114836f,
0.30767134f, -0.114445254f, -0.94458485f, 0.4520617f,
0.9902485f, -0.016790086f, -0.13829562f, 0.741867f,
		};
	private float l6j2rot[] = {
				0.0f, 1.0f, 0.0f, -2.2827806f,
0.0f, 1.0f, 0.0f, -2.7954702f,
0.0f, 1.0f, 0.0f, -2.8665118f,
0.0f, 1.0f, 0.0f, -2.292931f,
0.0f, 1.0f, 0.0f, -2.2827806f,

		};

	private float body[];
	private float theta;
	private float bodyrot[];
	private int numFrames;
	private SFRotation l1j1_rotation_changed;		
	private SFRotation l1j2_rotation_changed;		
	private SFRotation l2j1_rotation_changed;		
	private SFRotation l2j2_rotation_changed;		
	private SFRotation l3j1_rotation_changed;		
	private SFRotation l3j2_rotation_changed;		
	private SFRotation l4j1_rotation_changed;		
	private SFRotation l4j2_rotation_changed;		
	private SFRotation l5j1_rotation_changed;		
	private SFRotation l5j2_rotation_changed;		
	private SFRotation l6j1_rotation_changed;		
	private SFRotation l6j2_rotation_changed;		
	private SFVec3f body_translation_changed;
	private SFRotation body_rotation_changed;

	public void initialize () {
		System.out.println("start");
		body = new float[3];
		theta = 0f;
		bodyrot = new float[4];
		bodyrot[0] = 0f;
		bodyrot[1] = 0f;
		bodyrot[2] = 1f;
		bodyrot[3] = 0f;
		
		l1j1_rotation_changed = (SFRotation) getEventOut("l1j1_rotation_changed");
		l1j2_rotation_changed = (SFRotation) getEventOut("l1j2_rotation_changed");
		l2j1_rotation_changed = (SFRotation) getEventOut("l2j1_rotation_changed");
		l2j2_rotation_changed = (SFRotation) getEventOut("l2j2_rotation_changed");
		l3j1_rotation_changed = (SFRotation) getEventOut("l3j1_rotation_changed");
		l3j2_rotation_changed = (SFRotation) getEventOut("l3j2_rotation_changed");
		l4j1_rotation_changed = (SFRotation) getEventOut("l4j1_rotation_changed");
		l4j2_rotation_changed = (SFRotation) getEventOut("l4j2_rotation_changed");
		l5j1_rotation_changed = (SFRotation) getEventOut("l5j1_rotation_changed");
		l5j2_rotation_changed = (SFRotation) getEventOut("l5j2_rotation_changed");
		l6j1_rotation_changed = (SFRotation) getEventOut("l6j1_rotation_changed");
		l6j2_rotation_changed = (SFRotation) getEventOut("l6j2_rotation_changed");
		body_translation_changed = (SFVec3f) getEventOut("body_translation_changed");
		body_rotation_changed = (SFRotation) getEventOut("body_rotation_changed");

		numFrames = 5;

	}

	// Interpolator
	private void set_fraction (float input) {
		
		theta += 0.0010f;

		body[0] += 0.1f*(float)Math.cos(theta);
		body[1] += 0.1f*(float)Math.sin(theta);

		body_translation_changed.setValue(body);
		bodyrot[3] = theta;
		body_rotation_changed.setValue(bodyrot);
				
		float val = input * (numFrames - 1);
		System.out.println("clk: " + input);
		int lowertime = 4 * ((int)Math.floor((double)val));
		int uppertime = 4 * ((int)Math.ceil((double)val));

		float l1j1_lowerbound;
		float l1j1_upperbound;
		float l1j2_lowerbound;
		float l1j2_upperbound;
		float l2j1_lowerbound;
		float l2j1_upperbound;
		float l2j2_lowerbound;
		float l2j2_upperbound;
		float l3j1_lowerbound;
		float l3j1_upperbound;
		float l3j2_lowerbound;
		float l3j2_upperbound;
		float l4j1_lowerbound;
		float l4j1_upperbound;
		float l4j2_lowerbound;
		float l4j2_upperbound;
		float l5j1_lowerbound;
		float l5j1_upperbound;
		float l5j2_lowerbound;
		float l5j2_upperbound;
		float l6j1_lowerbound;
		float l6j1_upperbound;
		float l6j2_lowerbound;
		float l6j2_upperbound;

		float slope;
		float b;

		float l1j1_current_angle[];	
		float l1j2_current_angle[];			
		float l2j1_current_angle[];
		float l2j2_current_angle[];
		float l3j1_current_angle[];
		float l3j2_current_angle[];
		float l4j1_current_angle[];
		float l4j2_current_angle[];
		float l5j1_current_angle[];
		float l5j2_current_angle[];
		float l6j1_current_angle[];
		float l6j2_current_angle[];

		l1j1_current_angle = new float[4];
		l1j2_current_angle = new float[4];
		l2j1_current_angle = new float[4];
		l2j2_current_angle = new float[4];
		l3j1_current_angle = new float[4];
		l3j2_current_angle = new float[4];
		l4j1_current_angle = new float[4];
		l4j2_current_angle = new float[4];
		l5j1_current_angle = new float[4];
		l5j2_current_angle = new float[4];
		l6j1_current_angle = new float[4];
		l6j2_current_angle = new float[4];

		System.out.println("for");
		for (int i = 0; i <= 3; i++) {
		l1j1_lowerbound = l1j1rot[lowertime + i];
		l1j1_upperbound = l1j1rot[uppertime + i];
		l1j2_lowerbound = l1j2rot[lowertime + i];
		l1j2_upperbound = l1j2rot[uppertime + i];
		l2j1_lowerbound = l2j1rot[lowertime + i];
		l2j1_upperbound = l2j1rot[uppertime + i];
		l2j2_lowerbound = l2j2rot[lowertime + i];
		l2j2_upperbound = l2j2rot[uppertime + i];
		l3j1_lowerbound = l3j1rot[lowertime + i];
		l3j1_upperbound = l3j1rot[uppertime + i];
		l3j2_lowerbound = l3j2rot[lowertime + i];
		l3j2_upperbound = l3j2rot[uppertime + i];
		l4j1_lowerbound = l4j1rot[lowertime + i];
		l4j1_upperbound = l4j1rot[uppertime + i];
		l4j2_lowerbound = l4j2rot[lowertime + i];
		l4j2_upperbound = l4j2rot[uppertime + i];
		l5j1_lowerbound = l5j1rot[lowertime + i];
		l5j1_upperbound = l5j1rot[uppertime + i];
		l5j2_lowerbound = l5j2rot[lowertime + i];
		l5j2_upperbound = l5j2rot[uppertime + i];
		l6j1_lowerbound = l6j1rot[lowertime + i];
		l6j1_upperbound = l6j1rot[uppertime + i];
		l6j2_lowerbound = l6j2rot[lowertime + i];
		l6j2_upperbound = l6j2rot[uppertime + i];
		
		

		slope = (l1j1_upperbound - l1j1_lowerbound) / ((uppertime - lowertime)/4);
		b = l1j1_lowerbound - (slope * (lowertime/4));
		l1j1_current_angle[i] = (slope * val) + b;
		System.out.println("S: " + slope +" " + b);
		System.out.println(i);

		slope = (l1j2_upperbound - l1j2_lowerbound) / ((uppertime - lowertime)/4);
		b = l1j2_upperbound - (slope * (uppertime/4));
		l1j2_current_angle[i] = (slope * val) + b;

		slope = (l2j1_upperbound - l2j1_lowerbound) / ((uppertime - lowertime)/4);
		b = l2j1_upperbound - (slope * (uppertime/4));
		l2j1_current_angle[i] = (slope * val) + b;

		slope = (l2j2_upperbound - l2j2_lowerbound) / ((uppertime - lowertime)/4);
		b = l2j2_upperbound - (slope * (uppertime/4));
		l2j2_current_angle[i] = (slope * val) + b;

		slope = (l3j1_upperbound - l3j1_lowerbound) / ((uppertime - lowertime)/4);
		b = l3j1_upperbound - (slope * (uppertime/4));
		l3j1_current_angle[i] = (slope * val) + b;

		slope = (l3j2_upperbound - l3j2_lowerbound) / ((uppertime - lowertime)/4);
		b = l3j2_upperbound - (slope * (uppertime/4));
		l3j2_current_angle[i] = (slope * val) + b;

		slope = (l4j1_upperbound - l4j1_lowerbound) / ((uppertime - lowertime)/4);
		b = l4j1_upperbound - (slope * (uppertime/4));
		l4j1_current_angle[i] = (slope * val) + b;

		slope = (l4j2_upperbound - l4j2_lowerbound) / ((uppertime - lowertime)/4);
		b = l4j2_upperbound - (slope * (uppertime/4));
		l4j2_current_angle[i] = (slope * val) + b;

		slope = (l5j1_upperbound - l5j1_lowerbound) / ((uppertime - lowertime)/4);
		b = l5j1_upperbound - (slope * (uppertime/4));
		l5j1_current_angle[i] = (slope * val) + b;

		slope = (l5j2_upperbound - l5j2_lowerbound) / ((uppertime - lowertime)/4);
		b = l5j2_upperbound - (slope * (uppertime/4));
		l5j2_current_angle[i] = (slope * val) + b;

		slope = (l6j1_upperbound - l6j1_lowerbound) / ((uppertime - lowertime)/4);
		b = l6j1_upperbound - (slope * (uppertime/4));
		l6j1_current_angle[i] = (slope * val) + b;

		slope = (l6j2_upperbound - l6j2_lowerbound) / ((uppertime - lowertime)/4);
		b = l6j2_upperbound - (slope * (uppertime/4));
		l6j2_current_angle[i] = (slope * val) + b;

		}

		l1j1_rotation_changed.setValue(l1j1_current_angle);
		l1j2_rotation_changed.setValue(l1j2_current_angle);
		l2j1_rotation_changed.setValue(l2j1_current_angle);
		l2j2_rotation_changed.setValue(l2j2_current_angle);
		l3j1_rotation_changed.setValue(l3j1_current_angle);
		l3j2_rotation_changed.setValue(l3j2_current_angle);
		l4j1_rotation_changed.setValue(l4j1_current_angle);
		l4j2_rotation_changed.setValue(l4j2_current_angle);
		l5j1_rotation_changed.setValue(l5j1_current_angle);
		l5j2_rotation_changed.setValue(l5j2_current_angle);
		l6j1_rotation_changed.setValue(l6j1_current_angle);
		l6j2_rotation_changed.setValue(l6j2_current_angle);


	}

	public void processEvent (Event e){
		String EventName = e.getName();
		if (EventName.equals("set_fraction")) {
			set_fraction(((ConstSFFloat)e.getValue()).getValue());
		}
		
	}
}