Skip to content
Snippets Groups Projects
index.html 43.6 KiB
Newer Older
Xavier Gibert's avatar
Xavier Gibert committed

<!doctype html>
<html lang="en">
<head>
	<title>Sphere</title>
	<meta charset="utf-8">
	<!--<meta name="viewport" content="width=device-width">--><!-- target-densitydpi=device-dpi -->
	<meta name="viewport" content="width=device-width, height=device-height, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
	<link rel=stylesheet href="css/base.css"/>
</head>
<body>

<!--<script src="js/myThree.js"></script>-->
<!--<script src="js/three.r60.js"></script>-->
<script src="js/three.js"></script>
<script src="js/three.ext.js"></script>
<script src="js/mySprites.js"></script>

Xavier Gibert's avatar
Xavier Gibert committed
<script src="js/Detector.js"></script>
<script src="js/Stats.js"></script>
<script src="js/OrbitControls.js"></script>
<script src="js/THREEx.KeyboardState.js"></script>
<script src="js/THREEx.FullScreen.js"></script>
<script src="js/THREEx.WindowResize.js"></script>

<script type='text/javascript' src='js/DAT.GUI.min.js'></script>

<script src="js/shaders/ShaderEngine.js"></script><!-- SC engine plasma -->
<script src="js/shaders/ShaderGlow.js"></script><!-- Sun glow effect -->
<script src="js/shaders/ShaderSun.js"></script><!-- Sun surface -->



<!-- jQuery code to display an information button and box when clicked. -->
<!--<script src="js/jquery-1.9.1.js"></script>
<script src="js/jquery-ui.js"></script>
<link rel=stylesheet href="css/jquery-ui.css" />
<link rel=stylesheet href="css/info.css"/>-->
<!--<script src="js/info.js"></script>-->
<!--<div id="infoButton"></div>
<div id="infoBox" title="Demo Information">
This three.js demo is part of a collection at
<a href="http://stemkoski.github.io/Three.js/">http://stemkoski.github.io/Three.js/</a>
</div>-->
<!-- ------------------------------------------------------------ -->


<script type="text/javascript">
    function showAndroidToast(toast) {
		if (typeof Android != "undefined"){ // check the bridge 
		  if (Android.showToast!= "undefined") { // check the method
			 Android.showToast(toast);
		  }
	   }
    }
	function setLoadingProgress(progress) {// from 0 to 100 
Xavier Gibert's avatar
Xavier Gibert committed
		if (typeof Android != "undefined"){ // check the bridge 
		  if (Android.setProgress!= "undefined") { // check the method
			 Android.setProgress(progress);
		  }
	   }
    }
	function updateFPS(){
		if (typeof Android != "undefined"){ // check the bridge 
		  if (Android.updateFPS!= "undefined") { // check the method
			 Android.updateFPS(stats.domElement.children[0].children[0].textContent);
		  }
		}
	}
	function getInitialization(){
		if (typeof Android != "undefined"){ // check the bridge 
		  if (Android.getInitializationJSON!= "undefined") { // check the method
			 
			var config = JSON.parse(Android.getInitializationJSON());
		
			show_fps = config.show_fps;
			fps_update_skips = config.fps_update_skips;

			show_sky = config.show_sky;
			show_sphere = config.show_sphere;
			//show_mini_spheres = config.show_mini_spheres; //option blocked for robustness (axis labels go clipped there)
Xavier Gibert's avatar
Xavier Gibert committed
			show_circles = config.show_circles;
			show_axis = config.show_axis;
			show_axis_labels = config.show_axis_labels;
			show_planes = config.show_planes;

			//Option blocked for robustness (S/C will show the attitude and a view will follow it)
			//show_spacecraft = config.show_spacecraft;//If set to false, instead of a S/C it will be a miniSphere in the reference position.
Xavier Gibert's avatar
Xavier Gibert committed
			sc_show_eng_texture = config.sc_show_eng_texture;
			
			show_sun = config.show_sun;
			sun_rotates = config.sun_rotates;
			sun_rotation_speed = config.sun_rotation_speed;
			show_sun_texture = config.show_sun_texture;
			sun_simple_glow = config.sun_simple_glow;//Recomended to not use the shader glow, problems in android
			sun_show_line = config.sun_show_line;
			sun_show_dist = config.sun_show_dist;

			show_earth = config.show_earth;
			earth_rotates = config.earth_rotates;
			earth_rotation_speed = config.earth_rotation_speed;
			show_earth_texture = config.show_earth_texture;
			earth_show_line = config.earth_show_line;
			earth_show_dist = config.earth_show_dist;
			
			show_velocity = config.show_velocity;
			color_velocity = config.color_velocity;
			limit_velocity = config.limit_velocity; //Km/s value corresponding to the full length arrow (touching the sphere)
			show_acceleration = config.show_acceleration;
			color_acceleration = config.color_acceleration;
			limit_acceleration = config.limit_acceleration; //Km/s2 value corresponding to the full length arrow (touching the sphere)
			show_momentum = config.show_momentum;
			color_momentum = config.color_momentum;
			show_target_a = config.show_target_a;
			color_target_a = config.color_target_a;
			show_vector_a = config.show_vector_a;
			color_vector_a = config.color_vector_a;
			limit_vector_a = config.limit_vector_a;// In the same units of the provided value
			show_direction_a = config.show_direction_a;
			color_direction_a = config.color_direction_a;

			performance_level = config.performance_level;//1: VeryLow, 2: Low, 3: Normal, 4: High, 5: VeryHigh, 6: Ultra ...;
		  }
	   }
	}
	function canvasMode(){
		canvas_mode = true;//To prevent putting reflective materials
	
		show_sky = false;
		show_sphere = false;
		//show_mini_spheres = true;
Xavier Gibert's avatar
Xavier Gibert committed
		show_circles = true;
		show_axis = true;
		show_axis_labels = true;
		show_planes = false;

		//show_spacecraft = true;//If set to false, instead of a S/C it will be a miniSphere in the reference position.
Xavier Gibert's avatar
Xavier Gibert committed
		sc_show_eng_texture = false;
		
		show_sun = false;
		sun_rotates = false;
		sun_rotation_speed = 0;
		show_sun_texture = false;
		sun_simple_glow = true;//Recomended to not use the shader glow, problems in android
		sun_show_line = false;
		sun_show_dist = false;

		show_earth = false;
		earth_rotates = false;
		earth_rotation_speed = 0;
		show_earth_texture = false;
		earth_show_line = false;
		earth_show_dist = false;
		

		performance_level = 1;//1: VeryLow, 2: Low, 3: Normal, 4: High, 5: VeryHigh, 6: Ultra ...;
		
		// Segments
		segments_scale = performance_level;//Multiply segments of all geometries: 
		sc_body_segments = 4 * segments_scale;
		sc_window_segments = 8 * segments_scale;
		sc_engine_segments = 8 * segments_scale;
		sc_eng_disk_segments = sc_engine_segments;
		sun_seg = 10 * segments_scale;
		earth_seg = 12 * segments_scale;
		sphere_segments = 20 * segments_scale;
		miniSphere_seg = 7 * segments_scale;
		torus_seg_r = 4 * segments_scale;
		torus_seg_t = 32 * segments_scale;
		arrow_segments = 4 * segments_scale;
		momentum_segments = 4 * segments_scale;
		target_segments = 8 * segments_scale;
	}
	function updateModelState(new_state){
		//if (typeof Android != "undefined"){ // check the bridge 
		  //if (Android.getStateJSON!= "undefined") { // check the method
			var state = JSON.parse(new_state);			
Xavier Gibert's avatar
Xavier Gibert committed
			value_sun  = new THREE.Vector3( state.value_sun[0], state.value_sun[1], state.value_sun[2] ); //Km
			value_earth  = new THREE.Vector3( state.value_earth[0], state.value_earth[1], state.value_earth[2] ); //Km
			value_velocity  = new THREE.Vector3( state.value_velocity[0], state.value_velocity[1], state.value_velocity[2] ); //Km/s
			value_acceleration  = new THREE.Vector3( state.value_acceleration[0], state.value_acceleration[1], state.value_acceleration[2] ); //Km/s2
			value_momentum  = new THREE.Vector3( state.value_momentum[0], state.value_momentum[1], state.value_momentum[2] ); // direction --> will be normalized
			value_target_a  = new THREE.Vector3( state.value_target_a[0], state.value_target_a[1], state.value_target_a[2] ); // direction --> will be normalized
			value_vector_a  = new THREE.Vector3( state.value_vector_a[0], state.value_vector_a[1], state.value_vector_a[2] ); // will be normalized by Limit in same units
			value_direction_a  = new THREE.Vector3( state.value_direction_a[0], state.value_direction_a[1], state.value_direction_a[2] ); // direction --> will be normalized
Xavier Gibert's avatar
Xavier Gibert committed
	}
	function getCamDistance(){
		return Math.sqrt(camera.position.x*camera.position.x+camera.position.y*camera.position.y+camera.position.z*camera.position.z);
	}
	function getCamEquilater(){
		return getCamDistance()/Math.sqrt(3);
	}
	function restoreMiniSpheres(){
		if(show_mini_spheres){
			miniSphereX.visible=true;
			miniSphereXX.visible=true;
			miniSphereY.visible=true;
			miniSphereYY.visible=true;
			miniSphereZ.visible=true;
			miniSphereZZ.visible=true;
		}
	}
Xavier Gibert's avatar
Xavier Gibert committed
	function changeView(view_mode){
		restoreMiniSpheres();
Xavier Gibert's avatar
Xavier Gibert committed
		switch(view_mode){
			case "XYZ"://xyz
				camera.position = new THREE.Vector3(getCamEquilater(),getCamEquilater(),getCamEquilater());
Xavier Gibert's avatar
Xavier Gibert committed
				break;
			case "X"://+X
				miniSphereX.visible=false;
				camera.position = new THREE.Vector3(getCamDistance(),0,0);
Xavier Gibert's avatar
Xavier Gibert committed
				break;
			case "-X"://-X
				miniSphereXX.visible=false;
				camera.position = new THREE.Vector3(-getCamDistance(),0,0);
Xavier Gibert's avatar
Xavier Gibert committed
				break;
			case "Y"://+Y
				miniSphereY.visible=false;
				camera.position = new THREE.Vector3(0,getCamDistance(),0);
Xavier Gibert's avatar
Xavier Gibert committed
				break;
			case "-Y"://-Y
				miniSphereYY.visible=false;
				camera.position = new THREE.Vector3(0,-getCamDistance(),0);
Xavier Gibert's avatar
Xavier Gibert committed
				break;
			case "Z"://+Z
				miniSphereZ.visible=false;
				camera.position = new THREE.Vector3(0,0,getCamDistance());
Xavier Gibert's avatar
Xavier Gibert committed
				break;
			case "-Z"://-Z
				miniSphereZZ.visible=false;
				camera.position = new THREE.Vector3(0,0,-getCamDistance());
				break;
			case "Earth"://-Z
				camera.position = new THREE.Vector3(getCamEquilater(),getCamEquilater(),getCamEquilater());
				break;
			case "Sun"://-Z
				camera.position = new THREE.Vector3(getCamEquilater(),getCamEquilater(),getCamEquilater());
Xavier Gibert's avatar
Xavier Gibert committed
				break;
			default://xyz
				camera.position = new THREE.Vector3(getCamEquilater(),getCamEquilater(),getCamEquilater());
Xavier Gibert's avatar
Xavier Gibert committed
				break;
		}
		camera.lookAt(scene.position);
	}
</script>
<!--<input type="button" value="Say hello" onClick="showAndroidToast('Hello Android!')" />-->

<div id="ThreeJS" style="position: absolute; left:0px; top:0px"></div>
<!--<div id="SimulatorTop">TEST</div>
<div id="SimulatorBottom">TEST2</div>-->
<script>
	// MAIN
	//***********************************************************************************************************************
	//		GLOBAL VARIABLES
	//***********************************************************************************************************************
	setLoadingProgress(5);
	var container, scene, camera, renderer, controls, stats, light, sunLight, lineSun, spriteSun, contextSun, contextEarth, lineEarth, spriteEarth;
	var keyboard = new THREEx.KeyboardState();
	var clock = new THREE.Clock();
	var sun, earth, arrow_vel, arrow_accel, arrow_momentum, target_a, vector_a, direction_a;
	var origin = new THREE.Vector3(0,0,0);
	var fontsizeSun, borderColorSun, borderThicknessSun, backgroundColorSun, fontColorSun;
	var fontsizeEarth, borderColorEarth, borderThicknessEarth, backgroundColorEarth, fontColorEarth;
	var fps_update_counter = 0;
	var miniSphereX,miniSphereXX,miniSphereY,miniSphereYY,miniSphereZ,miniSphereZZ;
Xavier Gibert's avatar
Xavier Gibert committed
	var gui, parameters;
	
	//-----------------------------------------------------------------------------------------------------------------------
	//			SCENE PARAMS (Hard-coded parameters)
	//-----------------------------------------------------------------------------------------------------------------------
	var canvas_mode = false;
	var cam_init_pos  = new THREE.Vector3(300,300,300);
	var cam_view_angle = 25;
	var cam_rend_near = 0.1;
	var cam_rend_far = 20000;
	
	var sphere_radius = 100;
	var miniSphere_radius = 5;
	var miniSphere_margin = 4;
	var torus_radius = sphere_radius;
	var torus_tube = 0.5;
	
	var sc_body_color = 0xDDDDDD;
	var sc_window_color = 0x00d4ff;
	var sc_engine_color = 0x545454;
	var sc_eng_solid_color = 0x5d00ff;//For when not using texture

	var sun_radius = 5;
	var sun_solid_color = 0xffb600 ;//For when not using textures
	var sun_obj_dist = sphere_radius + 10;
	
	var earth_radius = 8;
	var earth_solid_color = 0x00bfff ;//For when not using textures
	var earth_obj_dist = sphere_radius + earth_radius;
	
	var arrow_head_length = 9;
	var arrow_head_width = 5;
	var arrow_max_length = sphere_radius;
	var target_head_length = 2;
	var target_head_width = 1;
	var target_length = sphere_radius + target_head_width;
	var momentum_length = sphere_radius/4;
	var momentum_head_length = 8;
	var momentum_head_width = 7;	
		
//-----------------------------------------------------------------------------------------------------------------------
//			PERFORMANCE VALUES (Set at initialization)
//-----------------------------------------------------------------------------------------------------------------------
	
	var show_fps = true;//Show FPS stats in Android
	var fps_update_skips = 60;

	var show_sky = true;
	var show_sphere = true;
Xavier Gibert's avatar
Xavier Gibert committed
	var show_mini_spheres = true;
	var show_circles = true;
	var show_axis = true;
	var show_axis_labels = true;
	var show_planes = true;
	
	var show_spacecraft = true;//If set to false, instead of a S/C it will be a miniSphere in the reference position.
	var sc_show_eng_texture = true;
Xavier Gibert's avatar
Xavier Gibert committed
	
	var show_sun = true;
	var sun_rotates = true;
	var sun_rotation_speed = 5;//Rotation speed multiplier [0->9]
	var show_sun_texture = true;
Xavier Gibert's avatar
Xavier Gibert committed
	var sun_simple_glow = true;//Recomended to not use the shader glow, problems in android
	var sun_show_line = true;
	var sun_show_dist = true;
	
	var show_earth = true;
	var earth_rotates = true;
	var earth_rotation_speed = 2;//Rotation speed multiplier [0->9]
	var show_earth_texture = true;
Xavier Gibert's avatar
Xavier Gibert committed
	var earth_show_line = true;
	var earth_show_dist = true;
	
	var show_velocity = true;
	var color_velocity = 0x001dff;
	var limit_velocity = 15; //Km/s value corresponding to the full length arrow (touching the sphere)
	var show_acceleration = true;
	var color_acceleration = 0xfc00b0;
	var limit_acceleration = 15; //Km/s2 value corresponding to the full length arrow (touching the sphere)
	var show_momentum = true;
	var color_momentum = 0x00fc19;
	var show_target_a = true;
	var color_target_a = 0xff0000;
	var show_vector_a = false;
	var color_vector_a = 0x00fffa;
	var limit_vector_a = 25; //In the same units as the provided values
	var show_direction_a = false;
	var color_direction_a = 0xffff00;
	
	
	var performance_level = 3;//1: VeryLow, 2: Low, 3: Normal, 4: High, 5: VeryHigh, 6: Ultra ...;
	
	getInitialization();//If used in Android, update the init params with the Android configuration
	
	// Segments
	if(performance_level<1)
		performance_level=1;
	var segments_scale = performance_level;//Multiply segments of all geometries: 
	var sc_body_segments = 4 * segments_scale;
	var sc_window_segments = 8 * segments_scale;
	var sc_engine_segments = 8 * segments_scale;
	var sc_eng_disk_segments = sc_engine_segments;
	var sun_seg = 10 * segments_scale;
	var earth_seg = 12 * segments_scale;
	var sphere_segments = 20 * segments_scale;
	var miniSphere_seg = 7 * segments_scale;
	var torus_seg_r = 4 * segments_scale;
	var torus_seg_t = 32 * segments_scale;
	var arrow_segments = 4 * segments_scale;
	var momentum_segments = 4 * segments_scale;
	var target_segments = 8 * segments_scale;
//-----------------------------------------------------------------------------------------------------------------------
//			DYNAMIC VALUES (Updated at each cycle)
//-----------------------------------------------------------------------------------------------------------------------
	
	var value_sun  = new THREE.Vector3(87000000,87000000,87000000); //Km
	var value_earth  = new THREE.Vector3(36000,12000,5); //Km
	var value_velocity  = new THREE.Vector3(0,0,-15); //Km/s
	var value_acceleration  = new THREE.Vector3(-5,0,0); //Km/s2
	var value_momentum  = new THREE.Vector3(-5,0,-5); // direction --> will be normalized
	var value_target_a  = new THREE.Vector3(-5,-5,-5); // direction --> will be normalized
	var value_vector_a  = new THREE.Vector3(-7,-5,-5); // will be normalized with its limit
	var value_direction_a  = new THREE.Vector3(-5,-5,-7); // direction --> will be normalized
	
	
	
	//-----------------------------------------------------------------------------------------------------------------------

	init();
	animate();

// FUNCTIONS 		
function init() 
{
	//***********************************************************************************************************************
	//		SCENE ELEMENTS
	//***********************************************************************************************************************
	setLoadingProgress(15);
	// SCENE
	scene = new THREE.Scene();
	// CAMERA
	var SCREEN_WIDTH = window.innerWidth, SCREEN_HEIGHT = window.innerHeight;
	var VIEW_ANGLE = cam_view_angle, ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT, NEAR = cam_rend_near, FAR = cam_rend_far;
	camera = new THREE.PerspectiveCamera( VIEW_ANGLE, ASPECT, NEAR, FAR);
	scene.add(camera);
	camera.position = cam_init_pos;
	camera.lookAt(scene.position);	
	// RENDERER
	if ( Detector.webgl ){
		renderer = new THREE.WebGLRenderer( {antialias:true} );
	}else{
		renderer = new THREE.CanvasRenderer();
		alert('WebGL not supported in this device');
		canvasMode();
	}
	renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
	container = document.getElementById( 'ThreeJS' );
	container.appendChild( renderer.domElement );
	// EVENTS
	THREEx.WindowResize(renderer, camera);
	THREEx.FullScreen.bindKey({ charCode : 'm'.charCodeAt(0) });
	// CONTROLS
	controls = new THREE.OrbitControls( camera, renderer.domElement );
	// STATS
	stats = new Stats();
	stats.domElement.style.position = 'absolute';
	stats.domElement.style.top = '0px';
	stats.domElement.style.zIndex = 100;
	//stats.domElement.style.webkitTransform = 0;
	//container.appendChild( stats.domElement );
	// LIGHT
	light = new THREE.PointLight(0xE0E0E0);
	//light.position.set(200,200,200);
	scene.add(light);
	
	if(!canvas_mode){
		sunLight = new THREE.PointLight(0xffef7a);
		//sunLight.position.set(200,200,200);
		scene.add(sunLight);
	}
	// ambient
	var ambient = new THREE.AmbientLight( 0xFFFFFF );
	//scene.add( ambient );
	
	
	
	//***********************************************************************************************************************
	//		STATIC ELEMENTS
	//***********************************************************************************************************************
	setLoadingProgress(35);
	
	//-----------------------------------------------------------------------------------------------------------------------
	//			REFERENCE SPHERE
	//-----------------------------------------------------------------------------------------------------------------------
	if(show_sphere){
		var mat_sphere = new THREE.MeshPhongMaterial( { 
			color: 0x282400,
			transparent: true,
			side: THREE.FrontSide,
			metal: true,
			opacity: 0.4,
			} );	
		var mat_sphere2 = new THREE.MeshBasicMaterial( { 
			color: 0xBBBBBB,
			transparent: true,
			side: THREE.FrontSide,
			metal: true,
			opacity: 0.11,
			} );
		var mats_sphere = [mat_sphere, mat_sphere2];
		var sphere = THREE.SceneUtils.createMultiMaterialObject(new THREE.SphereGeometry( sphere_radius, sphere_segments, sphere_segments ), mats_sphere);
		
		
		sphere.position.set( 0, 0, 0 );
		sphere.renderDepth = -0.1;
		scene.add( sphere );
	}
	//-----------------------------------------------------------------------------------------------------------------------
	//			MINI SPHERES
	//-----------------------------------------------------------------------------------------------------------------------
	if(show_mini_spheres){
		if(!canvas_mode)
			var mat_mini = new THREE.MeshPhongMaterial( { color: 0xAAAAAA, metal: true } );
		else
			var mat_mini = new THREE.MeshBasicMaterial( { color: 0xAAAAAA } );
		var miniSphere = new THREE.Mesh(new THREE.SphereGeometry( miniSphere_radius, miniSphere_seg, miniSphere_seg ), mat_mini);
		miniSphere.position.set( 0, 0, 0 );
		if(!show_spacecraft){
			scene.add( miniSphere );
		}
		
		miniSphereX = miniSphere.clone();
		miniSphereX.position.set( sphere_radius+miniSphere_margin, 0, 0 );
		scene.add( miniSphereX );
		miniSphereXX = miniSphere.clone();
		miniSphereXX.position.set( -sphere_radius-miniSphere_margin, 0, 0 );
		scene.add( miniSphereXX );
		miniSphereY = miniSphere.clone();
		miniSphereY.position.set( 0, sphere_radius+miniSphere_margin, 0 );
		scene.add( miniSphereY );
		miniSphereYY = miniSphere.clone();
		miniSphereYY.position.set( 0, -sphere_radius-miniSphere_margin, 0 );
		scene.add( miniSphereYY );
		miniSphereZ = miniSphere.clone();
		miniSphereZ.position.set( 0, 0, sphere_radius+miniSphere_margin);
		scene.add( miniSphereZ );
		miniSphereZZ = miniSphere.clone();
		miniSphereZZ.position.set( 0, 0, -sphere_radius-miniSphere_margin);
		scene.add( miniSphereZZ );
Xavier Gibert's avatar
Xavier Gibert committed
	}
	//-----------------------------------------------------------------------------------------------------------------------
	//			SPACECRAFT
	//-----------------------------------------------------------------------------------------------------------------------
	if(show_spacecraft){
		if(!canvas_mode)
			var sc_material = new THREE.MeshLambertMaterial( { color: sc_body_color, metal: true, shading: THREE.SmoothShading, blending: THREE.AdditiveBlending, vertexColors: THREE.VertexColors } );
		else
			var sc_material = new THREE.MeshBasicMaterial( { color: sc_body_color } );
		var sc_geometry = new THREE.CylinderGeometry( 6, 1, 15, sc_body_segments );
		var sc = new THREE.Mesh( sc_geometry, sc_material );
		sc.position.set( 0, 0, 0 );
		sc.rotation.x = -Math.PI/2;
		scene.add( sc );
		
		if(!canvas_mode)
			var mat_window = new THREE.MeshPhongMaterial( { color: sc_window_color, metal: true, side: THREE.FrontSide } );
		else
			var mat_window = new THREE.MeshBasicMaterial( { color: sc_window_color, side: THREE.FrontSide } );
		var sc_window = new THREE.Mesh(new THREE.SphereGeometry( 3, sc_window_segments, sc_window_segments ), mat_window);
		sc_window.position.set( 0, 1.5, -2 );
		scene.add( sc_window );
		
		var eng_geometry = new THREE.CylinderGeometry( 2, 2.5, 2, sc_engine_segments );
		if(!canvas_mode)
			var eng_material = new THREE.MeshPhongMaterial( { color: sc_engine_color, metal: true, side: THREE.FrontSide } );
		else
			var eng_material = new THREE.MeshBasicMaterial( { color: sc_engine_color, side: THREE.FrontSide } );
		var eng = new THREE.Mesh( eng_geometry, eng_material );
		eng.rotation.x = -Math.PI/2;
		eng.position.set( -2.5, 0, -8 );
		scene.add( eng );
		
		var eng2 = eng.clone();
		eng2.rotation.x = -Math.PI/2;
		eng2.position.set( 2.5, 0, -8 );
		scene.add( eng2 );
		
		if (sc_show_eng_texture){
			var noiseTexture = new THREE.ImageUtils.loadTexture( 'textures/lava/cloud.png' );
			noiseTexture.wrapS = noiseTexture.wrapT = THREE.RepeatWrapping;	
			var waterTexture = new THREE.ImageUtils.loadTexture( 'textures/water/engine.jpg' );
			waterTexture.wrapS = waterTexture.wrapT = THREE.RepeatWrapping; 
			// use "this." to create global object
			this.customUniforms2 = {
				baseTexture: 	{ type: "t", value: waterTexture },
				baseSpeed: 		{ type: "f", value: 1.15 },
				noiseTexture: 	{ type: "t", value: noiseTexture },
				noiseScale:		{ type: "f", value: 0.5 },
				alpha: 			{ type: "f", value: 0.8 },
				time: 			{ type: "f", value: 1.0 }
			};

			// create custom material from the shader code above
			//   that is within specially labeled script tags
			var customMaterial2 = new THREE.ShaderMaterial( 
			{
				uniforms: customUniforms2,
				vertexShader:   THREE.ShaderEngine.vertexShader,
				fragmentShader: THREE.ShaderEngine.fragmentShader
			}   );
		 
			// other material properties
			
			//customMaterial2.transparent = true;
		}else{
			if(!canvas_mode)
				var customMaterial2 = new THREE.MeshPhongMaterial( { color: sc_eng_solid_color, metal: true } );
			else
				var customMaterial2 = new THREE.MeshBasicMaterial( { color: sc_eng_solid_color } );
		}
		customMaterial2.side = THREE.BackSide;
		// apply the material to a surface    innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength)
		var flatGeometry = new THREE.RingGeometry( 0.5, 2, 15 );
		var surface = new THREE.Mesh( flatGeometry, customMaterial2 );
		//surface.rotation.z = -Math.PI/2;
		surface.position.set( 2.5, 0, -9.1 );
		scene.add( surface );
		var engine_surface2 = surface.clone(); 
		engine_surface2.position.set( -2.5, 0, -9.1 );
		scene.add( engine_surface2 );
	}
	//-----------------------------------------------------------------------------------------------------------------------
	//			SPHERE CIRCLES
	//-----------------------------------------------------------------------------------------------------------------------
	if(show_circles){
		if(!canvas_mode)
			var mat_torus = new THREE.MeshPhongMaterial( { color: 0xAAAAAA, metal: true, transparent: false, opacity: 1.0, side: THREE.BackSide } );
		else
			var mat_torus = new THREE.MeshBasicMaterial( { color: 0xAAAAAA,  side: THREE.BackSide } );
	
		var sphere_y = new THREE.Mesh( new THREE.TorusGeometry( torus_radius, torus_tube, torus_seg_r, torus_seg_t ), mat_torus );
		sphere_y.position.set( 0, 0, 0 );
		scene.add( sphere_y );
		
		var sphere_z = new THREE.Mesh( new THREE.TorusGeometry( torus_radius, torus_tube, torus_seg_r, torus_seg_t ), mat_torus );
		sphere_z.position.set( 0, 0, 0 );
		sphere_z.rotation.x = Math.PI/2;
		scene.add( sphere_z );
		
		var sphere_x = new THREE.Mesh( new THREE.TorusGeometry( torus_radius, torus_tube, torus_seg_r, torus_seg_t ), mat_torus );
		sphere_x.position.set( 0, 0, 0 );
		sphere_x.rotation.y = Math.PI/2;
		scene.add( sphere_x );
	}
	//-----------------------------------------------------------------------------------------------------------------------
	//			REFERENCE AXIS
	//-----------------------------------------------------------------------------------------------------------------------
	if(show_axis){
		var axis = new THREE.AxisHelper( sphere_radius );
		axis.position.set( 0, 0, 0 );
		scene.add( axis );
	}
	if(show_axis_labels){
		var sprite_X = makeTextSprite( 0, " X ", 
		{ fontsize: 48, borderColor: {r:0, g:0, b:0, a:1.0}, borderThickness: 1, backgroundColor: {r:0, g:0, b:0, a:0.5}, fontColor: {r:255, g:174, b:0, a:1.0} } );
		miniSphereX.add( sprite_X );
Xavier Gibert's avatar
Xavier Gibert committed
		
		var sprite_X = makeTextSprite( 0, " Y ", 
		{ fontsize: 48, borderColor: {r:0, g:0, b:0, a:1.0}, borderThickness: 1, backgroundColor: {r:0, g:0, b:0, a:0.5}, fontColor: {r:16, g:219, b:2, a:1.0} } );
		miniSphereY.add( sprite_X );
Xavier Gibert's avatar
Xavier Gibert committed
		
		var sprite_Z = makeTextSprite( 0, " Z ", 
		{ fontsize: 48, borderColor: {r:0, g:0, b:0, a:1.0}, borderThickness: 1, backgroundColor: {r:0, g:0, b:0, a:0.5}, fontColor: {r:50, g:119, b:255, a:1.0} } );
		miniSphereZ.add( sprite_Z );
Xavier Gibert's avatar
Xavier Gibert committed
	}
	//-----------------------------------------------------------------------------------------------------------------------
	//			REFERENCE PLANES
	//-----------------------------------------------------------------------------------------------------------------------
	
	// IMPLEMENT !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
	
	//-----------------------------------------------------------------------------------------------------------------------
	//			SKY
	//-----------------------------------------------------------------------------------------------------------------------
	
	if(show_sky){
		// create the geometry sphere
		var sky_geometry  = new THREE.SphereGeometry(1000, 32, 32);
		// create the material, using a texture of startfield
		var sky_material  = new THREE.MeshBasicMaterial();
		sky_material.map   = THREE.ImageUtils.loadTexture('textures/sky/stars.jpg');
		sky_material.map.wrapS = sky_material.map.wrapT = THREE.RepeatWrapping;
		sky_material.map.repeat.set( 8, 8 ); 
		sky_material.side  = THREE.BackSide;
		// create the mesh based on geometry and material
		var sky_mesh  = new THREE.Mesh(sky_geometry, sky_material);
		scene.add(sky_mesh);
	}
	
	//***********************************************************************************************************************
	//		DYNAMIC ELEMENTS
	//***********************************************************************************************************************
	setLoadingProgress(65);
	//-----------------------------------------------------------------------------------------------------------------------
	//			ARROWS
	//-----------------------------------------------------------------------------------------------------------------------
	
	// ARROWS
	var direction;
	
	// BASIC
	if(show_velocity){
		direction = new THREE.Vector3().subVectors(value_velocity, origin).normalize();		
		arrow_vel = new THREE.ArrowHelper(direction, origin, arrow_max_length, color_velocity, arrow_head_length, arrow_head_width, arrow_segments, canvas_mode);
		scene.add(arrow_vel);
	}
	
	if(show_acceleration){
		direction = new THREE.Vector3().subVectors(value_acceleration, origin).normalize();
		arrow_accel = new THREE.ArrowHelper(direction, origin, arrow_max_length, color_acceleration, arrow_head_length, arrow_head_width, arrow_segments, canvas_mode);
		scene.add(arrow_accel);
	}
	
	if(show_momentum){
		direction = new THREE.Vector3().subVectors(value_momentum, origin).normalize();
		arrow_momentum = new THREE.MomentumHelper(direction, origin, momentum_length, color_momentum, momentum_head_length, momentum_head_width, momentum_segments, canvas_mode);
		scene.add(arrow_momentum);
	}
	
	// EXTRA
	if(show_target_a){
		direction = new THREE.Vector3().subVectors(value_target_a, origin).normalize();
		target_a = new THREE.TargetHelper(direction, origin, target_length, color_target_a, target_head_length, target_head_width, target_segments, canvas_mode);
		scene.add(target_a);
	}
	
	if(show_vector_a){
		direction = new THREE.Vector3().subVectors(value_vector_a, origin).normalize();
		vector_a = new THREE.ArrowHelper(direction, origin, arrow_max_length, color_vector_a, arrow_head_length, arrow_head_width, arrow_segments, canvas_mode);
		scene.add(vector_a);
	}
	
	if(show_direction_a){
		direction = new THREE.Vector3().subVectors(value_direction_a, origin).normalize();
		direction_a = new THREE.MomentumHelper(direction, origin, momentum_length, color_direction_a, momentum_head_length, momentum_head_width, momentum_segments, canvas_mode);
		scene.add(direction_a);
	}
	
	//-----------------------------------------------------------------------------------------------------------------------
	//			SUN
	//-----------------------------------------------------------------------------------------------------------------------
	setLoadingProgress(75);
	if(show_sun){
		if(show_sun_texture){
			// base image texture for mesh
			var lavaTexture = new THREE.ImageUtils.loadTexture( 'textures/lava/lava.jpg');
			lavaTexture.wrapS = lavaTexture.wrapT = THREE.RepeatWrapping; 
			// multiplier for distortion speed 		
			var baseSpeed = 0.02;
			// number of times to repeat texture in each direction
			var repeatS = repeatT = 2.0;
			// texture used to generate "randomness", distort all other textures
			var noiseTexture = new THREE.ImageUtils.loadTexture( 'textures/lava/cloud.png' );
			noiseTexture.wrapS = noiseTexture.wrapT = THREE.RepeatWrapping; 
			// magnitude of noise effect
			var noiseScale = 0.5;
			// texture to additively blend with base image texture
			var blendTexture = new THREE.ImageUtils.loadTexture( 'textures/lava/lava.jpg' );
			blendTexture.wrapS = blendTexture.wrapT = THREE.RepeatWrapping; 
			// multiplier for distortion speed 
			var blendSpeed = 0.08;
			// adjust lightness/darkness of blended texture
			var blendOffset = 0.45;
			// texture to determine normal displacement
			var bumpTexture = noiseTexture;
			bumpTexture.wrapS = bumpTexture.wrapT = THREE.RepeatWrapping; 
			// multiplier for distortion speed 		
			var bumpSpeed   = 0.5;
			// magnitude of normal displacement
			var bumpScale   = 2.0;
			
			// use "this." to create global object
			this.customUniforms = {
				baseTexture: 	{ type: "t", value: lavaTexture },
				baseSpeed:		{ type: "f", value: baseSpeed },
				repeatS:		{ type: "f", value: repeatS },
				repeatT:		{ type: "f", value: repeatT },
				noiseTexture:	{ type: "t", value: noiseTexture },
				noiseScale:		{ type: "f", value: noiseScale },
				blendTexture:	{ type: "t", value: blendTexture },
				blendSpeed: 	{ type: "f", value: blendSpeed },
				blendOffset: 	{ type: "f", value: blendOffset },
				bumpTexture:	{ type: "t", value: bumpTexture },
				bumpSpeed: 		{ type: "f", value: bumpSpeed },
				bumpScale: 		{ type: "f", value: bumpScale },
				alpha: 			{ type: "f", value: 1.0 },
				time: 			{ type: "f", value: 1.0 }
			};
			
			// create custom material from the shader code above
			//   that is within specially labeled script tags
			var customMaterialSun = new THREE.ShaderMaterial( 
			{
				uniforms: customUniforms,
				vertexShader:   THREE.ShaderSun.vertexShader,
				fragmentShader: THREE.ShaderSun.fragmentShader
			}   );
		}else{//Not using texture, solid color instead
			var customMaterialSun = new THREE.MeshPhongMaterial( { color: sun_solid_color, metal: true } );
		}
		
		var sunGeometry = new THREE.SphereGeometry( sun_radius, sun_seg, sun_seg );
		sun = new THREE.Mesh(	sunGeometry, customMaterialSun );
		sun.position.set(0, 85, 85);//Don't remove or the dashed material is not created
		scene.add( sun );
		
		if(!sun_simple_glow){
			// SHADER GLOW EFFECT
			var customMaterialGlow = new THREE.ShaderMaterial( 
			{
				uniforms: 
				{ 
					"c":   { type: "f", value: 0.1 },
					"p":   { type: "f", value: 3.4 },
					glowColor: { type: "c", value: new THREE.Color(0xffff00) },
					viewVector: { type: "v3", value: camera.position }
				},
				vertexShader:   THREE.ShaderGlow.vertexShader,
				fragmentShader: THREE.ShaderGlow.fragmentShader,
				side: THREE.FrontSide,
				blending: THREE.AdditiveBlending,
				transparent: true
			}   );
				
			this.moonGlow = new THREE.Mesh( sunGeometry.clone(), customMaterialGlow.clone() );
			
			moonGlow.position = sun.position;
			moonGlow.scale.multiplyScalar(1.8);
			scene.add( moonGlow );
		}else{
			// SUPER SIMPLE GLOW EFFECT
			// use sprite because it appears the same from all angles
			var spriteMaterial = new THREE.SpriteMaterial( 
			{ 
				map: new THREE.ImageUtils.loadTexture( 'textures/lava/glow.png' ), 
				useScreenCoordinates: false,// alignment: THREE.SpriteAlignment.center,
				color: 0xf79216, transparent: false, blending: THREE.AdditiveBlending
			});
			var sprite = new THREE.Sprite( spriteMaterial );
			sprite.scale.set(20, 20, 1.0);
			sun.add(sprite); // this centers the glow at the mesh
		}
		
		if(sun_show_line){
			// SUN LINE
			var lineGeometrySun = new THREE.Geometry();
			lineGeometrySun.dynamic = true;
			var vertArraySun = lineGeometrySun.vertices;
			vertArraySun.push( new THREE.Vector3(sun.position.x,sun.position.y,sun.position.z), new THREE.Vector3(0, 0, 0) );
			lineGeometrySun.computeLineDistances();
			var lineMaterialSun = new THREE.LineDashedMaterial( { color: 0xffd800, dashSize: 2, gapSize: 2 } );
			lineSun = new THREE.Line( lineGeometrySun, lineMaterialSun );
			scene.add(lineSun);
		}
		
		if(sun_show_dist){
			// Sun Sprite
			spriteSun = makeTextSprite( 1, " 1.05 AU ", 
				{ fontsize: 24, borderColor: {r:255, g:255, b:255, a:1.0}, borderThickness: 1, backgroundColor: {r:0, g:0, b:0, a:1.5}, fontColor: {r:255, g:255, b:255, a:1.0} } );
			sun.add( spriteSun );
		}
	}
	
	//-----------------------------------------------------------------------------------------------------------------------
	//			EARTH
	//-----------------------------------------------------------------------------------------------------------------------
	setLoadingProgress(85);
	// EARTH
	if(show_earth){
		var earth_geometry = new THREE.SphereGeometry( earth_radius, earth_seg, earth_seg ) ;
		if(show_earth_texture){	 
			var earth_material = new THREE.MeshBasicMaterial( { map: THREE.ImageUtils.loadTexture( 'textures/earth/Land_ocean_ice_cloud_2048.jpg' ), overdraw: true } )
		}else{
			var earth_material = new THREE.MeshPhongMaterial( { color: earth_solid_color, metal: true } );
		}
		earth = new THREE.Mesh( earth_geometry, earth_material ) ;
		earth.position.set(75, 0, 75);//Don't remove or the dashed material is not created
		scene.add( earth );
		
		if(earth_show_line){
			// EARTH LINE
			var lineGeometryEarth = new THREE.Geometry();
			var vertArrayEarth = lineGeometryEarth.vertices;
			vertArrayEarth.push( new THREE.Vector3(earth.position.x,earth.position.y,earth.position.z), new THREE.Vector3(0, 0, 0) );
			lineGeometryEarth.computeLineDistances();
			var lineMaterialEarth = new THREE.LineDashedMaterial( { color: 0x0099ff, dashSize: 2, gapSize: 2 } );
			lineEarth = new THREE.Line( lineGeometryEarth, lineMaterialEarth );
			scene.add(lineEarth);
		}
		if(earth_show_dist){
			// Earth Sprite
			spriteEarth = makeTextSprite( 2, " 36150 Km ", 
				{ fontsize: 20, borderColor: {r:255, g:255, b:255, a:1.0}, borderThickness: 1, backgroundColor: {r:0, g:0, b:0, a:0.5}, fontColor: {r:255, g:255, b:255, a:1.0} } );
			earth.add( spriteEarth );
		}
	}
	setLoadingProgress(100);
}

function animate() 
{
    	requestAnimationFrame( animate );
Xavier Gibert's avatar
Xavier Gibert committed
	render();		
	update();
}

function update()
Xavier Gibert's avatar
Xavier Gibert committed
	light.position.set(camera.position.x,camera.position.y,camera.position.z);
	if ( keyboard.pressed("z") ) 
	{ 
		// do something
	}
	var delta = clock.getDelta();
	
	if(show_spacecraft && sc_show_eng_texture){
		customUniforms2.time.value += delta;
	}
	controls.update();
	
	//-----------------------------------------------------------------------------------------------------------------------
	//			ANDROID STATS UPDATE
	//-----------------------------------------------------------------------------------------------------------------------
	if(show_fps){
		stats.update();
		fps_update_counter=fps_update_counter+1;
		if(fps_update_counter>fps_update_skips){
			fps_update_counter=0;	
			updateFPS();
		}
	}
	//-----------------------------------------------------------------------------------------------------------------------
	//			SUN UPDATE
	//-----------------------------------------------------------------------------------------------------------------------
	if(show_sun){
		if(show_sun_texture){
			customUniforms.time.value += delta;
		}
		var sun_obj_pos = value_sun.clone().normalize().multiplyScalar(sun_obj_dist);
		sun.position = sun_obj_pos;
		// change the direction this spotlight is facing
		sunLight.position.set(sun.position.x,sun.position.y,sun.position.z);
		if(sun_show_line){
			// SUN LINE
			lineSun.geometry.vertices[0] = new THREE.Vector3(sun.position.x,sun.position.y,sun.position.z);
			lineSun.geometry.computeLineDistances();
			lineSun.geometry.verticesNeedUpdate = true;
			//lineSun.material.attributes.lineDistances.needsUpdate = true;
		}
		if(sun_show_dist){
			var sun_label_distance = value_sun.length()/149597871;//convert Km to AU
			var messageSun = " "+parseFloat(Math.round(sun_label_distance * 1000) / 1000).toFixed(3)+" AU ";
			contextSun.fillStyle = "rgba(0, 0, 0, 1.0)"; // CLEAR WITH COLOR BLACK (new BG color)
			contextSun.fill(); // FILL THE CONTEXT
			// get size data (height depends only on font size)
			var metrics = contextSun.measureText( messageSun );
			var textWidthSun = metrics.width;
			// background color
			contextSun.fillStyle   = "rgba(" + backgroundColorSun.r + "," + backgroundColorSun.g + ","
										  + backgroundColorSun.b + "," + backgroundColorSun.a + ")";
			// border color
			contextSun.strokeStyle = "rgba(" + borderColorSun.r + "," + borderColorSun.g + ","
										  + borderColorSun.b + "," + borderColorSun.a + ")";
			contextSun.lineWidth = borderThicknessSun;
			roundRect(contextSun, borderThicknessSun/2, borderThicknessSun/2, textWidthSun + borderThicknessSun, fontsizeSun * 1.4 + borderThicknessSun, 6);
			// 1.4 is extra height factor for text below baseline: g,j,p,q.
			// text color
			contextSun.fillStyle   = "rgba(" + fontColorSun.r + "," + fontColorSun.g + ","
										  + fontColorSun.b + "," + fontColorSun.a + ")";
			contextSun.fillText( messageSun, borderThicknessSun, fontsizeSun + borderThicknessSun);
			spriteSun.material.map._needsUpdate = true; // AND UPDATE THE IMAGE..
		}
		if(!sun_simple_glow){
			moonGlow.material.uniforms.viewVector.value = 
				new THREE.Vector3().subVectors( camera.position, moonGlow.position );
		}
		if(sun_rotates){
			//sun.rotation.x += 0.005;
			sun.rotation.y += 0.001*sun_rotation_speed;
		}
	}
	//-----------------------------------------------------------------------------------------------------------------------
	//			EARTH UPDATE
	//-----------------------------------------------------------------------------------------------------------------------
	if(show_earth){
		var earth_obj_pos = value_earth.clone().normalize().multiplyScalar(earth_obj_dist);
		earth.position = earth_obj_pos;
		//XGGDEBUG: maybe it does not need to update the line after updating the object position since it is link to its coordinates.
		if(earth_show_line){
			// EARTH LINE
			lineEarth.geometry.vertices[0].set(earth.position.x,earth.position.y,earth.position.z);
			lineEarth.geometry.computeLineDistances();
			lineEarth.geometry.verticesNeedUpdate = true;
			//lineEarth.material.attributes.lineDistances.needsUpdate = true;
		}
		if(earth_show_dist){
			var earth_label_distance = value_earth.length();//Km
			var messageEarth = " "+parseFloat(Math.round(earth_label_distance * 1) / 1).toFixed(0)+" Km ";
			contextEarth.fillStyle = "rgba(0, 0, 0, 1.0)"; // CLEAR WITH COLOR BLACK (new BG color)
			contextEarth.fill(); // FILL THE CONTEXT
			// get size data (height depends only on font size)
			var metricsEarth = contextEarth.measureText( messageEarth );
			var textWidthEarth = metricsEarth.width;
			// background color
			contextEarth.fillStyle   = "rgba(" + backgroundColorEarth.r + "," + backgroundColorEarth.g + ","
										  + backgroundColorEarth.b + "," + backgroundColorEarth.a + ")";
			// border color
			contextEarth.strokeStyle = "rgba(" + borderColorEarth.r + "," + borderColorEarth.g + ","
										  + borderColorEarth.b + "," + borderColorEarth.a + ")";
			contextEarth.lineWidth = borderThicknessEarth;
			roundRect(contextEarth, borderThicknessEarth/2, borderThicknessEarth/2, textWidthEarth + borderThicknessEarth, fontsizeEarth * 1.4 + borderThicknessEarth, 6);
			// 1.4 is extra height factor for text below baseline: g,j,p,q.
			// text color
			contextEarth.fillStyle   = "rgba(" + fontColorEarth.r + "," + fontColorEarth.g + ","
										  + fontColorEarth.b + "," + fontColorEarth.a + ")";
			contextEarth.fillText( messageEarth, borderThicknessEarth, fontsizeEarth + borderThicknessEarth);
			spriteEarth.material.map._needsUpdate = true; // AND UPDATE THE IMAGE..
		}