API Docs for:
Show:

File: workspace\templates\renderScript.js

//<script>
;



if( typeof(startupScripts) == 'undefined'){

	var startupScripts = {
		"0":function(){},
		"1":function(){},
		"2":function(){},
		"3":function(){},
		"4":function(){},
		"5":function(){},
		"6":function(){},
		"7":function(){}
	};

}



/**
*
* Class containing all the methods used in the 3d visual assembly
* @class renderGlobal
* @static
*/




// Put recieved data about assembly into here. The code handles the rest.
// theXMLFile should be a string, and theSTLFiles as a binary ArrayBuffer
// Any text-based STL files should be in an 8-bit encoding
/**
*
* The function which handles the actual rendering of the solution file animation
* and loading in the models
*
* @method rdr_recieveData
* @for renderGlobal
* @param {String} theXMLFile
* @param {Object} theSTLFiles
* @return {Void}
*
*/
function rdr_receiveData(theXMLFile, theSTLFiles){

	theXML=theXMLFile;

	parts.length=0;
	var pos=0;
	var lim=theSTLFiles.length;
	var partGeom;
	var partMesh;

	while(pos<lim){
		partGeom=null;
		partGeom=theSTLFiles[pos];
		if(partGeom===null){
			partGeom=parseStlBinary(fileReaders[pos].Reader.result);
		}

		//console.log(partGeom);

		partMesh=new THREE.Mesh(
				partGeom,
				new THREE.MeshNormalMaterial( )
		);
		parts.push({
			Mesh: partMesh,
			Name: fileReaders[pos].Name
		})
		scene.add(partMesh);

		pos++;
	}

	rdr_renderParts();

}









// Dialates time with the scrolling of the mouse
function rdr_zoomIt(e){

	//zoom=zoom*Math.pow(1.001,e.wheelDelta);
	var theDelta = e.deltaY == 0 ? 0 : ( e.deltaY > 0 ? 1 : -1 );
	zoom+=theDelta*(-1);

}


/**
*
*  Attempts to lock the mouse for camera manupulation
*
* @method rdr_tryMouseLock
* @for renderGlobal
* @return {Void}
*
*/
function rdr_tryMouseLock(){

	var element= document.getElementById("theDisplay");

	element.requestPointerLock = element.requestPointerLock ||
		 element.mozRequestPointerLock ||
		 element.webkitRequestPointerLock;
	// Ask the browser to lock the pointer
	element.requestPointerLock();

}



/**
*
* Adds or Removes event listeners for input meant for camera manipulation.
* Is triggered by a change in the state of the mouse locking or unlocking.
* The mouse locking results in input listeners being added to the webpage,
* whereas the unlocking of the mouse results in the removal of appropriate
* listeners.
*
* @method rdr_lockChange
* @for renderGlobal
*
*
* @param {Event} e The event that is to be applied to the function by event listeners upon
* a change in the state of mouselock
* @return {Void}
*
*
*/
function rdr_lockChange(e){

	var theTarget=document.getElementById("theDisplay");
	if (document.pointerLockElement === theTarget ||
		document.mozPointerLockElement === theTarget ||
		document.webkitPointerLockElement === theTarget) {
		// Pointer was just locked
		// Enable the mousemove listener
		document.addEventListener("mousemove", rdr_mouseMoved, false);
		pointerIsLocked=true;
	}
	else {
		// Pointer was just unlocked
		// Disable the mousemove listener
		document.removeEventListener("mousemove", rdr_mouseMoved, false);
		pointerIsLocked=false;
	}

}



/**
*
* Changes the orientation of the camera based off of the mouse movement
* contained in the supplied mouse movement event. X-axis movement
* corresponds to change in the yaw of the camera whereas Y-axis movement
* corresponds to a change in the pitch of the camera.
*
* @method rdr_mouseMoved
* @for renderGlobal
*
* @param {Event} e The mouse movement event to be supplied to the function by a mouse
* movement event listener on the web page
* @return {Void}
*
*/
function rdr_mouseMoved(e){

	var movementX = e.movementX ||
		  e.mozMovementX        ||
		  e.webkitMovementX     ||
		  0;
	var movementY = e.movementY ||
		  e.mozMovementY        ||
		  e.webkitMovementY     ||
		  0;

	camPitch-=movementY/400;
	if(camPitch> Math.PI/2){
		camPitch= Math.PI/2;
	}
	else if(camPitch< Math.PI/(-2)){
		camPitch= Math.PI/(-2)
	}

	camYaw-=movementX/400;
	if(camPitch> Math.PI){
		camPitch= Math.PI;
	}
	else if(camPitch< Math.PI*(-1)){
		camPitch= Math.PI*(-1);
	}

}



// Changes key press states based off of key presses
/**
*
* Accepts a key press event and, if the key press corresponds to one
* of the keys used for manipulating the view, sets the proper components
* of "inputState" to true.
*
* @method rdr_registerDown
* @for renderGlobal
*
*
* @param {Event} e The key down event to be supplied to the function by a key down event
* listener on the web page
* @return {Void}
*
*/
function rdr_registerDown(e){



	var theKey;
	if (e.which == null) {
		theKey= String.fromCharCode(e.keyCode) // IE
	} else if (e.which!=0 /*&& e.charCode!=0*/) {
		theKey= String.fromCharCode(e.which)   // the rest
	} else {
		return;// special key
	}
	theKey=theKey.toUpperCase();



	if(theKey=='A'){
		inputState.A=true;
	}
	if(theKey=='S'){
		inputState.S=true;
	}
	if(theKey=='D'){
		inputState.D=true;
	}
	if(theKey=='W'){
		inputState.W=true;
	}
	if(theKey==' '){
		inputState.Space=false;
	}
	if(theKey=='Q'){
		inputState.Q=true;
	}
	if(theKey=='E'){
		inputState.E=true;
	}
	if(theKey=='R'){
		inputState.R=true;
	}
	if(theKey=='F'){
		inputState.F=true;
	}
	return;

}




/**
*
* Accepts a key press release and, if the key release corresponds to one
* of the keys used for manipulating the view, sets the proper components
* of "inputState" to false
*
* @method rdr_registerUp
* @for renderGlobal
*
*
* @param {Event} e The key up event to be supplied to the function by a key up event
* listener on the web page
* @return {Void}
*
*/
function rdr_registerUp(e){


	var theKey;
	if (e.which == null) {
		theKey= String.fromCharCode(e.keyCode) // IE
	} else if (e.which!=0 /*&& e.charCode!=0*/) {
		theKey= String.fromCharCode(e.which)   // the rest
	} else {
		return;// special key
	}
	theKey=theKey.toUpperCase();



	if(theKey=='A'){
		inputState.A=false;
	}
	if(theKey=='S'){
		inputState.S=false;
	}
	if(theKey=='D'){
		inputState.D=false;
	}
	if(theKey=='W'){
		inputState.W=false;
	}
	if(theKey==' '){
		inputState.Space=false;
	}
	if(theKey=='Q'){
		inputState.Q=false;
	}
	if(theKey=='E'){
		inputState.E=false;
	}
	if(theKey=='R'){
		inputState.R=false;
	}
	if(theKey=='F'){
		inputState.F=false;
	}
	return;

}


// Affects the state of the camera/animation based off of the state of the inputs
/**
*
* Once called, interprets the current state of registered inputs and manipulates
* the visualization accordingly, including the accelleration of the camera, as
* affected by the W,S,A, and D keys, and the rotation of the camera if the F key
* is depressed and there currently is a highlighted object of interest
*
* @method rdr_manageControls
* @for renderGlobal
* @return {Void}
*
*/
function rdr_manageControls(){

	// Set up rotation and relative position deltas
	var theRot= new THREE.Quaternion(0,0,0,0);
	theRot.setFromEuler(camera.rotation);
	var theDir= new THREE.Vector3(0,0,0);


	//
	if(inputState.A==true){
		theDir.x-=1;
	}
	if(inputState.S==true){
		theDir.z+=1;
	}
	if(inputState.D==true){
		theDir.x+=1;
	}
	if(inputState.W==true){
		theDir.z-=1;
	}
	if(inputState.Space==true && inputState.switchPrimed==true){
		inputState.switchPrimed = false;
		treequenceActive = !treequenceActive;
	}
	if(inputState.Space==false){
		inputState.switchPrimed = true;
	}
	if(inputState.Q==true){
		momentum.y-=1;
	}
	if(inputState.E==true){
		momentum.y+=1;
	}
	if(inputState.R==true){
		theTime=0;
	}

	if(theDir.length()>0.1){

		if(theBoost<boostLim){

			theBoost+=boostInc;

		}
		else{

			theBoost=boostLim;

		}

	}
	else{

		theBoost=1;

	}

	theDir.applyQuaternion(theRot);
	theDir.multiplyScalar(theSpeed*theBoost);

	momentum.x+=theDir.x;
	momentum.y+=theDir.y;
	momentum.z+=theDir.z;

	camera.position.x+=momentum.x;
	camera.position.y+=momentum.y;
	camera.position.z+=momentum.z;




	if(inputState.F==true){
		if(focusPoint==null && objectOfInterest!=null){
			focusPoint=objectOfInterest;
		}
		if(focusPoint!=null){

			camera.lookAt(getPartCenter(focusPoint));
			camPitch=camera.rotation.x;
			camYaw=camera.rotation.y;
		}
	}
	else{
		if(focusPoint!=null){
			focusPoint.Mesh.material= getStdMaterial();
			focusPoint=null;
		}
	}

	if(focusPoint==null){
		camera.rotation.x=camPitch;
		camera.rotation.y=camYaw;
	}


}







/**
*
* Accepts a string and outputs the string of all characters following the final '.' symbol
* in the string. This is used internally to extract file extensions from file names.
*
* @method rdr_grabExtension
* @for renderGlobal
* @param {String} theName The file name to be processed
* @return {String} the extension in the given file name. If no extension is found, the
* 'undefined' value is returned.
*
*/
function rdr_grabExtension(theName){
	return (/[.]/.exec(theName)) ? /[^.]+$/.exec(theName) : undefined;
}

// Returns from the given list of file readers those that have not completed loading
function rdr_whoIsLeft(theReaders){

	var pos=0;
	var lim=fileReaders.length;
	var theList=[];
	while(pos<lim){
		if(theReaders[pos].Reader.readyState!=2){
			theList.push(theReaders[pos].Name);
		}
		pos++;
	}
	console.log(theList);

}




/**
*
* Called internally by "loadParts". Parses the text stored in "theXML" into a tree
* structure composed of nested javascript objects and converts that structure into a
* series of keyframe arrays, each of which are stored alongside their respective
* parts in "partFrames". Additionally, generates the path lines for each subassembly
* and inserts those lines into "scene".
*
* @method rdr_renderParts
* @for renderGlobal
* @return {Void}
*
*/
function rdr_renderParts(){


	theXML = inText;
	// Cuts of the common first characters from all the part names
	cutoffPartNames(parts);

	// Parses in the xml of the treequence
	//console.log(theXML);
	var treeQ = $.parseXML(theXML);
	console.log(treeQ);
	treeQ=grab(treeQ,"AssemblyCandidate");
	//console.log(treeQ);
	treeQ=grab(treeQ,"Sequence");
	//console.log(treeQ);
	treeQ=grab(treeQ,"Subassemblies");
	//console.log(treeQ);
	treeQ=grab(treeQ,"SubAssembly");

	// Turns the treequence into a tree storing the movement data of each subassembly
	console.log(treeQ);
	var moveTree=getMovement(treeQ,0,0,0,new THREE.Vector3(0,0,0),0);
	console.log(moveTree);

	// Cuts off the common first characters of all the part names in the tree
	cutOffNames(moveTree,similarityCutoff(getNameList(moveTree)));
	//console.log(moveTree);
	//printAllNames(parts,moveTree);

	// Makes a series of keyframes for each part for evaluation in the animation
	var theFrameLists=makeKeyFrames(moveTree,[],[]);
	timeAdjustment = addCurveKeyFrames( theFrameLists, new THREE.Vector3 ( 1000,1000,1000 ) );
	//bumpTreeTimes(moveTree,10*timeAdjustment);
	//console.log(theFrameLists);
	//console.log(parts);

	// Links each key frame list object to the appropriate part object
	partFrames= bindPartsToKeyFrames(theFrameLists,parts);
	//console.log(partFrames.length.toString());
	//console.log(partFrames.length.toString());
	//console.log(partFrames);
	//showFrames(theFrameLists);

	// Zeroes the time, for obvious reasons
	theTime=0;

	// Adds the movement trace lines to the scene
	addLines(moveTree,null,scene,false);

	// Stores the movement tree for later use
	movementTree=moveTree;

	// Mirrors the time measurements at each keyfram to turn the dissassembly into
	// an assembly animation
	flipTreeTime(movementTree,getLongestTime(movementTree));
	//console.log(partFrames.length.toString());
	addDisplacement(movementTree, partFrames, 0);

	// Populates the treequence graphic
	document.getElementById("treequenceDiv").classList.add("refBranch");
	insertTreequenceHTML(movementTree,document.getElementById("treequenceDiv"));
	rdr_showHideTreequence();

	// Fixes a minor thing in the treequence graphic
	getChildrenByTag(document.getElementById("treequenceDiv"),"BUTTON")[0].innerHTML="+";
	getChildrenByTag(document.getElementById("treequenceDiv"),"DIV")[0].classList.add("rootNode");
	// Begins to display the parts
	initAxisLines();

	alignAssemblyCenter();

	addGrid(50000,500, -1000, 0x888888);
	addGrid(50000,500, 8000, 0x888888);

	var pos = 0;
	while(pos<100){
		addCylender(200, -1000, 8000, (pos%10)/10*50000-25000, pos/10/10*50000-25000, 8, 12, 0x888888);
		pos++;
	}

	rdr_render();

}




// Toggles the display of the treequence graphic
/**
*
* Toggles the display of the HTML div element containing the treequence representation of
* the assembly.
*
* @method rdr_showHideTreequence
* @for renderGlobal
* @return {Void}
*
*/
function rdr_showHideTreequence(){

	TDiv=document.getElementById("treequenceDiv");
	if(TDiv.state=="shown"){
		TDiv.state="notShown";
		TDiv.classList.remove("shown");
		TDiv.classList.add("hidden");
	}
	else{
		TDiv.state="shown";
		TDiv.classList.remove("hidden");
		TDiv.classList.add("shown");
	}

}



startupScripts["7"] = function(){
	//
	//    Pretty Important: Keep this as true unless/until you've incorperated some other
	//                      method of getting file input/output
	//
	manualFileInput=false;


	if(manualFileInput==true){

		document.getElementById("HUD").innerHTML="<input type='file' id='fileinput' multiple />"+document.getElementById("HUD").innerHTML;

	}
	// Holder for animation frames for parts
	partFrames=null;

	// Sets the time to 0, for the sake of starting the animation at the right time
	theTime=0;


	// Holder for parsed-in javascript objects from the XML document
	theTreequence=null;

	treequenceActive = false;


	timeAdjustment = 0;

	standard = false;


	// Holds the state of button press inputs to smooth out control response



	/**
	*
	* Contains a representation of the last keyboard events reported by the
	* web page for each given key that acts as input for manipulating the
	* visulization: 'W','A','S','D','R','F', and the 'Space' key
	*
	* @element inputState
	* @for renderGlobal
	* @return {Void}
	*
	*/
	inputState={

		W: false,
		A: false,
		S: false,
		D: false,
		R: false,
		F: false,
		Q: false,
		E: false,
		Space: false,
		switchPrimed: false

	}


	// The color of the background of the scene
	skyColor= 0xFFFFFF;

	if(standard){
		skyColor = 0x000000;
	}

	// The tree structure holding animation data
	movementTree=null;
	theCenter= new THREE.Vector3(0,0,0);

	// The part directly in front of the camera, if any such part exists
	objectOfInterest=null;

	// The part being locked onto by using the 'F' key
	focusPoint=null;

	// Name of the part being looked at, if there is any such part
	mouseOverText="";

	// Time dialation coefficeint
	zoom=0.2;

	// Base Accelleration
	theSpeed=0.2;

	// Accelleration bonus variables
	theBoost=1; // Initial accelleration bonus
	boostLim=25; // Limit to accelleration bonus
	boostInc=0.1; // Rate of accelleration bonus increase

	// Coefficient of drag camera experiences
	theDrag=0.96;

	// Angles of camera
	camYaw=0;
	camPitch=Math.PI/2;

	// The momentum of the camera
	momentum= new THREE.Vector3(0,0,0);



	/**update
	*
	* The main portion of the visualization's rendering cycle, managing frame rate,
	* input, camera decelleration, keyframe manipulation, model animation, object highlighting,
	* and informational display.
	*
	* @method render
	* @for renderGlobal
	* @return {Void}
	*
	*/
	rdr_render = function () {

		// The function that will manage frame requests
		requestAnimationFrame( rdr_render );



		// Recieve input and set the appropriate state
		rdr_manageControls();

		// Apply air friction to camera
		momentum.multiplyScalar(theDrag);


		// Moves the parts along the appropriate motions of the animation
		if(zoom>=0){
			theTime=animate(partFrames,theTime,Math.pow(zoom,1.008),treequenceActive);
		}
		else{
			theTime=animate(partFrames,theTime,0-Math.pow(0-zoom,1.008),treequenceActive);
		}


		// Reset the appearence of the last object of interest
		if(objectOfInterest!=null){
			objectOfInterest.Mesh.material=getStdMaterial();
		}

		// Get the first part being directly looked at and sets it as object of interest
		objectOfInterest=getFirstIntersect(scene,camera,partFrames);


		// Change appearance of the object of interest and display the appropriate information
		if(objectOfInterest!==null && standard !== true){

			mouseOverText=" "+objectOfInterest.Name.substring(0,objectOfInterest.Name.length-4);
			objectOfInterest.Mesh.material=new THREE.MeshStandardMaterial({
				color:0xbbbbbb,
				roughness: 1.0,
				metalness: 1.0,
				shading: THREE.SmoothShading
			} );

		}
		else{

			mouseOverText="";

		}


		// Change appearance of the focus point mesh
		if(focusPoint!=null && standard !== true){

			focusPoint.Mesh.material=new THREE.MeshStandardMaterial({
				color:0xff6666,
				roughness: 1.0,
				metalness: 1.0,
				shading: THREE.SmoothShading
			} );

		}


		// Display information about the object of interest
		document.getElementById("mouseoverName").innerHTML="PART: "+mouseOverText;
		document.getElementById("theTime").innerHTML=("TIME: "+ theTime.toFixed(10)).toString();

		// Update the installation trace lines
		updateLines(movementTree,null,theTime-timeAdjustment,false,treequenceActive);

		updateAxisLines();


		// Call for the render
		renderer.render(scene, camera);

	};

	camera.position.x=0;
	camera.position.z=0;
	camera.position.y=0;

	// The variable holding the state of whether or not the pointer is locked
	pointerIsLocked=false;

	clearScene("theDisplay");

	// Setting camera to Yaw-Pitch-Roll configuration
	camera.rotation.reorder('YXZ');


	theXAxis=null;
	theYAxis=null;
	theZAxis=null;
	xRet=null;
	yRet=null;




	// Adding a whole bunch of event listeners for input
	document.getElementById("theDisplay").addEventListener("wheel", rdr_zoomIt);
	document.addEventListener('pointerlockchange', rdr_lockChange, false);
	document.addEventListener('mozpointerlockchange', rdr_lockChange, false);
	document.addEventListener('webkitpointerlockchange', rdr_lockChange, false);
	document.addEventListener('keydown', rdr_registerDown , false);
	document.addEventListener('keyup', rdr_registerUp , false);

	rdr_renderParts();

}

//</script>