Skip to content
Snippets Groups Projects
index.html 46.3 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/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 -->

<script type="text/javascript" src="js/mySprites.js"></script>


<!-- 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 (will fill the progress bar from 50% to 100%)
		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;
			show_circles = config.show_circles;
			show_axis = config.show_axis;
			show_axis_labels = config.show_axis_labels;
			show_planes = config.show_planes;

			show_spacecraft = config.show_spacecraft;//If set to false, instead of a S/C it will be a miniSphere in the reference position.
			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;
		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.
		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 updateState(){
		if (typeof Android != "undefined"){ // check the bridge 
		  if (Android.getStateJSON!= "undefined") { // check the method
			var state = JSON.parse(Android.getStateJSON());
			
			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
		  }
	   }
	}
	function changeView(view_mode){
		switch(view_mode){
			case 0://xyz
				camera.position = new THREE.Vector3(300,300,300);
				break;
			case 1://+X
				camera.position = new THREE.Vector3(519,0,0);
				break;
			case 2://-X
				camera.position = new THREE.Vector3(-519,0,0);
				break;
			case 3://+Y
				camera.position = new THREE.Vector3(0,519,0);
				break;
			case 4://-Y
				camera.position = new THREE.Vector3(0,-519,0);
				break;
			case 5://+Z
				camera.position = new THREE.Vector3(0,0,519);
				break;
			case 6://-Z
				camera.position = new THREE.Vector3(0,0,-519);
				break;
			default://xyz
				camera.position = new THREE.Vector3(300,300,300);
				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 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
305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000
	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 SCREEN_WIDTH = document.body.clientWidth, SCREEN_HEIGHT = document.body.clientHeight;
	//var SCREEN_WIDTH = screen.width, SCREEN_HEIGHT = screen.height / window.devicePixelRatio - window.screenTop;
	//showAndroidToast(SCREEN_WIDTH+"-"+SCREEN_HEIGHT);
	/*var width = screen.height;
	var height = screen.width;
	var screenRatio;
	var realWidth;
	var realHeight;
	if(width>height){realWidth=width;realHeight=height;screenRatio=(height/width);}
	else{realWidth=height;realHeight=width;screenRatio=(width/height);}
	if(isNaN(screenRatio)){
 
	if(window.innerHeight>window.innerWidth){realWidth=window.innerHeight; realHeight= window.innerWidth ;screenRatio = (window.innerWidth/window.innerHeight);}
	else{realWidth=window.innerWidth; realHeight= window.innerHeight;screenRatio = (window.innerHeight/window.innerWidth);}
	}
	SCREEN_WIDTH = realWidth;
	SCREEN_HEIGHT = realHeight;*/
	/*var SCREEN_MIN, SCREEN_EXTRA = 120;
	if(SCREEN_HEIGHT>SCREEN_WIDTH)
		SCREEN_MIN = SCREEN_WIDTH;
	else
		SCREEN_MIN = SCREEN_HEIGHT;*///android:screenOrientation="portrait"
	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} );
		//alert('WebGL compatible!');
	}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 );
	
	// FLOOR
	/*var floorTexture = new THREE.ImageUtils.loadTexture( 'images/checkerboard.jpg' );
	floorTexture.wrapS = floorTexture.wrapT = THREE.RepeatWrapping; 
	floorTexture.repeat.set( 10, 10 );
	var floorMaterial = new THREE.MeshBasicMaterial( { map: floorTexture, side: THREE.DoubleSide } );
	var floorGeometry = new THREE.PlaneGeometry(1000, 1000, 10, 10);
	var floor = new THREE.Mesh(floorGeometry, floorMaterial);
	floor.position.y = -0.5;
	floor.rotation.x = Math.PI / 2;
	scene.add(floor);*/
	// SKYBOX/FOG
	//scene.fog = new THREE.FogExp2( 0x9999ff, 0.00025 );
	
	// GUI
	/*gui = new dat.GUI();
	
	parameters = 
	{
		x: 0, y: 30, z: 0,
		color: "#ff0000", // color (change "#" to "0x")
		opacity: 1, 
		visible: true,
		material: "Phong",
		reset: function() { resetCube() }
	};

	var folder1 = gui.addFolder('Position');
	var cubeX = folder1.add( parameters, 'x' ).min(-200).max(200).step(1).listen();
	var cubeY = folder1.add( parameters, 'y' ).min(0).max(100).step(1).listen();
	var cubeZ = folder1.add( parameters, 'z' ).min(-200).max(200).step(1).listen();
	folder1.open();
	
	cubeX.onChange(function(value) 
	{   cube.position.x = value;   });
	cubeY.onChange(function(value) 
	{   cube.position.y = value;   });
	cubeZ.onChange(function(value) 
	{   cube.position.z = value;   });
	
	var cubeColor = gui.addColor( parameters, 'color' ).name('Color').listen();
	cubeColor.onChange(function(value) // onFinishChange
	{   cube.material.color.setHex( value.replace("#", "0x") );   });
	
	var cubeOpacity = gui.add( parameters, 'opacity' ).min(0).max(1).step(0.01).name('Opacity').listen();
	cubeOpacity.onChange(function(value)
	{   cube.material.opacity = value;   });
	
	var cubeMaterial = gui.add( parameters, 'material', [ "Basic", "Lambert", "Phong", "Wireframe" ] ).name('Material Type').listen();
	cubeMaterial.onChange(function(value) 
	{   updateCube();   });
	
	var cubeVisible = gui.add( parameters, 'visible' ).name('Visible?').listen();
	cubeVisible.onChange(function(value) 
	{   cube.visible = value;  	});
	
	gui.add( parameters, 'reset' ).name("Reset Cube Parameters");
	
	gui.open();
	*/
	
	//***********************************************************************************************************************
	//		STATIC ELEMENTS
	//***********************************************************************************************************************
	setLoadingProgress(35);
	/*
	var sprite_view = makeTextSprite( 3, " +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} } );
	sprite_view.position.set( window.innerWidth - 50, window.innerWidth - 50, 0 );
	//sprite_view.position.set( 50, 50, 0 );
	//sprite_view.scale.set( 64, 64, 1.0 ); // imageWidth, imageHeight	
	scene.add( sprite_view );
	*/	
	
	//-----------------------------------------------------------------------------------------------------------------------
	//			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 );
		}
		
		var miniSphereA = miniSphere.clone();
		miniSphereA.position.set( sphere_radius+miniSphere_margin, 0, 0 );
		scene.add( miniSphereA );
		
		var miniSphereB = miniSphere.clone();
		miniSphereB.position.set( -sphere_radius-miniSphere_margin, 0, 0 );
		scene.add( miniSphereB );
		
		var miniSphereC = miniSphere.clone();
		miniSphereC.position.set( 0, sphere_radius+miniSphere_margin, 0 );
		scene.add( miniSphereC );
		
		var miniSphereD = miniSphere.clone();
		miniSphereD.position.set( 0, -sphere_radius-miniSphere_margin, 0 );
		scene.add( miniSphereD );
		
		var miniSphereE = miniSphere.clone();
		miniSphereE.position.set( 0, 0, sphere_radius+miniSphere_margin);
		scene.add( miniSphereE );
		
		var miniSphereF = miniSphere.clone();
		miniSphereF.position.set( 0, 0, -sphere_radius-miniSphere_margin);
		scene.add( miniSphereF );
	}
	//-----------------------------------------------------------------------------------------------------------------------
	//			SPACECRAFT
	//-----------------------------------------------------------------------------------------------------------------------
	if(show_spacecraft){
		/*var sc_materials = [
					new THREE.MeshLambertMaterial( { color: sc_body_color, metal: true, shading: THREE.SmoothShading, blending: THREE.AdditiveBlending, vertexColors: THREE.VertexColors } ),
					new THREE.MeshBasicMaterial( { color: 0x000000, shading: THREE.SmoothShading, wireframe: true, transparent: true } )
		];*/
		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 = THREE.SceneUtils.createMultiMaterialObject( sc_geometry, sc_materials );
		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} } );
		miniSphereA.add( sprite_X );
		
		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} } );
		miniSphereC.add( sprite_X );
		
		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} } );
		miniSphereE.add( sprite_Z );
	}
	//-----------------------------------------------------------------------------------------------------------------------
	//			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 );
	render();		
	update();
}

function update()
{
	updateState();	
	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)